zoukankan      html  css  js  c++  java
  • Appium编写脚本中的那些事

    所有的操作范例和方式调用皆可做在官方文档中查阅到,本文只是简单整理

    官方文档地址:http://appium.io/docs/en/about-appium/intro/

    一、常用的元素定位方式

    元素定位的官方文档

    find_element_by_id  (resource-id)

    find_element_by_accessibility_id  (content-desc)

    find_element_by_xpath

    find_element_by_android_uiautomator

    关键的Attribute:resource-id,content-desc,text,bounds,clickable

    常用 XPath 相对定位表达式:

    二、常用自动化动作支持

    click

    sendkeys

    swipe

    touch action

     

     三、capability设置

    automationName 默认使⽤用 uiautomator

    autoGrantPermissions ⾃自动赋予 App 权限

    noReset fullReset 是否在测试前后重置相关环境

    unicodeKeyBoard resetKeyBoard 是否需要输入非英文之外的语言并在测试完成后重置输入法

    四、appium设备交互api

     发短信,打电话

    APP处理:get_performance_data 获取CPU,内存,电量,网络数据

    五、等待

    1、隐式等待:服务端(Appium)会在特定的超时时间内重试多次寻找控件 

    self.driver.implicitly_wait(20)

    2、显式等待:在客户端(用例端)根据更灵活的条件循环等待条件满足

    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions
    from selenium.webdriver.support.wait import WebDriverWait
    
    #第一种情况使用lambda函数,如果未发现定位元素返回自定义的错误信息
    kk = WebDriverWait(driver,10).until(lambda driver:driver.find_element_by_id("kw"),message="worry!")
    kk.send_keys("测试")
    
    #第二种情况使用len判断返回要查找的元素是否大于等于1,如果大于等于1则执行接下来的代码
    WebDriverWait(self.driver,15).until(lambda x:len(self.driver.find_element_by_id("image_cancel"))>=1)
    self.driver.find_element_by_id("image_cancel").click()
    
    #第三种情况使用expected_conditions判断元素是否可见,如果可见则执行接下来的代码
    WebDriverWait(self.driver,15).until(expected_conditions.visibility_of_element_located((By.ID,"image_cancel")))
    self.driver.find_element_by_id("image_cancel").click()
    
    #第四种情况使用自定义函数的形式,灵活度自己掌握
    def loaded(driver):
      print(datetime.now())
      if len(self.driver.find_element_by_id("image_cancel"))>=1:
        self.driver.find_element_by_id("image_cancel").click()
        return True
      else:
        return False
    WebDriverWait(self.driver, 15).until(loaded)

    3、强制等待

    time.sleep(20)
    

     六、Toast识别

    toast练习的apk下载地址:https://github.com/appium/java-client/blob/master/src/test/resources/apps/ApiDemos-debug.apk

    toast捕获必须使用xpath查找,练习代码示例

     1     def test_toast(self):
     2         self.driver.find_element_by_accessibility_id('Views').click()
     3         self.driver.swipe(350,1000,350,300)    #也可以用uiautomator方式
     4         self.driver.find_element_by_accessibility_id('Popup Menu').click()
     5         self.driver.find_element_by_accessibility_id('Make a Popup!').click()
     6         self.driver.find_element_by_xpath('//*[@text="Search"]').click()
     7         #toast第一种识别方法,用class
     8         # print(self.driver.find_element_by_xpath("//*[@class='android.widget.Toast']").text)
     9         #toast第二种识别方法,用text文本
    10         print(self.driver.find_element_by_xpath("//*[contains(@text,'Clicked popup menu item Search')]").text)

    七、断言

    元素是否存在:find_elements

    元素属性正确性:get_attribute

     1 from appium import webdriver
     2 import time
     3 from unittest import TestCase
     4 from hamcrest import *
     5 
     6 class TestDemo(TestCase):
     7     def setUp(self):
     8         caps = {}
     9         caps["platformName"] = "Android"
    10         caps["deviceName"] = "Android Emulator"
    11         caps["appPackage"] = "com.xxxx.android"
    12         caps["appActivity"] = ".view.WelcomeActivityAlias"
    13         caps["autoGrantPermissions"] = "true"
    14 
    15         self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
    16         self.driver.implicitly_wait(20)
    17         #打开APP首页时同意内容
    18         el2 = self.driver.find_element_by_id("com.xxxx.android:id/tv_agree")
    19         el2.click()
    20         
    21     def test_search(self):
    22         el3 = self.driver.find_element_by_id("com.xxxx.android:id/home_search")
    23         el3.click()
    24         el4 = self.driver.find_element_by_id("com.xxxx.android:id/search_input_text")
    25         el4.send_keys("拼多多")
    26         self.driver.find_element_by_id('name').click()
    27         price = self.driver.find_element_by_id("current_price")
    28         #断言拼多多的股价是否大于68.5元
    29         assert float(price.text) > 68.5
    30         #断言price的元素属性resource-id是否为price
    31         assert "price" in price.get_attribute("resource-id")
    32         #hamcrest方式断言price元素属性的package包名是否为xueqiu.android
    33         assert_that(price.get_attribute("package"),equal_to("com.xxxx.android"))
    34 
    35     def tearDown(self):
    36         time.sleep(3)
    37         self.driver.quit()

    八、参数化与数据驱动

    1、利用pytest进行简单的参数化

    pytest和unittest编写上的两点不同:1、类名中是否写TestCase;2、pytest中setup和teardown是小写,而unittest中是大写

     1 import pytest,time
     2 from appium import webdriver
     3 
     4 class TestDemo():
     5     def setup(self):
     6         caps = {}
     7         caps["platformName"] = "Android"
     8         caps["deviceName"] = "Android Emulator"
     9         caps["appPackage"] = "com.xxxx.android"
    10         caps["appActivity"] = ".view.WelcomeActivityAlias"
    11         caps["autoGrantPermissions"] = "true"
    12 
    13         self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
    14         self.driver.implicitly_wait(20)
    15         self.driver.find_element_by_id("com.xxxx.android:id/tv_agree").click()
    16         
    17     #要进行参数化的数据
    18     @pytest.mark.parametrize("keyword,expected_price", [
    19         ("拼多多", 68.5),
    20         ("京东", 49)
    21     ])
    22     def test_search(self,keyword,expected_price):
    23         self.driver.find_element_by_id("com.xxxx.android:id/home_search").click()
    24         self.driver.find_element_by_id("com.xxxx.android:id/search_input_text").send_keys(keyword)
    25         self.driver.find_element_by_id('name').click()
    26         price = self.driver.find_element_by_id("current_price")
    27         assert float(price.text) > expected_price
    28     
    29     def teardown(self):
    30         time.sleep(3)
    31         self.driver.quit()

    2、数据驱动

     search.yaml数据文件及运行代码实现参数化数据读取来自外部文件

    1 - [ pdd, 68.5 ]
    2 - [ jd, 48 ]
     1 import pytest,time
     2 import yaml
     3 from appium import webdriver
     4 
     5 class TestDemo():
     6     search_data = yaml.safe_load(open("search.yaml",'r'))
     7     print(search_data)
     8     def setup(self):
     9         caps = {}
    10         caps["platformName"] = "Android"
    11         caps["deviceName"] = "Android Emulator"
    12         caps["appPackage"] = "com.xxxx.android"
    13         caps["appActivity"] = ".view.WelcomeActivityAlias"
    14         caps["autoGrantPermissions"] = "true"
    15 
    16         self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
    17         self.driver.implicitly_wait(20)
    18         self.driver.find_element_by_id("com.xxxx.android:id/tv_agree").click()
    19         
    20     @pytest.mark.parametrize("keyword,expected_price", search_data)
    21     def test_search(self,keyword,expected_price):
    22         self.driver.find_element_by_id("com.xxxx.android:id/home_search").click()
    23         self.driver.find_element_by_id("com.xxxx.android:id/search_input_text").send_keys(keyword)
    24         self.driver.find_elements_by_id('name')[0].click()
    25         price = self.driver.find_element_by_id("current_price")
    26         assert float(price.text) > expected_price
    27         
    28     def teardown(self):
    29         time.sleep(3)
    30         self.driver.quit()

    testcase.yaml测试步骤读取外部文件

    1 - id: home_search
    2 - id: search_input_text
    3   input: pdd
    4 - id: name
    5 - id: current_price
    6   get: text
     1 import yaml,time
     2 from appium import webdriver
     3 from selenium.webdriver.remote.webdriver import WebDriver
     4 
     5 class TestDemo():
     6     def setup(self):
     7         caps = {}
     8         caps["platformName"] = "Android"
     9         caps["deviceName"] = "Android Emulator"
    10         caps["appPackage"] = "com.xxxx.android"
    11         caps["appActivity"] = ".view.WelcomeActivityAlias"
    12         caps["autoGrantPermissions"] = "true"
    13 
    14         self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
    15         self.driver.implicitly_wait(20)
    16         self.driver.find_element_by_id("com.xxxx.android:id/tv_agree").click()
    17         
    18     def test_search(self):
    19         Test_Case("testcase.yaml").run(self.driver)
    20         
    21     def teardown(self):
    22         time.sleep(3)
    23         self.driver.quit()
    24         
    25 class Test_Case:
    26     def __init__(self,path):
    27         file = open(path,"r")
    28         self.steps = yaml.safe_load(file)
    29         print("打印出来的yaml文件内容为:",self.steps)
    30 
    31     def run(self,driver: WebDriver):
    32         for step in self.steps:
    33             if isinstance(step, dict):
    34                 element = None
    35                 if "id" in step.keys():
    36                     element = driver.find_element_by_id(step["id"])
    37                 elif "xpat" in step.keys():
    38                     element = driver.find_element_by_xpath(step["xpath"])
    39                 else:
    40                     print(step.keys())
    41 
    42                 if "input" in step.keys():
    43                     element.send_keys(step["input"])
    44                 elif "get" in step.keys():
    45                     text = element.get_attribute(step["get"])
    46                     print("获取到的文本内容为:", text)
    47                 else:
    48                     element.click()
     
  • 相关阅读:
    Dom-Align
    antd Dialog 学习笔记
    setState 同步 与异步
    移动端使用iframe碰到的那些坑
    谈页面上下滑动时,页面顶部导航等部分元素的定位方式发生改变
    一款table结合分页的插件
    监听页面滚动时间时所碰到的一些坑
    值得收藏的前端大牛博客
    后端时间转js时间,主要用于取倒计时
    论jquery与vuejs结合时的部分问题
  • 原文地址:https://www.cnblogs.com/hanxiaobei/p/12944839.html
Copyright © 2011-2022 走看看