记录 pytest 与 python selenium web 自动化的基本使用
文章目录
介绍
pytest 是 python 的一个开源库,可根据一定规则执行特定的代码块。
官网
https://pytest.org/
使用文档
https://docs.pytest.org/en/stable/getting-started.html
安装
python 环境
安装python 环境及pip包管理器
对于 Windows10 环境,在 PowerShell 中输入 python 确定是否已安装,如未安装,则会自动连接到 Windows Store 的 Python 安装选项,直接点击安装即可自动完成 Python 及 pip 的安装。
安装完成后需要配置环境变量。
一般 Windows Store 下载的软件安装路径在以下目录
C:\Users\username\AppData\Local\Microsoft\WindowsApps
通过 pip 安装的模块包的执行程序会在以下路径
C:\Users\username\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\Scripts
编译器
一般推荐 pycharm ,使用其他编译器亦可。
- 中文语言包
pycharm 安装完成后可配置中文语言,在 " file -> settings -> plugins -> Marketplace " 中搜索选择 中文语言包 安装即可。 - 问题处理
pycharm 创建项目时可选择 python 环境,可设置为 pycharm 创建的虚拟环境 virtenv 及 本机的 pipenv。
virtenv 环境针对特定项目。
pipenv 环境则可通用于所有项目。- pipenv的配置使用
- 安装
- pipenv的配置使用
pip install --user pipenv
如安装过程中有提示不在环境变量中,则增加配置环境变量即可。
另需要注意pip下载目录需要有读写权限,有些系统环境可能对应的目录为只读,此时安装会一直不成功,取消只读即可。
python 组件安装
可将所需的组件名称保存到 requirements.txt 中,一次安装所有所需组件。
pip install -r requirements.txt
安装 pytest
pip install pytest
安装 selenium
pip install selenium
webdriver 驱动文件
浏览器的 webdriver 驱动文件可以放置到 Scripts 目录,需要注意的是,在使用时,对应的 浏览器 调用路径需要指定或添加到环境变量。
web 自动化
基础内容
步骤
- 导入库
- 打开浏览器
- 访问网站
- 元素定位
- 操作
xpath
- 定位首个元素
webdriver.find_element_by_xpath('//*[@id="floor-user-profile_485"]//h4')
- 定位多个元素
webdriver.find_elements_by_xpath('//*[@id="floor-user-profile_485"]//h4')
元素操作
url 为访问地址
locator 为元素位置
====
打开浏览器 driver= webdriver.Firefox()
窗口最大化 driver.maximize_window()
访问url driver.get(str(url))
点击元素 driver.find_element_by_xpath(locator).click()
输入字符串 driver.find_element_by_xpath(locator).send_keys(str(value))
进入iframe标签 driver.switch_to.frame(self.driver.find_element_by_xpath(str(locator)))
退出浏览器 driver.quit()
网页打开加载元素可能又异步加载,会导致部分元素未加载完成不能定位到元素。
可使用浏览器隐式等待,每隔一秒钟自动寻找元素,找到元素了就继续后续操作,一段时间仍未找到则报错.
隐式等待在整个driver周期生效,添加一次即可,与sleep区分。
隐式等待在获取到元素后即进行下一步操作,但可能存在某些元素的size或其他属性未加载完全,需要固定等待以辅助元素获取。
设置隐式等待 webdriver.Chrome().implicitly_wait(10)
Po 设计模式
对象化,将每个用例封装成单独的函数方法
class Test:
def login(self):
print('s')
if __name__ == '__main__'
test = Test()
test.login()
requirements.txt
selenium
pytest
pytest-rerunfailures
pytest-xdist
allure-pytest
pytest 拓展使用
- web自动化测试
- pytest + selenium/appnium
- 接口自动化
- pytest + requests
- 第三方插件拓展
- pytest-selenium(集成selenium)
- pytest-html(完美html测试报告生成)
- pytest-rerunfailures(失败case重复执行)
- pytest-xdist(多CPU分发)
pytest 组成
- 测试模块
- 测试类
- 测试用例
运行方法
- pycharm
- 命令行
pytest 规则
pytest 默认的规则如下,
- 测试模块必须以test_开头或_test结尾。
- 测试类 class 必须以 Test 开头,且不能有 构造函数 init 方法。
- 测试用例(测试函数 def )必须以 test_ 开头。
example_test.py 或 test_example.py --py脚本
class Test_M1: --测试类,项目或模块的用例集合,可无测试类直接编写测试函数
def setup_class(self): ---前置用例或前置条件,在 用例集 执行前会先执行,只执行一次
....
def setup(self): ---在每个用例执行前,执行一次
...
def teardown_class(self): ---后置用例或后置条件,在 用例集 执行完成后执行,只执行一次
...
def teardown(self): -- 在每个用例执行后,执行一次
...
def test_login(self): -- 测试函数、测试用例,实际执行的内容
....
...
-----------------------------
@pytest.fixture() -----使在特定用例开始前可以执行 @pytest.fixture() 下的函数
def myinit(self):
"""
fixture 先于 setup 执行
"""
print('test start')
"""
yield 后于 teardown 执行
"""
yield
print('test down')
-------------------------------
def test_logout(self,myinit): ---在该用例执行前,先执行 myinit 函数
......
def test_login2(): ---没有测试类或测试集,直接写 测试函数/测试用例,此处函数无 self 参数,若添加了 self 参数,可能会因为没有测试类而导致报错 fixture 'self' not found
...
"""
参数化,有多少个参数,测试函数就跑多少次.
每行的参数个数一一对应
"""
testparam =
[
[1,1],
[2,2],
[3,3]
]
@pytest.mark.parametrize('x,y', testparam)
def test_sum(self,x,y):
print( sum(x,y) )
#对于功能用例,需要添加结果验证,如当前窗口url,窗口名称,页面的特有元素等,若为接口用例,则考虑接口返回状态码,返回的内容等。可使用断言 assert 判断
webdriver.current_url --------获取当前窗口 url
webdriver.title ---------------获取当前窗口名称
assert webdriver.current_url == homepage_url
#获取当前窗口句柄,即选中操作该窗口
cur_handle = webdriver.current_window_handle
#获取所有窗口句柄
all_handle = webdriver.window_handles
#切换窗口
webdriver.switch_to.window(cur_handle)
设置pytest用例执行顺序
可以通过 pytest-ordering 插件进行控制
pip install pytest-ordering
在用例前头加上以下语句即可控制顺序
@pytest.mark.run(order=11)
def test_SysManager_click(self):
self.web.click('//span[contains(text(),"系统管理")]')
需要注意:pytest执行,会先执行有 order 标志的用例(不管其编号从何开始,中间是否有间隔),在执行完 order 标志的用例后,再执行无标记的用例。如 order 之前的用例为关键用例如打开url或登录,其会在 order 执行结束后再执行,由此可能会导致 order 缺少前期的关键用例而导致失败。
建议关键性用例都加上 order 以确定顺序。
标记用例是否执行
@pytest.mark.skip(reason=None) -------标记无条件跳过该用例,reason 为可选参数
@pytest.mark.skip
def test_SysManager_click(self):
@pytest.mark.skipif(condition,reason=None) --------标记有条件跳过该用例,condition 为跳过条件,必传参数,reason 为必传参数
@pytest.mark.skipif(condition = 2>1 , reason = 'xxxxxx')
def test_SysManager_click(self):
用例分组
可以用 @pytest.mark.groupname 来对用例进行标记分组。
@pytest.mark.test1
@pytest.mark.test2
def test_a(self):
一个用例可以被标记多个组
执行:
pytest -s -m "test1"
pytest -s -m "test2"
若有以下警告信息
PytestUnknownMarkWarning: Unknown pytest.mark.test4 - is this a typo?
为标签不生效导致,在 pytest.ini 配置文件加入以下配置即可
[pytest]
markers = test1
test2
test3
test4
用例重复执行
可以使用 pytest-repeat 插件进行用例的重复执行
标记某用例重复执行
@pytest.mark.repeat(2)
def test_a(self):
命令执行时指定重试
pytest -s --reruns=3 --count=3 test_a.py
--reruns=3 失败时重试运行3次
--count=3 重复执行3次
pytest --count=100 -x test_a.py
重复执行直到失败,重复执行最大次数为100次
上述为针对每个用例重复执行,即 1 1 1 2 2 2 这样的效果,若要 1 2 1 2 1 2 这样的效果则需要添加 --repeat-scope 参数
- function(默认)范围针对每个用例重复执行,再执行下一个用例
- class 以class为用例集合单位,重复执行class里面的用例,再执行下一个
- module 以模块为单位,重复执行模块里面的用例,再执行下一个
- session 重复整个测试会话,即所有收集的测试执行一次,然后所有这些测试再次执行等等
使用--repeat-scope=session重复执行整个会话用例
pytest-repeat不能与unittest.TestCase测试类一起使用。无论–count设置多少,这些测试始终仅运行一次,并显示警告.
执行
三种方式
- pycharm 直接右键执行
- python 文件中通过命令执行
import pytest pytest.main(['-s','data/test_data.py'])
- 命令行调用 pytest 执行
pytest -s --reruns=2 --count=3 test_a.py 在错误时重试2次, 重复执行3次 pytest test_a.py::Test_Clas::test_003 运行 test_a.py 文件中的 Test_Clas 类的 test_003 用例方法 , :: 作为用例的分层
pytest ini配置文件
可通过创建 pytest 配置文件,自定义配置规则及运行参数。
pytest.ini 内容:
[pytest]
python_files = test_*.py *_test.py -----可修改默认识别的python文件名规则
python_classes = Test* ---------可修改默认识别的类名规则
python_functions = Test* ---------可修改默认识别的方法函数规则
addopts = -s --count=2 --------可指定pytest运行时自动添加的参数
conftest.py 配置文件
conftest.py 文件可用于存放用例之外的设置,如 @pytest.fixture() 等非用例的方法;
其与用例文件在同一目录,就作用于这个目录;
同目录的测试文件在运行前都会先执行 conftest.py 文件;
同级目录下必须要存在 init.py 文件;
不用被其他文件导入,放着就生效;
import pytest
@pytest.fixture()
def getsome():
a = 'test case begin'
print("startk")
return a
生成报告
- python 运行报告
在右键或python文件命令执行后,在下方结果栏的选项中有导出报告 选项,点击即将结果生成 html 文件,但结果较为简单。
亦可通过命令行指定生成报告pytest --html=report.html test_a.py 依赖 pytest-html 插件,若执行报错考虑是否尚未安装插件导致 pip install pytest-html
- allure 报告
注意需要先创建 temp 目录及 report 目录import pytest import os import allure if __name__ == '__main__': pytest.main(['-v','-s','--count','10','--repeat-scope','session','--html=result2V.html','test_data.py','--alluredir','./temp']) os.system('allure generate ./temp -o ./report --clean')