zoukankan      html  css  js  c++  java
  • 【备档】客户端自动化(主Android Appium + python

    之前做分享写的文档,备档~

    0.移动客户端自动化简介

    客户端自动化测试的本质

    定位对象 · 操作对象 · 校验对象

    对象的定位应该是自动化测试的核心,要想操作、校验一个对象,首先应该识别这个对象。

    一个对象具有特定的属性,譬如:文字、类型、位置等等。我们可以通过这些属性找到这对象。

    移动客户端自动化测试常见框架

    Android

    1. Monkey
    2. Monkeyrunner
    3. UIautomator
    4. Robotium

    iOS

    1. UIAutomation

    通用

    1. Appium
    2. Calabash
      ...

    框架选择

    1. 支持平台,系统版本
    2. 是否需要源码
    3. 脚本语言
    4. 是否支持webview
      ...

    浅谈移动端自动化测试框架和工具

    http://blog.csdn.net/meyoung01/article/details/40076511

    iOS自动化测试框架对比

    http://www.jianshu.com/p/047035416095

    1.Appium 思想·原理·环境搭建

    Appium 思想

    你无需为了自动化,而重新编译或者修改你的应用。
    你不必局限于某种语言或者框架来写和运行测试脚本。
      →Appium 真正的工作引擎其实是第三方自动化框架
      →把这些第三方框架封装成一套 API,WebDriver API.WebDriver(也就是 “Selenium WebDriver") 指定了客户端到服务端的协议。
      →Selenium 是web自动化测试工具集,核心是RC(selenium 1.0)和WebDriver(selenium 2.0)
      →RC和WebDriver 定义客户端脚本与浏览器交互的协议。以及元素定位与操作的接口。
       
    一个移动自动化的框架不应该在接口上重复造轮子。
       →WebDriver 已经成为 web 浏览器自动化的标准,也成了 W3C 的标准 —— W3C Working Draft,并扩充了WebDriver 的协议,在原有的基础上添加移动自动化相关的 API 方法
    无论是精神上,还是名义上,都必须开源。 

    架构原理

    • 左边的WebDriver script是我们的selenium测试脚本

    • 中间是起的Appium的服务,Appium在这边起了一个Server,Appium Server接收webdriver 标准请求,解析请求内容,调⽤用对应的框架响应操作。如:脚本发送一个点击按钮的请求给appium server

    • Appium server会把请求转发给中间件Bootstrap.jar ,它是用java写的,安装在手机上.Bootstrap 接收appium 的命令,最终通过调⽤用UiAutomator的命令来实现

    • 最后执⾏行的结果由Bootstrap返回给Appium server

    Appium环境搭建python篇(mac系统)

    安装时使用VPN可能比淘宝源成功率更高~

    2.定位对象 · 操作对象 · 校验对象

    定位对象-Android

    工具

    UiAutomatorview (4.1下版本不支持)

    启动方法 

      ~ uiautomatorviewer

    定位方法

    查找客户端页面元素方法

    以下是Appium给出的所有方法(但不一定支持!)

    查找页面中存在的单个元素
    查找页面中存在多个元素(返回数组)
    查找方法

    find_element

    find_elements
    def find_element(self, by=By.ID, value=None)

    被其他find_element方法调用

    find_element_by_accessibility_id find_elements_by_accessibility_id

    Accessibility ID在Android上面就等同于contentDescription,这个属性是方便一些生理功能有缺陷的人使用应用程序的。

    UiAutomatorview中content-desc

    find_element_by_android_uiautomator find_elements_by_android_uiautomator 使用android_uiautomator表达
    find_element_by_class_name find_elements_by_class_name UiAutomatorview中class
    find_element_by_id find_elements_by_id UiAutomatorview中resource-id
    find_element_by_ios_uiautomation find_elements_by_ios_uiautomation -
    find_element_by_link_text find_elements_by_link_text UiAutomatorview中text
    find_element_by_name find_elements_by_name Appium 1.5 版本已经被废除
    find_element_by_partial_link_text find_elements_by_partial_link_text

    UiAutomatorview中text,可以匹配部分文字

    譬如:美食(XX家)

    find_element_by_tag_name find_elements_by_tag_name Appium 1.0 版本已经被废除
    find_element_by_xpath find_elements_by_xpath xpath,强烈不推荐

    find_element_by_android_uiautomator() 举栗子

    def autotest_find_name_by_uiautomator(self, name):
        return self.driver.find_element_by_android_uiautomator('new UiSelector().text("%s")' % name)
    

      

    find_element_by_android_uiautomator()中的字符串为Uiautomator的写法,主要有以下几种方法:

    new UiSelector().text("%s")
    new UiSelector().textContains("%s")
    new UiSelector().className("%s")
    new UiSelector().resourceId("%s")
    
    textContains类似于find_element_by_partial_link_text,可以做部分文字匹配

    操作对象

    以下是常用的方法,更多的方法可以通过源码或提示获得

    tips:某些方法可能在特定系统不支持

    # 点击对象
    .click()
     
    # 文本框输入文字
    .send_keys("%s")
    #获取控件文字
    .text
      
    # 从(startx,starty)滑到(endx,endy),分duration步滑,每一步用时是5毫秒。
    driver.swipe(int startx, int starty, int endx, int endy, int duration)
      
    # 按手机固定键,key值定义在AndroidKeyCode类中
    # keycode http://blog.csdn.net/crisschan/article/details/50419963
    driver.send_key_event(int key)
      
    # 获取当前的activity
    driver.current_activity()
     
    # 等待指定的activity出现,interval为扫描间隔1秒
    driver.wait_activity(activity, timeout, interval=1)
      
    ...
    

      

    校验对象

    在Python环境下,Appium 官方推荐使用unittest来维护测试用例,unittest提供了多种assert方法,我们可以通过这些方法来做校验。

    unittest中常用的assert语句

    http://www.cnblogs.com/paulwinflo/p/5742142.html

    校验方式

    • 校验控件是否展示
    • 校验控件中的数据(文本)是否正确
    • 图片对比
    • ...

    代码实现

    校验元素非空

    def assert_element_exist_by_x(self, how, what, msg=None):
        """
        通过*方法验证元素非空
        :param how:find_element_by_* methods
        (By.CLASS_NAME/By.TAG_NAME/By.NAME/By.PARTIAL_LINK_TEXT/By.NAME/By.XPATH/By.ID)
        :param what:
        :param msg:
        """
        try:
            if how ==By.NAME:
                self.assertIsNotNone(self.autotest_find_name_by_uiautomator(what), msg)
            else:
                self.assertIsNotNone(self.driver.find_element(by=how, value=what), msg)
            return True
        except Exception:
            print "xxxxx"
    

       

    3.用例编写

    官方栗子

    import os
    import unittest
    from appium import webdriver
    from time import sleep
    
    # Returns abs path relative to this file and not cwd
    PATH = lambda p: os.path.abspath(
        os.path.join(os.path.dirname(__file__), p)
    )
    
    class ContactsAndroidTests(unittest.TestCase):
        def setUp(self):
            desired_caps = {}
            desired_caps['platformName'] = 'Android'
            desired_caps['platformVersion'] = '4.2'
            desired_caps['deviceName'] = 'Android Emulator'
            desired_caps['app'] = PATH(
                '../../../sample-code/apps/ContactManager/ContactManager.apk'
            )
            desired_caps['appPackage'] = 'com.example.android.contactmanager'
            desired_caps['appActivity'] = '.ContactManager'
    
            self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
    
        def tearDown(self):
            self.driver.quit()
    
        def test_add_contacts(self):
            el = self.driver.find_element_by_accessibility_id("Add Contact")
            el.click()
    
            textfields = self.driver.find_elements_by_class_name("android.widget.EditText")
            textfields[0].send_keys("Appium User")
            textfields[2].send_keys("someone@appium.io")
    
            self.assertEqual('Appium User', textfields[0].text)
            self.assertEqual('someone@appium.io', textfields[2].text)
    
            self.driver.find_element_by_accessibility_id("Save").click()
    
            # for some reason "save" breaks things
            alert = self.driver.switch_to_alert()
    
            # no way to handle alerts in Android
            self.driver.find_element_by_android_uiautomator('new UiSelector().clickable(true)').click()
    
            self.driver.press_keycode(3)
    
    
    if __name__ == '__main__':
        suite = unittest.TestLoader().loadTestsFromTestCase(ContactsAndroidTests)
        unittest.TextTestRunner(verbosity=2).run(suite)
    

       

    setup

    在Appium中所有动作的前提是要启动一个session,启动方法就是

    http://127.0.0.1:4723/wd/hub/session

    self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    其中desired_caps是配置信息,它告诉server 本次测试的具体内容,譬如:

    • 本次测试是启动浏览器还是启动移动设备?
    • 是启动andorid还是启动ios?
    • 启动android时,app的package是什么?
    • 启动android时,app的activity是什么?

    必要的desired_caps参数

    desired_caps['platformName'] = 'Android'
    desired_caps['platformVersion'] = '4.2'
    desired_caps['deviceName'] = '022MWW146T007732'
    desired_caps['app'] = 'XXX.apk'
    • platformName:使用哪种移动平台。iOS, Android, orFirefoxOS?
    • deviceName:启动哪种设备,是真机还是模拟器?iPhone Simulator, iPad Simulator, iPhone Retina 4-inch, Android Emulator, Galaxy S4, etc...
    • app:应用的绝对路径,注意一定是绝对路径。如果指定了appPackage和appActivity的话,这个属性是可以不设置的。另外这个属性和browserName属性是冲突的。
    • automationName:使用哪种自动化引擎。appium(默认)还是Selendroid?
    • appActivity:待测试的app的Activity名字。比如MainActivity, .Settings。注意,原生app的话要在activity前加个"."。
    • appPackage:待测试的app的java package。比如com.example.android.myApp, com.android.settings。

    teardown

     self.driver.quit()

    4.其他

    • Android 获取当前Activity、包名方法
      adb shell dumpsys activity | grep "mFocusedActivity"
      adb shell pm list package
    • 元素定位不到/没有id的方法
      麻烦开发增加特有、不重复的id
  • 相关阅读:
    iOS内存管理机制
    iOS开发之XML和JSON数据解析
    Ubuntu小点汇总,更新中...
    Android与服务器的简单通讯
    Gedit乱码问题
    Eclipse软件问题-方案积累
    开放接口使用积累
    定制知识积累
    Android小代码-技巧积累
    Android初学点滴积累(操作篇)
  • 原文地址:https://www.cnblogs.com/silvi/p/7156762.html
Copyright © 2011-2022 走看看