天天看点

Appium Python Client readme 中文版https://github.com/appium/python-clientAppium Python Client获取  Appium Python clientDevelopment发布用法

https://github.com/appium/python-client

Appium Python Client

Appium Python Client readme 中文版https://github.com/appium/python-clientAppium Python Client获取  Appium Python clientDevelopment发布用法
Appium Python Client readme 中文版https://github.com/appium/python-clientAppium Python Client获取  Appium Python clientDevelopment发布用法
Appium Python Client readme 中文版https://github.com/appium/python-clientAppium Python Client获取  Appium Python clientDevelopment发布用法

一个添加了 Selenium 3.0 draft 和 Mobile JSON Wire Protocol Specification draft 功能到 Python 语言绑定的拓展库, 和移动测试框架 Appium 一块使用.

获取  Appium Python client

真理有三种方法安装并使用 Appium Python client.

  1.  以  'Appium-Python-Client' 从 PyPi 安装
    pip install Appium-Python-Client      
    你可以从这里查看历史记录 here
  2. Install from source, via PyPi. From 'Appium-Python-Client', download and unarchive the source tarball (Appium-Python-Client-X.X.tar.gz).
    tar -xvf Appium-Python-Client-X.X.tar.gz
    cd Appium-Python-Client-X.X
    python setup.py install      
  3.  由 GitHub 从源(source)安装
    git clone [email protected]:appium/python-client.git
    cd python-client
    python setup.py install      

Development

  • 格式指南 : https://www.python.org/dev/peps/pep-0008/
    • autopep8

       帮助自动格式化代码
      $ python -m autopep8 -r --global-config .config-pep8 -i .
                 
    • isort

       帮助自动选定引入
      $ python -m isort -rc .
                 
  • You can customise 

    CHANGELOG.rst

     with commit messages following .gitchangelog.rc
    • It generates readable changelog
  • Setup
    • pip install --user pipenv

    • python -m pipenv lock --clear

      • If you experience the below error, then refer pypa/pipenv#187 to solve it.
        Locking Failed! unknown locale: UTF-8
                   
    • python -m pipenv install --dev --system

    • pre-commit install

运行测试集

你可以在本地通过 tox 在 CI 上运行所有的测试

$ tox
           

你也可以像接下来那样运行特定的测试

Unit

$ py.test test/unit
           

运行 

pytest-xdist

$ py.test -n 2 test/unit
           

函数

$ py.test test/functional/ios/find_by_ios_class_chain_tests.py
           

适用于iOS

  1. 创建命名为 'iPhone 6s - 8100' 和'iPhone 6s - 8101' 的模拟器
  2. 通过 pip 安装测试库
    $ pip install pytest pytest-xdist
               
  3. 运行测试集
    $ py.test -n 2 test/functional/ios/find_by_ios_class_chain_tests.py
               

发布

按照以下步骤。

$ pip install twine
$ pip install git+git://github.com/vaab/gitchangelog.git # Getting via GitHub repository is necessary for Python 3.7
# Type the new version number and 'yes' if you can publish it
# You can test the command with DRY_RUN
$ DRY_RUN=1 ./release.sh
$ ./release.sh # release      

用法

Appium Python Client 完全符合 Selenium 3.0 规范草案, 其中一些工具包使得在Python中进行移动测试更简单. 大多数用法仍然与 Selenium 2 (WebDriver) 一样, and as the official Selenium Python bindings begins to implement the new specification that implementation will be used underneath, so test code can be written that is utilizable with both bindings.

要立即使用新功能,并使用函数的超集,不再在你的测试代码中引入 Selenium 

webdriver

 模块,而是从 Appium 引用这个(Selenium 

webdriver

)模块来代替

from appium import webdriver      

从这里开始你的大部分测试代码将无需任何改变。

作为以下代码示例的基础,以下设置  UnitTest 环境:

# Android environment
import unittest
from appium import webdriver

desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '8.1'
desired_caps['automationName'] = 'uiautomator2'
desired_caps['deviceName'] = 'Android Emulator'
desired_caps['app'] = PATH('../../../apps/selendroid-test-app.apk')

self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)      
# iOS environment
import unittest
from appium import webdriver

desired_caps = {}
desired_caps['platformName'] = 'iOS'
desired_caps['platformVersion'] = '11.4'
desired_caps['automationName'] = 'xcuitest'
desired_caps['deviceName'] = 'iPhone Simulator'
desired_caps['app'] = PATH('../../apps/UICatalog.app.zip')

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

更改或添加功能

改变的方法是......

直接连接网址

如果你的 Selenium/Appium 服务器使用以下键名(keys)修饰新的会话功能响应:

  • directConnectProtocol

  • directConnectHost

  • directConnectPort

  • directConnectPath

然后 python client 客户端将其端点切换到由这些键的值指定的端点

import unittest
from appium import webdriver

desired_caps = {}
desired_caps['platformName'] = 'iOS'
desired_caps['platformVersion'] = '11.4'
desired_caps['automationName'] = 'xcuitest'
desired_caps['deviceName'] = 'iPhone Simulator'
desired_caps['app'] = PATH('../../apps/UICatalog.app.zip')

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

在 'Native(原生)' 和 'Webview' 之间切换

对于移动测试,之前用于在窗口之间切换的Selenium方法被用于在本机应用程序(native applications)和webview上下文(webview contexts)之间切换。为此明确的方法已添加到Selenium 3规范中,因此将使用这些“上下文”方法。

获取当前上下文, 不再调用 

driver.current_window_handle

 而是使用

current = driver.current_context      

不再使用 

driver.window_handles

 检索可用的上下文而是用

driver.contexts      

最后,要切换到新的上下文, 不再用 

driver.switch_to.window(name)

, 而是使用可比较的上下文方法

context_name = "WEBVIEW_1"
driver.switch_to.context(context_name)      

通过 iOS UIAutomation search 查找元素

This allows elements in iOS applications to be found using recursive element search using the UIAutomation library. This method is supported on iOS devices that still support UIAutomation, that is, versions which predate XCUITEST.

Adds the methods 

driver.find_element_by_ios_uiautomation

 and 

driver.find_elements_by_ios_uiautomation

.

el = self.driver.find_element_by_ios_uiautomation('.elements()[0]')
self.assertEqual('UICatalog', el.get_attribute('name'))      
els = self.driver.find_elements_by_ios_uiautomation('.elements()')
self.assertIsInstance(els, list)      

通过 Android UIAutomator search 查找元素

这允许使用UIAutomator库使用递归元素搜索找到Android应用程序中的元素. 添加了方法 

driver.find_element_by_android_uiautomator

 和 

driver.find_elements_by_android_uiautomator

.

el = self.driver.find_element_by_android_uiautomator('new UiSelector().description("Animation")')
self.assertIsNotNone(el)      
els = self.driver.find_elements_by_android_uiautomator('new UiSelector().clickable(true)')
self.assertIsInstance(els, list)      

通过 Android viewtag(视图标签) search 查找元素

这种方法允许使用 View#tags 发现元素. 此方法适用于 Espresso Driver.

添加了方法 

driver.find_element_by_android_viewtag

 和

driver.find_elements_by_android_viewtag

.

el = self.driver.find_element_by_android_viewtag('a tag name')
self.assertIsNotNone(el)      
els = self.driver.find_elements_by_android_viewtag('a tag name')
self.assertIsInstance(els, list)      

通过 iOS predicates 查找元素

This method allows finding elements using iOS predicates. The methods take a string in the format of a predicate, including element type and the value of fields.

Adds the methods 

driver.find_element_by_ios_predicate

 and 

find_elements_by_ios_predicate

.

el = self.driver.find_element_by_ios_predicate('wdName == "Buttons"')
self.assertIsNotNone(el)      
els = self.driver.find_elements_by_ios_predicate('wdValue == "SearchBar" AND isWDDivisible == 1')
self.assertIsInstance(els, list)      

通过 iOS class chain 查找元素

This method is only for XCUITest driver

This method allows finding elements using iOS class chain. The methods take a string in the format of a class chain, including element type.

Adds the methods 

driver.find_element_by_ios_class_chain

 and 

find_elements_by_ios_class_chain

.

el = self.driver.find_element_by_ios_class_chain('XCUIElementTypeWindow/XCUIElementTypeButton[3]')
self.assertIsNotNone(el)      
els = self.driver.find_elements_by_ios_class_chain('XCUIElementTypeWindow/XCUIElementTypeButton')
self.assertIsInstance(els, list)      

通过 Accessibility ID 查找元素

允许使用 "Accessibility(可访问的) ID" 查找元素. 这些方法传入代表给定元素的可访问性标识或附加标签的字符串, 例如,对于iOS,可访问性标识符和对于Android的内容描述。添加了方法 

driver.find_element_by_accessibility_id

 和

find_elements_by_accessibility_id

.

el = self.driver.find_element_by_accessibility_id('Animation')
self.assertIsNotNone(el)      
els = self.driver.find_elements_by_accessibility_id('Animation')
self.assertIsInstance(els, list)      

触摸动作

为了适应移动触控以及涉及多点触控 , Selenium 3.0 草案指定了 "touch gestures" (触摸手势)和 "multi actions"(多点触控), 它们构建在触摸动作之上。

move_to: 请注意,如果没有元素,请使用关键字参数

 API 围绕 

TouchAction

 对象构建, 这个对象是按顺序执行的一个或多个动作的链 ,动作是

perform

perform

方法将链发送到服务器以便生效。它还清空了动作链,因此可以重用该对象。它将在所有单一动作链的末尾,但在编写多动作链时不被使用。

tap

tap

方法独立,无法与其他方法链接。如果你需要一个类似

tap

的动作来启动更长的链,请使用

press

它可以是带有可选xy偏移的元素,也可以是tap的绝对xy坐标,以及可选的计数。

el = self.driver.find_element_by_accessibility_id('Animation')
action = TouchAction(self.driver)
action.tap(el).perform()
el = self.driver.find_element_by_accessibility_id('Bouncing Balls')
self.assertIsNotNone(el)      

press

long_press

release

move_to

wait

cancel

多点触控动作

除了在单个手势内执行的动作链之外,还可以同时执行多个链,以模拟多手指动作。这是通过构建

MultiAction

包含多个单独

TouchAction

对象的对象来完成的,每个对象对应一个“手指”。

给定两个彼此相邻的列表,我们可以独立滚动它们,但同时:

els = self.driver.find_elements_by_class_name('listView')
a1 = TouchAction()
a1.press(els[0]) \
    .move_to(x=10, y=0).move_to(x=10, y=-75).move_to(x=10, y=-600).release()

a2 = TouchAction()
a2.press(els[1]) \
    .move_to(x=10, y=10).move_to(x=10, y=-300).move_to(x=10, y=-600).release()

ma = MultiAction(self.driver, els[0])
ma.add(a1, a2)
ma.perform();      

特定于Appium的触摸动作

移动测试人员需要做很少的操作,使用Touch和Multi-touch Action API进行构建可能相对复杂。为此,我们在Appium客户端中提供了一些便捷方法。

driver.tap

在WebDriver对象上,此方法允许使用多个手指轻敲(tap),只需传入一个xy坐标数组即可。

el = self.driver.find_element_by_name('Touch Paint')
action.tap(el).perform()

# set up array of two coordinates
positions = []
positions.append((100, 200))
positions.append((100, 400))

self.driver.tap(positions)      

driver.swipe

从一个点滑动到另一个点。

应用管理方法

在测试中,有时您希望管理正在运行的应用程序,例如安装或删除应用程序等。

背景应用程序

The method 

driver.background_app

 sends the running application to the background for the specified amount of time, in seconds. After that time, the application is brought back to the foreground.

该方法

driver.background_app

指定的时间内将运行的应用程序发送到后台(以秒为单位)。在此之后,应用程序将返回到前台。

driver.background_app(1)
sleep(2)
el = driver.find_element_by_name('Animation')
assertIsNotNone(el)      

检查是否安装了应用程序

要检查设备上当前是否安装了应用程序,请使用该

device.is_app_installed

 方法。此方法获取应用程序的bundle id并返回

True

或 

False

assertFalse(self.driver.is_app_installed('sdfsdf'))
assertTrue(self.driver.is_app_installed('com.example.android.apis'))      

安装应用程序

要在设备上安装已卸载的应用程序,请使用

device.install_app

,发送应用程序文件或存档的路径。

assertFalse(driver.is_app_installed('io.selendroid.testapp'))
driver.install_app('/Users/isaac/code/python-client/test/apps/selendroid-test-app.apk')
assertTrue(driver.is_app_installed('io.selendroid.testapp'))      

删除应用程序

如果您需要从设备中删除应用程序,请使用

device.remove_app

,传入应用程序ID。

assertTrue(driver.is_app_installed('com.example.android.apis'))
driver.remove_app('com.example.android.apis')
assertFalse(driver.is_app_installed('com.example.android.apis'))      

关闭并启动应用程序

要启动所需功能中指定的应用程序,请调用 

driver.launch_app

。关闭该应用程序是通过 

driver.close_app 方法

el = driver.find_element_by_name('Animation')
assertIsNotNone(el)
driver.close_app();

try:
    driver.find_element_by_name('Animation')
except Exception as e:
    pass # should not exist

driver.launch_app()
el = driver.find_element_by_name('Animation')
assertIsNotNone(el)      

重置应用程序

要重置运行的应用程序,使用

driver.reset

el = driver.find_element_by_name('App')
el.click()

driver.reset()
sleep(5)

el = driver.find_element_by_name('App')
assertIsNotNone(el)      

其他方法

开始任意活动

driver.start_activity

方法在设备上打开任意活动。如果活动不是被测试应用程序的一部分,它还将启动活动的应用程序。

driver.start_activity('com.foo.app', '.MyActivity')      

检索应用程序字符串

property方法

driver.app_strings 

从设备上的应用程序返回应用程序字符串。

strings = driver.app_strings      

将按键事件发送到Android设备

该 

driver.keyevent

 方法将按钮代码发送到设备. 键码可以在 here 这里找到. 仅适用于Android.

# sending 'Home' key event
driver.press_keycode(3)      

在iOS中隐藏键盘

To hide the keyboard from view in iOS, use 

driver.hide_keyboard

. If a key name is sent, the keyboard key with that name will be pressed. If no arguments are passed in, the keyboard will be hidden by tapping on the screen outside the text field, thus removing focus from it.

# get focus on text field, so keyboard comes up
el = driver.find_element_by_class_name('android.widget.TextView')
el.set_value('Testing')

el = driver.find_element_by_class_name('keyboard')
assertTrue(el.is_displayed())

driver.hide_keyboard('Done')

assertFalse(el.is_displayed())      
# get focus on text field, so keyboard comes up
el = driver.find_element_by_class_name('android.widget.TextView')
el.set_value('Testing')

el = driver.find_element_by__name('keyboard')
assertTrue(el.is_displayed())

driver.hide_keyboard()

assertFalse(el.is_displayed())      

检索当前正在运行的包和活动

property方法

driver.current_package

返回设备上运行的当前包的名称。

package = driver.current_package
assertEquals('com.example.android.apis', package)      

property方法

driver.current_activity

返回设备上运行的当前活动的名称。

activity = driver.current_activity
assertEquals('.ApiDemos', activity)      

直接在元素上设置值

有时需要直接在设备上设置元素的值。要做到这一点,方法 

driver.set_value

 或 

element.set_value

 被调用.

el = driver.find_element_by_class_name('android.widget.EditText')
driver.set_value(el, 'Testing')

text = el.get_attribute('text')
assertEqual('Testing', text)

el.set_value('More testing')
text = el.get_attribute('text')
assertEqual('More testing', text)      

从设备中检索文件

要从设备检索文件的内容,请使用 

driver.pull_file

,它返回用 Base64中编码的指定文件的内容。

# pulling the strings file for our application
data = driver.pull_file('data/local/tmp/strings.json')
strings = json.loads(data.decode('base64', 'strict'))
assertEqual('You can\'t wipe my data, you are a monkey!', strings[u'monkey_wipe_data'])      

将文件放在设备上

要将文件放在特定位置的设备上,请使用该

driver.push_file

 方法,该方法携带路径和数据信息以Base64编码形式写入文件。

path = 'data/local/tmp/test_push_file.txt'
data = 'This is the contents of the file to push to the device.'
driver.push_file(path, data.encode('base64'))
data_ret = driver.pull_file('data/local/tmp/test_push_file.txt').decode('base64')
self.assertEqual(data, data_ret)      

结束测试覆盖率

Android模拟器中有一些功能可用于检测某些活动。有关此信息,请参阅 Appium docs. 要结束此覆盖并检索数据,请使用 

driver.end_test_coverage

,传入 

intent

 正在被工具化的数据, 以及 

coverage.ec

 设备上文件的路径.

coverage_ec_file = driver.end_test_coverage(intent='android.intent.action.MAIN', path='')      

锁定设备

要在iOS上锁定设备一段时间,请使用

driver.lock

。参数是解锁前等待的秒数。

摇晃设备

要摇动设备,请使用

driver.shake

Appium设置

设置是appium引入的新概念。它们目前不是Mobile JSON Wire Protocol或Webdriver规范的一部分。

设置是指定appium服务器行为的一种方法。

设置是:

可变,它们可以在会话期间更改仅在相关应用会话期间。它们会针对每个新会话重置。控制appium服务器在测试自动化期间的行为方式。它们不适用于控制受测试的应用程序或设备。

有关更多信息,请参阅文档。

要获得设置:

settings = driver.get_settings()      

要设置设置:

driver.update_settings({"some setting": "the value"})