Pytest简单入门
Pytest是一个易用、强大、灵活的功能测试框架。
- 易用: 用例编写简单, 断言方便
- 强大: 全能的mark, 强大的fixtures
- 灵活: 灵活的执行控制及丰富的插件
安装方法
pip install pytest
用例编写
Pytest可以使用函数或者类来编写测试用例,一般来说,测试脚本文件应以test开头,测试函数应以test开头,测试类应以Test开头,作为标识。
例如: test_example.py
def test_example1():
assert 1 + 1 == 2
class TestModule1:
def test_example2(self):
assert 0
断言
Pytest使用Python中的assert语句进行断言,assert语句也可以自定义断言失败信息。
例如:
def test_example3():
assert 1 + 1 == 2
assert 1 > 0 is True
assert {"name": "kevin"}.get("name") is not None
# 自定义断言失败信息
assert "a" in ["a", "b", "c"], '断言是不:["a", "b", "c"]不包含"a"'
异常断言(断言抛出了指定异常)
with pytest.raises(Exception):
例如:
import pytest
with pytest.raises(ZeroDivisionError):
1 / 0
用例标记
自定义用例标记
在测试函数或测试类上可以使用@pytest.mark.xxx
,为用例添加自定义标记,(在严格模式下,所有自定义标签应在pytest.ini文件中提前注册)。
运行用例时,可以使用-m
参数,指定标签(支持and or not)筛选用例运行, 如
pytest -m "apitest and level1"
用例跳过或期望失败
@pytest.mark.skip(reason)
:无条件跳过用例@pytest.mark.skipif(condition, reason)
:根据条件跳过用例@pytest.mark.xfail(reason)
:用例期望失败
在用例中可以使用pytest.skip()
,pytest.xfail()
或 pytest.fail()
强制设置用例跳过、期望失败或者失败
例如:
import pytest
def test_a():
if 1 > 0:
pytest.skip()
# pytest.xfail()
# pytest.fail()
用例和运行
通过pytest
命令,可以实现非常灵活的执行控制
Pytest运行模式
-
-q
: 安静模式, 不输出环境信息 -
-v
: 丰富信息模式, 输出更详细的用例执行信息 -
-s
: 显示程序中的print/logging输出 -
运行目录及子包下的所有用例:
pytest <目录名>
-
运行指定模块所有用例:
pytest test_reg.py
-
运行指定模块指定类指定用例:
pytest test_reg.py::TestClass::test_method
-
运行名称包含指定表达式的用例:-k 表达式(支持and or not),如
pytest -k "test_a and test_b"
-
运行指定标签(mark)的用例: -m 标签(支持and or not), 如
pytest -m "apitest and level1"
-
遇到失败后停止:-x/--exitfirst 首次失败后退出(可用于保留出错现场) --maxfails=3 3次失败后退出
-
执行上次失败的用例:
pytest --lf/--last-failed
-
先执行上次失败的用例,再执行成功的用例:
pytest --ff/--failed-first
-
只收集用例,不执行:
pytest --collect-only
-
显示执行最慢的前N条用例:--durations=N
测试准备及清理
Pytest提供模块/类/方法及函数及的测试准备(setup)和测试清理(teardown)方法。
- def setup_module():模块级测试准备
- def teardown_module():模块级测试清理
- def setup_class(self):类级测试准备
- def teardown_class(self):类级测试准备
- def setup_method(self):类级测试准备
- def teardown_method(self):类级测试准备
- def setup_method(self):类级测试准备
- def teardown_method(self):类级测试准备
例如:test_example2.py
def setup_module():
print('测试模块准备')
def teardown_module():
print('测试模块清理')
def setup_function():
print('---测试函数准备---')
def teardown_function():
print('---测试函数清理---')
def test_1():
print('test_1')
def test_2():
print('test_2')
class TestModule2(object):
def setup_class(self):
print('测试类准备')
def teardown_class(self):
print('测试类清理')
def setup_method(self):
print('测试方法准备')
def teardown_method(self):
print('测试方法清理')
def test_3(self):
print('test_3')
def test_4(self):
print('test_4')
自定义Fixture函数
Test Fixture即测试准备+测试清理方法,Fixture函数中使用yield分隔setup和teardown方法。也可以使用return
只包含setup测试准备。
例如:
import pytest
@pytest.fixture(scope='function', autouse=False)
def my_fixture():
print("setup ...")
yield "some result"
print("teardown ...")
Fixture函数参数:
- scope: 生效范围,支持session,package,module,class,function,默认为function
- autouse: 是否自动使用,默认为False
Fixture函数可以相互依赖,形成一种步骤递进关系。
Fixture函数可以写到conftest.py中来进行共享
参数化
Pytest中可以使用@pytest.mark.parametrize
进行参数化测试,即数据驱动测试。
例如:
import pytest
data = [(1,2,3), (-2, 4, 2), (0, 0, 0), (1.1, -2.2, -1.1)]
@pytest.mark.parametrize('a, b, expected', data)
def test_add(a, b, expected):
url = f'http://115.28.108.130:5000/add/?a={a}&b={b}'
actual = a + b
assert expected == actual