一、简介
pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,但是比unittest框架使用起来更简洁,效率更高。
二、安装
安装方法:
1 pip install -U pytest
安装成功,查询安装的版本号
1 pytest --version
pytest常用的插件
pytest-selenium 集成 selenium
pip install allure-pytest 生成漂亮的allure测试报告
pip install pytest-sugar 优化运行效果
pip install pytest-rerunfailures 执行用例失败后重新运行
pip install pytest-xdist 多线程并行与分布式执行
pip install pytest-assume 多条断言前面报错后面依然执行
pip install pytest-cover 测试覆盖率
三、Demo
新建test_one.py,输入以下代码,cmd至文件目录下,输入pytest运行
1 def func(x): 2 return x + 1 3 def test_answer(): 4 assert func(3) == 5 5 #assert func(3) == 4
运行pytest命令,或py.test命令,或python –m pytest命令。(pytest的三种运行方式)
用例不通过与用例通过的结果展示,如下图所示。
四、用例设计原则
- 文件名以test_*.py文件*_test.py
- 测试类以Test开头,并且不能带有init方法
- 以test_开头的函数
- 以Test开头的类
- 以test_开头的方法
- 所有的包pakege必须要有__init__.py文件
- 断言使用assert
五、断言
pytest允许你使用标准Python断言来验证Python测试中的期望值。
常用断言
pytest里面断言实际上就是python里面的assert断言方法,常用的有以下几种:
assert xx 判断xx为真
assert not xx 判断xx不为真
assert a in b 判断b包含a
assert a == b 判断a等于b
assert a != b 判断a不等于b
六、装饰器
pytest.mark.skip 可以标记无法在某些平台上运行的测试功能,或者希望失败的测试功能。
skip if意味着在不满足某些条件时才希望测试通过,否则 pytest应该跳过运行测试。 常见示例是在非 Windows 平台上跳过仅限Windows 的测试,或跳过测试依赖于当前不可用的外部资源。
xfail 意味着你希望测试由于某种原因而失败。 一个常见的例子是对功能的测试尚未实施,或尚未修复的错误。。
skip
跳过测试函数的最简单方法是使用跳过装饰器标记它,可以传递一个可选的原因。
例:
@pytest.mark.skip(reason=“本轮测试不执行此用例")
def test_the_unknown():
skipif
如果你希望有条件地跳过某些内容,则可以使用 skipif 代替。
例:
import sys
@pytest.mark.skipif(sys.version_info < (3,6),
reason="requires python3.6 or higher")
自定义标记 mark
pytest 可以支持自定义标记,自定义标记可以把一个 web 项目划分多个模块,然后指定模块名称执行。
@pytest.mark.webtest
def test_send_http():
如果不想执行标记 webtest 的用例,那就用”not webtest”
七、Fixture
unittest 的都知道里面用前置和后置 setup 和 teardown 非常好用,在每次用例开始前和结束后都去执行一次。
setupClass 和 teardownClass,需配合@classmethod 装饰器一起使用。
用例运行级别
- 模块级(setup_module/teardown_module)开始于模块始末,全局的
- 函数级(setup_function/teardown_function)只对函数用例生效(不在类中)
- 类级(setup_class/teardown_class)只在类中前后运行一次(在类中)
- 方法级(setup_method/teardown_method)开始于方法始末(在类中)
- 类里面的(setup/teardown)运行在调用方法的前后
运行的优先级
setup_class>setup_method>setup >用例>teardown> teardown_method>teardown_class
函数和类混合
如果一个.py 的文件里面既有函数用例又有类和方法用例,运行顺序如下:
setup_module/teardown_module 的优先级是最大的。
函数里面用到的 setup_function/teardown_function和类里面的 setup_class/teardown_class 互不干涉
Fixture优势
命名方式灵活,不局限于setup和teardown这几个命名
conftest.py 配置里可以实现数据共享,不需要import就能自动找到一些配置
scope=”module” 可以实现多个.py跨文件共享前置
scope=”session” 以实现多个.py跨文件使用一个session来完成多个用例
1 fixture(scope="function", params=None, autouse=False, ids=None, name=None): 2 """使用装饰器标记fixture的功能 3 可以使用此装饰器(带或不带参数)来定义fixture功能。 fixture功能的名称可以在以后使用 4 引用它会在运行测试之前调用它:test模块或类可以使用pytest.mark.usefixtures(fixturename标记。 5 测试功能可以直接使用fixture名称作为输入参数,在这种情况下,夹具实例从fixture返回功能将被注入。 6 7 :arg scope: scope 有四个级别参数 "function" (默认), "class", "module" or "session". 8 9 :arg params: 一个可选的参数列表,它将导致多个参数调用fixture功能和所有测试使用它 10 11 :arg autouse: 如果为True,则为所有测试激活fixture func 可以看到它。 如果为False(默认值)则显式需要参考来激活fixture 12 13 :arg ids: 每个字符串id的列表,每个字符串对应于params 这样他们就是测试ID的一部分。 如果没有提供ID它们将从params自动生成 14 15 :arg name: fixture的名称。 这默认为装饰函数的名称。 如果fixture在定义它的同一模块中使用,夹具的功能名称将被请求夹具的功能arg遮蔽; 解决这个问题的一种方法是将装饰函数命名 16 “fixture_”然后使用”@ pytest.fixture(name =' ')“”。
参数解析
fixture(scope="function", params=None, autouse=False,ids=None, name=None):
scope 有四个级别参数:function, class、Module、session
params: 一个可选的参数列表,它将导致多个参数调用fixture 功能和所有测试使用它。
autouse: 如果为 True,则为所有测试激活 fixture func 可以看到它。 如果为 False(默认值)则显式需要参考来激活 fixture
每个字符串 id 的列表,每个字符串对应于 params 这样他们就是测试 ID 的一部分。 如果没有提供 ID 它们将从 params 自动生成。
name: fixture 的名称。 这默认为装饰函数的名称。
conftest.py配置
conftest.py 配置脚本名称是固定的,不能改名称
conftest.py 和运行的用例要在同一个 pakage 下,并且有__init__.py 文件
不需要 import 导入 conftest.py, pytest 用例会自动查找
yield 执行 teardown
yield:提供fixture 里面的 teardown 功能,用 yield 来唤醒teardown的执行
yield 遇到异常
1.如果其中一个用例出现异常,不影响 yield 后面的 teardown 执行,运行结果互不影响,并且全部用例执行完成后, yield 呼唤 teardown操作。
2.如果在 setup 就异常了,那么是不会去执行 yield 后面的teardown 内容了。
3.yield 也可以配合 with 语句使用。
Fixture参数化
pytest.mark.parametrize 装饰器可以实现测试用例参数化 它也可以标记单个测试实例在参数化 参数组合 若要获得多个参数化参数的所有组合,可以堆叠参数化装饰器