自动化框架
selenium
selenium工作原理
WebDriver提供了另外一种方式与浏览器进行交互。那就是利用浏览器原生的API,封装成一套更加面向对象的Selenium WebDriver API,直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件,配置证书之类的)。由于使用的是浏览器的原生API,速度大大提高,而且调用的稳定性交给了浏览器厂商本身,显然是更加科学。然而带来的一些副作用就是,不同的浏览器厂商,对Web元素的操作和呈现存在不同程度的差异,这就要求Selenium WebDriver要分浏览器厂商的不同,提供不同的实现,例如Chrome有专门的ChromeDriver,Firefox有FirefoxDriver等等。
WebDriver Wire协议是通用的,也就是说不管是FirefoxDriver还是ChromeDriver,启动之后都会在某一个端口启动基于这套协议的Web Service。例如ChromeDriver初始化成功之后,默认会从http://localhost:46350
开始,而FirefoxDriver从http://localhost:7055
开始。后续我们调用WebDriver的任何API,都需要借助一个ComandExecutor发送一个命令,实际上是一个HTTP request给监听端口上的Web Service。在我们的HTTP request的body中,会以WebDriver Wire协议规定的JSON格式的字符串来告诉Selenium我们希望浏览器接下来做什么事情
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WzpXkbt6-1647764171020)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007221011625.png)]
具体过程如下:
(1)实例化WebDriver,Selenium首先会确认浏览器的native component是否存在可用而且版本匹配。若匹配则在目标浏览器里启动一整套Web Service。这套Web Service使用了Selenium自己设计定义的协议,名字叫做The WebDriver Wire Protocol。这套协议非常之强大,几乎可以操作浏览器做任何事情,包括打开、关闭、最大化、最小化、元素定位、元素点击、文件上传等等
(2)发送请求时,用WebDriver的HttpCommandExecutor类将命令转换为URL作为value,命令作为key一起存入map作为request,同时会在request的body中存放相应的By Xpath、id、name。实际发送的URL都是相对路径,后缀多以/session/:sessionId开头,这也意味着WebDriver每次启动浏览器都会分配一个独立的sessionId,多线程并行的时候彼此之间不会有冲突和干扰。比如我们常用到的find_element_by_class_name这个接口,会转化为/session/:sessionId/element这个url,然后在发出Http Request Body内再附上具体的参数,比如class name的值。比如我们要访问某一个网站,请求地址为:http://localhost:46350/wd/hub/session/sessionId/url
,请求json内容:{"url":"http://www.qq.com"}
。比如查找一个classname为test的元素,请求地址后缀为/session/sessionId/element
,json内容{"using":"class_name","value":"test"}
。
(3)收到并执行了这个操作之后,也会回复一个Http Response。内容也是Json,会返回找到的element的各种细节,比如text、CSS selector、tag name、class name等等。比如:
{"sessionId":"XXXXX","status":0,"state":"success","value":
{"ELEMENT":"2"},"class":"XXX","hCode":"XXX"}
python+selenium环境搭建
(1)python的安装
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KbIu7o2N-1647764171023)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007203108993.png)]
python安装包后,需要配置环境变量,其实在3.7的安装过程中,第一个界面有一个“add python to path”的选项可以勾选(大概是这个名字)。勾选之后会自动将python添加到系统环境变量Path中。当然你也可以选择手动添加,添加方法如下:
我的电脑右键选择属性–>高级系统设置–>环境变量–>环境变量–>系统变量:找到path变量并修改,在Path路径的最前面加入:C:\Python37;C:\Python37\Scripts; (如果你的python安装在其他路径请做相应的改动,笔者这里是默认路径)
特别要注意:很多新手会把Path中原来的内容删除掉,笔者提醒一下这个绝对不能这样做,慎重!慎重!慎重!
安装之后,运行CMD窗口,输入python指令,用于校验python是否安装成功。如下图表示成功!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k1JpJPf4-1647764171024)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007203154058.png)]
(2)selenium的安装
selenium可以通过pip命令进行安装,安装方法如下:
-
打开cmd窗口
-
输入:pip install selenium
-
等待cmd窗口提示successful,则selenium安装成功,如中途中断了继续输入pip install selenium重新安装,不影响!
(3)chrome浏览器
Chrome官网:https://www.google.cn/chrome/
(4)安装chrome浏览器驱动
当Selenium提出了WebDriver的概念之后,它提供了利用浏览器原生的接口,封装成一套更加面向对象的Selenium WebDriver API,直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件)。
由于使用的是浏览器原生的接口,速度大大提高,而且调用的稳定性交给了浏览器厂商本身,显然是更加科学。然而带来的一些副作用就是,不同的浏览器厂商,对Web元素的操作和呈现多少会有一些差异,这就直接导致了Selenium WebDriver要分浏览器厂商不同,而提供不同的实现。例如Firefox就有专门的geckoDriver驱动,Chrome就有专门的Chrome驱动等。
这里特别要注意:chrome浏览器驱动必须和安装的chrome浏览器版本对应。那么如何保证对应呢?
1.先检查chrome浏览器的版本:点击chrome浏览器右上角的三个点–>帮助–>关于Google Chrome,如下图所示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pyLiZwob-1647764171025)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007204144539.png)]
2.chrome浏览器驱动下载地址:
Chromedriver驱动下载地址:http://npm.taobao.org/mirrors/chromedriver/
python+selenium自动化之旅
#demo
from selenium import webdriver
import os
import json
cookies = {'name': 'NEWOPPOSID',
'value': 'eyJpdiI6IlU0MkRaS0s2RGRobkxCcG5ZdGRYN2c9PSIsInZhbHVlIjoicC9nTVFhWldvTllhTUQ4bVVLQkVxcktEWTFpemFkVG81amVYVWM3d2lDclZPVGVlbWhYeWh3TTNlM0JnbWsvYnorMUowRVpYUzBmODhpczVsY0NwWVdMY2JqNXU4NUtCK2FxTUNsZWNHREZrQ1Y3Slh2THZNckcybldlMWdqb0YiLCJtYWMiOiIwMjczZTBjYWY0M2RkZWFiYzM4MmU3OTdiNmRjMzRlNDEwOGVjMDNhODU5NTRiMDM0NjRjNWJkYmQ3Y2UyYzk2In0='}
dir = os.path.dirname(os.path.abspath('.'))
chrome_driver_path = dir + '/tools/chromedriver_94.exe'
driver = webdriver.Chrome(executable_path=chrome_driver_path)
driver.get('https://store.oppo.com/cn/m/order/list')
# driver.delete_all_cookies()
driver.add_cookie(cookies)
driver.refresh()
print(driver.get_cookies())
appium
appium工作原理
介绍
Appium是一个开源工具,用于自动化iOS、Android设备和Windows桌面平台上的原生、移动Web和混合应用。
"原生应用"指那些用iOS、Android或者WindowsSDK编写的应用。
"移动web应用"是用移动端浏览器访问的应用(Appium支持iOS上的Safari、Chrome和Android上的内置浏览器)。
"混合应用"带有一个"webview"的包装器——用来和Web内容交互的原生控件。
重要的是:Appium是跨平台的:它允许你用同样的API对多平台写测试,做到在iOS、Android和Windows测试套件之间复用代码。
Appium关键词
Appium是基于nodejs的HTTP服务器,用于创建和处理基JSON wire protocol协议的多webdriver会话,支持IOS和android平台。
以下为Appium架构中关键词:
会话(session):标识Appium客户端和Appium服务器端惟一交互
Desired Capabilities:用于告诉Appium服务端要启动一个什么类型的自动化测试会话
Appium服务器:基于nodejs写的HTTP服务器,实现了对JSON wire protocol的处理
Appium客户端:支持多语言(python、ruby、java、php、javascript、C#)API,提供给测试或开发人员编写appium自动化测试脚本,另外还提供了Inspector用于查看APP的层级结构,便于分析APP的UI结构
APPIUM IOS端工作原理
下面我们通过一张图来看下IOS端APPIUM全过程工作原理:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GwmbzH7H-1647764171025)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007221429115.png)]
APPIUM Android端工作原理
下面我们通过一张图来看下android端APPIUM全过程工作原理:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qJuCkBKi-1647764171026)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007221506853.png)]
说明
- 整个箭头指向为一个完成的指令循环
- webdriver script需要自动化测试人员自己编写对应的测试脚本
- 建议大家去了解下JSON wire protocol
- 建议大家去了解下instruments
- 建议大家去了解下UiAutomator
windows+python+appium环境搭建
Appium 官网: http://appium.io/
安装方式一: 使用NodeJS 安装
首先到NodeJS官网下载安装最新的NodeJS,Windows下属于傻瓜安装。安装好之后你可以配置NodeJS的安装源,在国内一般都用taobao的镜像,速度还不错
在个人目录下新建一个 .npmrc 文件,写入
registry=https://registry.npm.taobao.org/
使用npm命令安装 Appium
npm install -g appium
安装appium-doctor
通过运行appium-doctor命令可以快速检查appium的环境问题
npm install -g appium-doctor
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ssd1UAP-1647764171027)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007212010670.png)]
如果安装成功,那么就可以通过 appium 命令启动 appium server
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HLPcR7l2-1647764171028)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007211809108.png)]
安装方式二: 使用Appium安装包
Appium 目前托管在github,正确的下载地址应该为:
- https://github.com/appium/appium-desktop/releases
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wB74DXyG-1647764171028)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007212233809.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S9cnr9dp-1647764171029)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007214637614.png)]
注意,你可以不安装Appium 桌面版,但是命令行版应该还是需要安装的,因为自动化测试运行时一般都是通过命令启动和关闭Appium,桌面版并不提供命令行功能,只是为了调试方便
关于appium的介绍文档
http://appium.io/docs/cn/about-appium/intro/
安装 Appium-Client
讨论Python实现的Appium测试
pip install Appium-Python-Client
如果需要使用其他编程语言,下表供参考:
语言/框架 | Github版本库以及安装指南 |
---|---|
Ruby | https://github.com/appium/ruby_lib |
Python | https://github.com/appium/python-client |
Java | https://github.com/appium/java-client |
JavaScript (Node.js) | https://github.com/admc/wd |
Objective C | https://github.com/appium/selenium-objective-c |
PHP | https://github.com/appium/php-client |
C# (.NET) | https://github.com/appium/appium-dotnet-driver |
RobotFramework | https://github.com/jollychang/robotframework-appiumlibrary |
环境变量设置
环境变量 | 值 |
---|---|
ANDROID_HOME | Android SDK 的安装位置 |
JAVA_HOME | JDK 或者 JRE 的安装位置 |
加入 PATH | %ANDROID_HOME%\tools |
加入 PATH | %ANDROID_HOME%\platform-tools |
加入 PATH | %JAVA_HOME%\bin |
加入 PATH | %ANDROID_HOME%\build-tools??version?? (可选) |
完成第一个自动化测试
启动appium服务并连接手机
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-92a3ZQak-1647764171030)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007213424471.png)]
import time
from appium import webdriver
capabilities = {}
# Android平台测试
capabilities['platformName'] = 'Android'
# 测试手机版本为11
capabilities['platformVersion'] = '11'
capabilities['deviceName'] = '73185eaf'
# 系统手机中的联系人app的包名
capabilities['appPackage'] = 'com.android.contacts'
# 系统手机中的联系人app的主入口activity
capabilities['appActivity'] = '.activities.PeopleActivity'
capabilities['unicodeKeyboard'] = True
capabilities['resetKeyboard'] = True
# 连接测试机所在服务器服务器
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', capabilities)
try:
# com.android.contacts:id/floating_action_button为通过uiautomatorviewer截取联系人界面获取到的
element = driver.find_element_by_id('com.android.contacts:id/floating_action_button')
#如果找到该id所指定控件,则进行点击操作
element.click()
except:
print("exit")
pass
time.sleep(2)
#断开连接
driver.quit()
常见问题
1:An unknown server-side error occurred while processing the command
selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Unable to find an active device or emulator with OS 10. The following are available: 73185eaf (11)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hgAvEQKG-1647764171031)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007213654910.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-muqmpiil-1647764171032)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007214108581.png)]
1、先检查包名是否正确(正常情况下包名不会错误)通过命令行查看包名:aapt dump badging shoujibaidu.apk
package: name='com.baidu.searchbox' versionCode='96732800' versionName='11.17.0.13' platformBuildVersionName=''
launchable-activity: name='com.baidu.searchbox.SplashActivity' label='Baidu' icon=''
2、检查对应包的appActivity是否正确:如果与命令行的activity不一致改过来就ok了
android版本改成11,问题解决
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-22X6hUUr-1647764171033)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211007223910719.png)]
unittest
pytest
Pytest安装和介绍
pip install -U pytest
C:\Users\d>pytest --version #会展示当前自己安装的版本
pytest 6.2.4
官方文档:
https://docs.pytest.org/en/latest/contents.html
https://www.osgeo.cn/pytest/contents.html
setup和teardown函数
运行于测试方法的始末,即:运行一次测试函数会运行一次setup和teardown
import pytest
class Test_ABC:
# 函数级开始
def setup(self):
print("------->setup_method")
# 函数级结束
def teardown(self):
print("------->teardown_method")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
if __name__ == '__main__':
pytest.main("[-s test_abc.py]")
setup_class和teardown_class函数
运行于测试类的始末,即:在一个测试内只运行一次setup_class和teardown_class,不关心测试类内有多少个测试函数
import pytest
class Test_ABC:
# 测试类级开始
def setup_class(self):
print("------->setup_class")
# 测试类级结束
def teardown_class(self):
print("------->teardown_class")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
if __name__ == '__main__':
pytest.main(["-s","test_abc.py"])
Pytest配置文件
pytest的配置文件通常放在测试目录下,名称为pytest.ini,命令行运行时会使用该配置文件中的配置.
#配置pytest命令行运行参数
[pytest]
addopts = -s ... # 空格分隔,可添加多个命令行参数 -所有参数均为插件包的参数配置测试搜索的路径
testpaths = ./scripts # 当前目录下的scripts文件夹 -可自定义
#配置测试搜索的文件名称
python_files = test*.py
#当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件 -可自定义
#配置测试搜索的测试类名
python_classes = Test_*
#当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件中,以Test开头的类 -可自定义
#配置测试搜索的测试函数名
python_functions = test_*
#当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件中,以Test开头的类内,以test_开头的方法 -可自定义
Pytest常用插件
插件列表网址: https://docs.pytest.org/en/latest/reference/plugin_list.html
Pytest测试报告
pytest-HTML是一个插件,pytest用于生成测试结果的HTML报告。兼容Python 2.7,3.6
]
pip install pytest-html
运行方式:
1.修改Test——App/pytest.ini文件,添加报告参数,即:addopts = -s --html=./report.html
# -s:输出程序运行信息
# --html=./report.html 在当前目录下生成report.html文件
️ 若要生成xml文件,可将--html=./report.html 改成 --html=./report.xml
2.命令行进入Test_App目录
3.执行命令: pytest
执行结果:
1.在当前目录会生成assets文件夹和report.html文件
#配置pytest命令行运行参数
[pytest]
addopts = -s --html=./report.html # 空格分隔,可添加多个命令行参数 -所有参数均为插件包的参数配置测试搜索的路径
testpaths = ./scripts # 当前目录下的scripts文件夹 -可自定义
#配置测试搜索的文件名称
python_files = test_setup.py
#当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件 -可自定义
#配置测试搜索的测试类名
python_classes = Test_*
#当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件中,以Test开头的类 -可自定义
#配置测试搜索的测试函数名
python_functions = test_*
#当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件中,以Test开头的类内,以test_开头的方法 -可自定义
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C41QCqGo-1647764171034)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010115556048.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8oePJsu3-1647764171034)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010115749926.png)]
pytest高级用法之fixture
fixture修饰器来标记固定的工厂函数,在其他函数,模块,类或整个工程调用它时会被激活并优先执行,通常会被用于完成预置处理和重复操作(如先登录获取token等)
方法:fixture(scope="function", params=None, autouse=False, ids=None, name=None)
常用参数:
scope:被标记方法的作用域 session>module>class>function
"function" (default):作用于每个测试方法,每个test都运行一次
"class":作用于整个类,每个class的所有test只运行一次 一个类中可以有多个方法
"module":作用于整个模块,每个module的所有test只运行一次;每一个.py文件调用一次,该文件内又有多个function和class
"session:作用于整个session(慎用),每个session只运行一次;是多个文件调用一次,可以跨.py文件调用,每个.py文件就是module
params:(list类型)提供参数数据,供调用标记方法的函数使用;一个可选的参数列表,它将导致多个参数调用fixture功能和所有测试使用它。
autouse:是否自动运行,默认为False不运行,设置为True自动运行;如果True,则为所有测试激活fixture func可以看到它。如果为False则显示需要参考来激活fixture ids:每个字符串id的列表,每个字符串对应于params这样他们就是测试ID的一部分。如果没有提供ID它们将从params自动生成;是给每一项params参数设置自定义名称用,意义不大。
fixture第一个例子(通过参数引用)
import pytest
class Test_ABC:
@pytest.fixture()
def before(self):
print("------->before")
def test_a(self,before): # ️ test_a方法传入了被fixture标识的函数,已变量的形式
print("------->test_a")
assert 1
if __name__ == '__main__':
pytest.main(["-s test_fixture.py"])
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6MuuZwnr-1647764171035)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010121838536.png)]
使用多个fixture
如果用例需要用到多个fixture的返回数据,fixture也可以返回一个元祖,list或字典,然后从里面取出对应数据。
import pytest
@pytest.fixture()
def test1():
a = 'door'
b = '123456'
print('传出a,b')
return (a, b)
def test_2(test1):
u = test1[0]
p = test1[1]
assert u == 'door'
assert p == '123456'
print('元祖形式正确')
if __name__ == '__main__':
pytest.main(['-s','test_fixture.py'])
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sbvd2Fpj-1647764171036)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010122103268.png)]
当然也可以分成多个fixture,然后在用例中传多个fixture参数
import pytest
@pytest.fixture()
def test1():
a = 'door'
print('\n传出a')
return a
@pytest.fixture()
def test2():
b = '123456'
print('传出b')
return b
def test_3(test1, test2):
u = test1
p = test2
assert u == 'door'
assert p == '123456'
print('传入多个fixture参数正确')
if __name__ == '__main__':
pytest.main(['-s','test_abc.py'])
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4f9hK7XL-1647764171036)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010122240691.png)]
fixture第二个例子(通过函数引用)
import pytest
@pytest.fixture() # fixture标记的函数可以应用于测试类外部
def before():
print("------->before---------")
# 1.需要前面标记了before函数,这才可以用,所以需求before函数前面标记@pytest.fixture();
# 2.前面标记了before函数,这不引用的话,执行后不执行before函数
#比如在接口测试中有需要先登录的就可以使用这个用法
@pytest.mark.usefixtures("before")
class Test_ABC:
def setup(self):
print("------->setup")
def test_a(self):
print("------->test_a")
assert 1
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7FzBHw2U-1647764171037)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010123642019.png)]
使用@pytest.mark.usefixtures()
import pytest
@pytest.fixture()
def test1():
print('\n开始执行function')
@pytest.mark.usefixtures('test1')
def test_a():
print('---用例a执行---')
@pytest.mark.usefixtures('test1')
class Test_Case:
def test_b(self):
print('---用例b执行---')
def test_c(self):
print('---用例c执行---')
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jeaIhlWF-1647764171038)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010163905077.png)]
叠加使用usefixtures
如果一个方法或者一个class用例想要同时调用多个fixture,可以使用@pytest.mark.usefixture()进行叠加。注意叠加顺序,先执行的放底层,后执行的放上层。
import pytest
@pytest.fixture()
def test1():
print('\n开始执行function1')
@pytest.fixture()
def test2():
print('\n开始执行function2')
@pytest.mark.usefixtures('test1')
@pytest.mark.usefixtures('test2')
def test_a():
print('---用例a执行---')
@pytest.mark.usefixtures('test2')
@pytest.mark.usefixtures('test1')
class Test_Case:
def test_b(self):
print('---用例b执行---')
def test_c(self):
print('---用例c执行---')
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aUgvp1ZG-1647764171038)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010164900523.png)]
fixture第三个例子(默认设置为运行)
import pytest
@pytest.fixture(scope='function',autouse=True) # 作用域设置为function,自动运行
def before():
print("------->before")
class Test_ABC:
def setup(self):
print("------->setup")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
assert 1
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-myqPjQy4-1647764171039)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010165940937.png)]
fixture 设置作用域为class
fixture方法 在整个Class类 之前运行一次
import pytest
@pytest.fixture(scope='class',autouse=True) # 作用域设置为class,自动运行
def before():
print("------->before---------")
class Test_ABC:
def setup(self):
print("------->setup")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
assert 1
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AGLeuC6O-1647764171040)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010170322337.png)]
fixtrure传参使用
发现结果运行了三次
注意:
1.此例中test_a方法被执行了三次,分别使用的数据为’1’,‘2’,‘3’,此结果类似于ddt数据驱动的功能。特别注意:这里的request参数名是固定的,然后request.param的param没有s。
2.可以把return request.param改成yield request.param,yield也是返回的意思,它和return的区别在于return返回后后面不能接代码,但是yield返回后,后面还可以接代码。
import pytest
def read_yaml():
return [1,2,3]
@pytest.fixture(params=read_yaml())
def need_data(request): # 传入参数request 系统封装参数
return request.param # 取列表中单个值,默认的取值方式
class Test_ABC:
def test_a(self, need_data):
print("------->test_a")
assert need_data != 3 # 断言need_data不等于3
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xvKtn6gW-1647764171040)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010170856872.png)]
fixture(设置作用域为module)
import pytest
@pytest.fixture(scope='module')
def test1():
b = '男'
print('传出了%s, 且在当前py文件下执行一次!!!' % b)
return b
def test_3(test1):
name = '男'
print('找到name3333333333')
assert test1 == name
class Test_Case:
def test_4(self, test1):
sex = '男'
print('找到sex444444444')
assert test1 == sex
def test_5(self, test1):
sex = '男'
print('找到sex555555555555')
assert test1 == sex
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YPhGtFdS-1647764171041)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010171756350.png)]
fixture(设置作用域为session)
fixture为session级别是可以跨.py模块调用的,也就是当我们有多个.py文件的用例的时候,如果多个用例只需调用一次fixture,那就可以设置为scope=“session”,并且写到conftest.py文件里。
conftest.py文件名称时固定的,pytest会自动识别该文件。放到项目的根目录下就可以全局调用了,如果放到某个package下,那就在该package内有效
conftest.py:
import pytest
@pytest.fixture(scope='session')
def test1():
a = 'door'
print('获取到%s' % a)
return a
import pytest
class Test_Case:
def test_3(self,test1):
b = 'door'
print('找到b')
assert test1 == b
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7ogfZE8o-1647764171042)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010174701281.png)]
如果需要同时执行两个py文件,可以在cmd中在文件py文件所在目录下执行命令:pytest -s test_abc.py test_abc.py
conftest.py的作用范围
一个工程下可以建多个conftest.py的文件,一般在工程根目录下设置的conftest文件起到全局作用。在不同子目录下也可以放conftest.py的文件,作用范围只能在改层级以及以下目录生效。
1.conftest在不同的层级间的作用域不一样
2.conftest是不能跨模块调用的(这里没有使用模块调用)
pytest跳过(Skip)及预期失败(xFail)
跳过测试函数
根据特定的条件,不执行标识的测试函数.
方法:
skipif(condition, reason=None)
参数:
condition:跳过的条件,必传参数
reason:标注原因,必传参数
使用方法:
@pytest.mark.skipif(condition, reason="xxx")
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
def test_a(self):
print("------->test_a")
assert 1
@pytest.mark.skipif(condition=2 > 1, reason="跳过该函数") # 跳过测试函数test_b
@pytest.mark.skip(reason="no reason") # -- 跳过执行测试函数 ,可传入一个非必须参数reason表示原因
def test_b(self):
print("------->test_b")
assert 0
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LA1LZ5nx-1647764171042)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010205324562.png)]
通过pytest.skip()方法跳过测试函数
import pytest
def test_01():
pytest.skip(msg="no reason")
print("---用例a执行---")
class Test_Case():
def test_02(self):
pytest.skip()
print("---用例b执行---")
def test_03(self):
print("---用例c执行---")
跳过测试类
跳过测试类其实和跳过测试方法一样,使用@pytest.mark.skip()和@pytest.mark.skipif()两个标签
根据某些条件跳过模块中的所有测试用例如:
pytestmark = pytest.mark.skipif(sys.platform == “win32”,reason=“tests for linux only”)
import pytest
myskip = pytest.mark.skip(reason="no reason")
def test_01():
print("---用例a执行---")
@myskip
class Test_Case():
def test_02(self):
print("---用例b执行---")
def test_03(self):
print("---用例c执行---")
if __name__ == '__main__':
pytest.main()
跳过模块
使用 pytestmark(不可更改变量名)变量,让他等于标签即可。
import pytest
# pytestmark = pytest.mark.skip()
pytestmark = pytest.mark.skip(reason='no reason')
def test_01():
print("---用例a执行---")
class Test_Case():
def test_02(self):
print("---用例b执行---")
def test_03(self):
print("---用例c执行---")
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nR2rvHcR-1647764171043)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010210244099.png)]
标记为预期失败函数
标记测试函数为失败函数
方法:
xfail(condition=None, reason=None, raises=None, run=True, strict=False)
常用参数:
condition:预期失败的条件,必传参数
reason:失败的原因,必传参数
使用方法:
@pytest.mark.xfail(condition, reason="xx")
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
def test_a(self):
print("------->test_a")
assert 1
@pytest.mark.xfail(2 > 1, reason="标注为预期失败") # 标记为预期失败函数test_b
def test_b(self):
print("------->test_b")
assert 0
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZtQvC2F5-1647764171044)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010210842100.png)]
pytest函数数据参数化
方便测试函数对测试数据的获取。
方法:
parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)
常用参数:
argnames:参数名
argvalues:参数对应值,类型必须为list
当参数为一个时格式:[value]
当参数个数大于一个时,格式为:[(param_value1,param_value2.....),(param_value1,param_value2.....)]
使用方法:
@pytest.mark.parametrize(argnames,argvalues)
️ 参数值为N个,测试方法就会运行N次
单个参数示例
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
@pytest.mark.parametrize("a", [3, 6]) # a参数被赋予两个值,函数会运行两遍
def test_a(self, a): # 参数必须和parametrize里面的参数一致
print("test data:a=%d" % a)
assert a % 3 == 0
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aST1SHi7-1647764171044)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010212522069.png)]
多个参数示例
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
@pytest.mark.parametrize("a,b", [(1, 2), (0, 3)]) # 参数a,b均被赋予两个值,函数会运行两遍
#a,b的值 分为2组,分别为:1,2 和 0,3 ;用例也运行2次
def test_a(self, a, b): # 参数必须和parametrize里面的参数一致
print("test data:a=%d,b=%d" % (a, b))
assert a + b == 3
if __name__ == '__main__':
pytest.main()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O9mEixc9-1647764171045)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010212845544.png)]
函数返回值类型示例
import pytest
def return_test_data():
return [(1, 2), (0, 3)]
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
@pytest.mark.parametrize("a,b", return_test_data()) # 使用函数返回值的形式传入参数值
def test_a(self, a, b):
print("test data:a=%d,b=%d" % (a, b))
assert a + b == 3
if __name__ == '__main__':
pytest.main()
robot framework
安装
官网
https://robotframework.org/
步骤一
1:安装python环境
2:安装RobotFramework
pip install robotframework
3:安装Ride
pip install wxPython==4.0.7.post2
pip install robotframework-ride==1.7.4.2
步骤二
1:安装SeleniumLibrary库
pip install robotframework-seleniumlibrary
2:安装RequestsLibrary库
pip install robotframework-requests
3:安装DatabaseLibrary库
pip install robotframework-databaselibrary
中文支持问题!!!
针对1.7.4.X版本
修改testrunnerplugin.py文件
此文件位于…\Lib\site-packages\robotide\contrib\testrunner目录下
启动
命令方式启动:
python [PythonDir]\Scripts\ride.py
F:\Program Files (x86)\Python\Python36\Scripts>python ride.py
桌面方式启动:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N4nH4rm3-1647764171045)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010215536861.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vpsm9rDT-1647764171046)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010215721278.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1P2Zqm0H-1647764171047)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010215752038.png)]
运行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PZRiyMn1-1647764171047)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010220220770.png)]
查看报告
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vztJc2jo-1647764171049)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010220614028.png)]
TestNg
IDEA+maven+java+TestNG环境搭建
新建Maven项目配置环境
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t3Gjsfpj-1647764171050)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010224703587.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5jSykA2j-1647764171050)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010224845264.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IoMvnrIw-1647764171051)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010230452707.png)]
# D:\dev\apache-maven-3.6.3\conf\settings.xml
<!-- 这里使用的是阿里的远程maven镜像,目前国内大多数都使用它 -->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
下载chrome的driver,先查看chrome的版本,再去网上查找chrome版本对照表
下载地址:http://npm.taobao.org/mirrors/chromedriver/
maven仓库搜索地址: https://mvnrepository.com/
配置 pox.xml文件
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-server -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
<version>3.14.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-chrome-driver -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>3.14.0</version>
</dependency>
</dependencies>
导入selenium-server-standalone jar包
下载地址: http://selenium-release.storage.googleapis.com/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EcYDqCGG-1647764171051)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010232032044.png)]
安装testng.xml文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A49EYC4l-1647764171052)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010232339715.png)]
重启IDEA,找到一个目录右键就会出现Create Testng xml的菜单,新建一个testng.xml文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rp4Vfmnr-1647764171053)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010232911300.png)]
testng运行demo
package framework;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.annotations.Test;
public class Testlogin {
@Test
public void login() {
System.setProperty("webdriver.chrome.driver", "E:\\Project\\testng_demo\\src\\main\\resources\\chromedriver_94.exe");
//System.setProperty("webdriver.ie.driver", "E:\\Java_project\\XTPTest_selenium\\src\\main\\resources\\IEDriverServer.exe");
//WebDriver driver= new InternetExplorerDriver();
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("http://www.baidu.com");
driver.findElement(By.id("kw")).sendKeys("selenium");
driver.findElement(By.xpath("//*[@id='su']")).click();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
driver.quit();
}
}
通过testng.xml运行测试用例
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="All Test Suite">
<test verbose="2" preserve-order="true" name="E:/Project/testng_demo">
<classes>
<class name="framework.Testlogin"></class>
</classes>
</test>
</suite>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iKgVZOhY-1647764171053)(C:\Users\d\AppData\Roaming\Typora\typora-user-images\image-20211010234646112.png)]
robotium
Robotium 是一款国外的Android自动化测试框架,主要针对Android平台的应用进行黑盒自动化测试,它提供了模拟各种手势操作(点击、长按、滑动等)、查找和断言机制的API,能够对各种控件进行操作。Robotium结合Android官方提供的测试框架达到对应用程序进行自动化的测试。另外,Robotium 4.0版本已经支持对WebView的操作。Robotium 对Activity,Dialog,Toast,Menu 都是支持的
安装
jdk、环境变量、Android SDK、Eclipse,并安装ADT插件,集成Android SDK
app移动端测试---- junit4框架,继承ActivityInstrumentation
uiautomator2
简介
uiautomator2是一个可以使用Python对Android设备进行UI自动化的库。其底层基于Google uiautomator
使用
import uiautomator2 as u2
d = u2.connect('192.168.31.234')
d = u2.connect_usb('73185eaf')
#启动微信
d.app_start("com.tencent.mm")
#搜索
d(resourceId="com.tencent.mm:id/j0").click()
#停止app
d.app_stop("com.meizu.mzbbs")
monkeyrunner
简介
monkeyrunner工具提供了一个API,使用此API写出的程序可以在Android代码之外控制Android设备和模拟器。通过monkeyrunner,您可以写出一个Python程序去安装一个Android应用程序或测试包,运行它,向它发送模拟击键,截取它的用户界面图片,并将截图存储于工作站上
使用
from com.android.monkeyrunner import MonkeyRunner,MonkeyDevice
device=MonkeyRunner.waitForConnection()
device.startActivity(component="com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity")
airtest
由于Airtest框架是基于python语言开发,本地需要搭建python相关环境,建议使用python3。
1.Python(2.7或<=3.6)下载地址:https://www.python.org/downloads/
2.AirtestIDE客户端下载:http://airtest.netease.com
3.Airtest框架安装:pip install -U airtest
4.Poco框架安装:pip install pocoui
AirtestIDE的使用教程跟文档:http://airtest.netease.com/docs/cn/index.html
打开 AirtestIDE,下载后解压,双击AirtestIDE.exe即可运行
airtest辅助窗
常用的api如下,将鼠标悬停就可以查看到对应的入参和用法
Airtest-Selenium详细API文档:http://airtest.netease.com/docs/cn/8_plugins/2_selenium.html?highlight=web
Airtest-Selenium介绍文档:http://airtest.netease.com/docs/cn/1_quick_start/5_get_started_with_web_test.html?highlight=web
装:pip install pocoui
AirtestIDE的使用教程跟文档:http://airtest.netease.com/docs/cn/index.html
打开 AirtestIDE,下载后解压,双击AirtestIDE.exe即可运行
airtest辅助窗
常用的api如下,将鼠标悬停就可以查看到对应的入参和用法
Airtest-Selenium详细API文档:http://airtest.netease.com/docs/cn/8_plugins/2_selenium.html?highlight=web
Airtest-Selenium介绍文档:http://airtest.netease.com/docs/cn/1_quick_start/5_get_started_with_web_test.html?highlight=web