一、Pytest简介
1. 简介
- Pytest是Python的一种单元测试框架
- 支持单元测试、selenium/appium自动化测试、接口自动化测试(python+requests)
- Pytest官网:https://docs.pytest.org/en/latest/contents.html#toc
- 第三方库:https://pypi.org/search/?q=pytest
- 简单灵活
- 支持参数化
- 支持重复执行失败的测试用例
- 支持运行时跳过某些测试用例
- 支持运行unittest编写的方法和函数
- 具有很多第三方插件:pytest-allure(html测试报告),pytest-xdist(多CPU分发),pytest-sugar
- 可以很好的和jenkins集成
2. 安装
pip install pytest
pip install -U pytest # 升级ytest
pytest -h # pytest帮助文档
pytest --version #查看pytest版本
二、Pytest基础用法
1. 示例
class TestDemo():
def setup(self):
print("setup方法")
def teardown(self):
print("teardown方法")
def test_demo(self):
a = 5
b = -1
assert a != b
print("test_demo")
2. Pytest编写规范
- 测试文件以test_开头
- 测试类以Test开头,并且不能带有__init__方法
- 测试函数以test_开头
- 所有package都要有init文件
3. Pytest - setup/teardown
函数级(setup_function/teardown_function):不在类中的函数开始和结束时各调用一次
方法级(setup_method/teardown_method):类中的方法开始和结束各调用一次
类级(setup_class/teardown_class):类的开始和结束各调用一次
模块级(setup_module):文件的开始和结束各调用一次
说明:对于一个脚本中,部分测试用例需要前置,部分用例不需要前置的情况,setup/teardown方法就不太适用了。可以用fixture解决。
4. Pytest - 断言
- 常用断言
assert a 判断a为真
assert not a 判断a不为真
assert a in b 判断b包含a
assert a == b判断a等于b
assert a != b判断a不等于b - 支持多个assert
说明:如果第一条断言失败,则不会继续运行下一条断言。可以用插件assume解决
def test_01():
a = 5
b = -1
assert is_true(a)
assert not is_true(b)
7.Pytest - 自定义marks
应用场景:运行指定的用例,如冒烟测试
用法:
- 在类或方法前添加@pytest.mark.smoke
- 运行:pytest -m smoke
示例:
跳过某个测试skip
用法:@pytest.mark.skip(reason = “原因”)
如果满足条件就跳过skipif,比如版本为2.42就执行
用法:@pytest.mark.skipif(表达式)
意料之中的失败xfail
用法:@pytest.mark.xfail(raise=RuntimeError)
7. Pytest - 用例执行方式
pytest filename.py
pytest -v -s filename.py
运行出错时停止运行
pytest -v -s -x filename.py maxfail=2
4. Pytest - 参数化
- @pytest.mark.parametrize(“x,y”,[(3,5),(4.6),(5,7)])
- @pytest.mark.parametrize(“username,pass”,[(“usr1”,“pass1”),(“usr2”,“pass2”)])
- @pytest.park.parametrize(“login_r”,test_user_data,indirect=True)#把login_r当作函数去执行
- 执行一个module
- pytest -v src/testcases/api/test_autouser.py
- 执行一个类,一个方法
- pytest -v src/testcases/api/test_autouse.py::TestSample
- pytest -v src/testcases/api/test_autouse.py::TestSample::test_answer
- 执⾏⼀个⽬录或者package
- pytest -v src/testcases/api
- 通过标签来运⾏测试⽤例
- pytest -m P0 src/testcases/api
- 通过pytest.main来执⾏,所有的参数和pytest命令⾏⽅式是一样的
- pytest.main(['-v', '--instafail', 'testcases/api/test_example.py', '-m=P2'])
- pytest -k
Pytest - fixture
应用场景:脚本中部分用例需要登录,一部分用例不需要登录
说明:
-
setup和teardown是针对测试脚本全局来设置的,没办法只针对某个方法来设置。假如遇到一些用例1需要提前登陆,用例3不需要提前登陆,到了用例5又要登陆,这种场景的用setup就显得很无助了,这时就可用fixture的方式替换setup/teardown了
-
fixture的命名方式很灵活
-
fixture不需要导入
-
fixture还可以实现多个模块-py文件共用一个session的情况,即:scope=session方式
用法:- 在该fixture方法或类前加@pytest.fixture()
- 在需要该fixture方法的用例参数里,添加该方法的名称
- @pytest.fixture(scope=“module”)
- 默认function级别
-
a.这里可以放在包中即类之外的方法前;也可以在类内测试方法前,也可放在类名前,放在类前是对类内所有测试方法起作用。
b.如果class用例需要同时调用多个fixture,可以使用@pytest.mark.usefixtures()叠加。注意叠加顺序,先执行的放底层,后执行的放上层
c.如果fixture装饰器有返回值,那么用usefixtures就无法获取到返回值,这个便是usefixtures和用例参数中直接传装饰器名的区别。也就是说当装饰器fixture的return值需要使用时,只能在用例里面传fixture参数了;当用例中不需要装饰器fixture的return值的时候,两种方法都可以 fixture通过固定参数request传递 @pytest.fixture(params=[1,2,3,4]) @pytest.fixture(params=["name","pass",1,2,3,4])
示例:
Pytest - conftest.py
- conftest介绍:
- conftest.py可以实现数据的共享,包括参数、方法等
- 在使用时不需要通过import来导入conftest,pytest会自动在用例py文件中识别同目录下的conftest.py里的通过@pytest.fixture装饰的方法。
- conftest使用时候需要配合fixture一块使用。
- 使用fixture的conftest方式可以跨模块(py文件)来共享前置、后置数据,而且在调用时不需要导入fixture修饰的方法,即:scope="module"方式
- 文件名不能修改
- conftest.py作用域:conftest.py所在路径下的所有文件
- fixture和conftest的区别:fixture适用于在同一个py文件中,多个用例执行时的使用;而conftest.py方式适用于多个py文件之间的数据共享。
- 应用场景:测试前后的初始化设置,如测试数据准备,链接数据库,打开浏览器等这些操作都可以使用fixture来实现
- yield
三、Pytest第三方插件
Pytest - assume
说明:前一条断言失败,可以继续运行下一条断言
安装:pip install pytest-assume
用法:
pytest.assume(1 == 4)
pytest.assume(2 == 4)
Pytest - rerunfails
安装:pip install pytest-rerunfailures
用法:
pytest --reruns 3 -v -s test_reruns_10.py
pytest -v --reruns 5 --reruns-delay 1
4. Pytest - pytest-html
安装:pip install pytest-html
用法:pytest -v -s --html=report.html
3. Pytest - allure
安装:brew install allure
官网:http://allure.qatools.ru/
GitHub地址:https://github.com/allure-framework/allure2/releases
下载zip包,解压,进入bin目录运行,把bin目录加入path路径
allure --version
pip install allure-pytest
#在测试执行期间生成测试报告
pytest -s -q --alluredir=./result/
#查看测试报告
allure serve ./result/
pip install sugar
pip install pytest-rerunfailures
pip install pytest-xdist
pip install pytest-assume
pip install pytest-html
pytest -xdist 分布式执行
说明:多个CPU执行
前提:用例之间都是独立的,没有先后顺序,随机都能执行,可重复运行,不影响其他用例
安装:pip install pytest-xdist
用法:pytest -n 3
- -n3是并行数量
- 注意数量需要小于电脑内核数;在多个终端下一起执行
Pytest - ordering
说明:设置执行顺序
安装:pip install pytest-ordering
用法:@pytest.mark.run(order=n),n=1,2,3…
- @pytest.mark.last,最后一个运行
示例:
import pytest
@pytest.mark.run(order=1)
def test_01():
print('test01')
@pytest.mark.run(order=2)
def test_02():
print('test01')
# @pytest.mark.last
def test_06():
print('test01')
def test_04():
print('test01')
def test_05():
print('test01')
@pytest.mark.run(order=3)
def test_03():
print('test01')
pytest中有个hook函数pytest_collection_modifyitems
pytest-cache功能:
重跑上次失败的用例,持续集成中很实用,提高分析效率,强烈推荐
--lf --ff --nf
pytest-sugar功能:
改变了pytest的默认外观,增加了一个进度条,并立即显示失败的测试。
pytest-dependency功能:
用 @pytest.mark.dependency()对所依赖的方法进行标记,使用@pytest.mark.dependency(depends=[“test_name”])引用依赖
另一种方式:用@pytest.mark.dependency(name=‘a’)对所依赖的方法进行标记,使用@pytest.mark.dependency(name=“b”, depends=[“a”])引用依赖