之前有介绍过python
自带的Unittest
单元测试框架,Python 自动化测试实战 Zero to Hero 单元测试框架unittest的使用,今天再来简单的讲诉下测试框架pytest
本文首发自伊洛的个人博客:https://yiluotalk.com,欢迎关注并查看更多内容!!!
#####1. 安装开始
- 直接使用
pip
安装就可以,pytest
支持python
的2.0
或3.0
版本
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
pip install -U pytest
- 检查版本,校验下是否安装成功
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
(yiluo) ➜ ~ pytest --version
2. pytest的基础语法规范
- 文件名应必须以
test
开头或结尾,例如test_example.py
或example_test.py
- 如果将测试定义为类上的方法,类名应以“
Test
”开头。例如,TestExample
。且不包含__init__
方法 - 测试方法名称或函数名称应以
test_
开头,例如test_example
,名称与该模式不匹配的方法将不会作为测试执行 - 按照命名的约定举个例子
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
- demo_tests/
- test_example.py
3. 开始测试
例子1
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
(yiluo) ➜ pytest pytest
======================== test session starts =========================
platform darwin -- Python 3.7.5, pytest-5.3.2, py-1.8.0, pluggy-0.13.1
plugins: allure-pytest-2.8.6, rerunfailures-5.0
collected 1 item
test_sample.py F [100%]
============================== FAILURES ==============================
____________________________ test_answer _____________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_sample.py:6: AssertionError
========================= 1 failed in 0.05s ==========================
例子2
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
import pytest
def sum(num1, num2):
return num1 + num2
def test_sum():
assert sum(3, 7) == 10
- 运行查看结果
================================== test session starts ==================================
platform darwin -- Python 3.7.5, pytest-5.3.2, py-1.8.0, pluggy-0.13.1
plugins: allure-pytest-2.8.6, rerunfailures-5.0
collected 1 item
test_example.py . [100%]
=================================== 1 passed in 0.01s ===================================
test_example.py .
- 注意
test_example.py .
后面有一个点.
,一个点就代表执行了一条测试用例
执行多项测试 - 如果需要获取更多信息的话,后面加上
-v
collected 1 item
test_example.py::test_sum PASSED [100%]
=================================== 1 passed in 0.01s ===================================
- 再加一条用例
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
import pytest
def sum(num1, num2):
return num1 + num2
def test_sum():
assert sum(3, 7) == 10
def test_sum_output_type():
assert type(sum(1, 2)) is int
- 运行一下看下结果
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
collected 2 items
test_example.py::test_sum PASSED [ 50%]
test_example.py::test_sum_output_type PASSED [100%]
=================================== 2 passed in 0.01s ===================================
- 再试下用例执行不成功
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
import pytest
def sum(num1, num2):
return num1 + num2
def test_sum():
assert sum(3, 7) == 100
def test_sum_output_type():
assert type(sum(1, 2)) is int
- 运行查看结果
test_example.py::test_sum FAILED [ 50%]
test_example.py::test_sum_output_type PASSED [100%]
======================================= FAILURES ========================================
_______________________________________ test_sum ________________________________________
def test_sum():
> assert sum(3, 7) == 100
E assert 10 == 100
E -10
E +100
test_example.py:12: AssertionError
============================== 1 failed, 1 passed in 0.06s ==============================
例子3
- 类的举例
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
class TestClass(object):
def test_one(self):
x = 'Yiluo'
assert 'l' in x
def test_two(self):
x = 'luoyi'
assert hasattr(x, 'yiluo')
- 运行结果
(yiluo) ➜ pytest pytest
======================== test session starts =========================
platform darwin -- Python 3.7.5, pytest-5.3.2, py-1.8.0, pluggy-0.13.1
plugins: allure-pytest-2.8.6, rerunfailures-5.0
collected 2 items
test_class.py .F [100%]
============================== FAILURES ==============================
_________________________ TestClass.test_two _________________________
self = <test_class.TestClass object at 0x10c5af7d0>
def test_two(self):
x = 'luoyi'
> assert hasattr(x, 'yiluo')
E AssertionError: assert False
E + where False = hasattr('luoyi', 'yiluo')
test_class.py:8: AssertionError
==================== 1 failed, 1 passed in 0.06s =====================
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
- 用法和调用命令行还可以是
python -m pytest [...]
4. 参数化测试
- 让我们对
test_sum
函数进行更改以使用参数
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
import pytest
def sum(num1, num2):
return num1 + num2
@pytest.mark.parametrize('num1 , num2, expected', [(3, 5, 8)])
def test_sum(num1, num2, expected):
assert sum(num1, num2) == expected
def test_sum_output_type():
assert type(sum(1, 2)) is int
- 运行查看结果
collected 2 items
test_example.py::test_sum[3-5-8] PASSED [ 50%]
test_example.py::test_sum_output_type PASSED [100%]
=================================== 2 passed in 0.04s ===================================
- 多传几个参数试验一下
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
import pytest
def sum(num1, num2):
return num1 + num2
@pytest.mark.parametrize('num1 , num2, expected', [(3, 5, 8),
(-2, -2, -4), (6, 6, 12), (6, -1, 5), (0, 5, 5)])
def test_sum(num1, num2, expected):
assert sum(num1, num2) == expected
def test_sum_output_type():
assert type(sum(1, 2)) is int
- 运行查看结果
collected 6 items
test_example.py::test_sum[3-5-8] PASSED [ 16%]
test_example.py::test_sum[-2--2--4] PASSED [ 33%]
test_example.py::test_sum[6-6-12] PASSED [ 50%]
test_example.py::test_sum[6--1-5] PASSED [ 66%]
test_example.py::test_sum[0-5-5] PASSED [ 83%]
test_example.py::test_sum_output_type PASSED [100%]
=================================== 6 passed in 0.03s ===================================
- 我们还可以进行函数调用以获取这些值
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
import pytest
def sum(num1, num2):
return num1 + num2
def get_sum_test_data():
return [(3, 5, 8),
(-2, -2, -4), (6, 6, 12), (6, -1, 5), (0, 5, 5)]
@pytest.mark.parametrize('num1 , num2, expected', get_sum_test_data() )
def test_sum(num1, num2, expected):
assert sum(num1, num2) == expected
def test_sum_output_type():
assert type(sum(1, 2)) is int
- 运行查看结果
collected 6 items
test_example.py::test_sum[3-5-8] PASSED [ 16%]
test_example.py::test_sum[-2--2--4] PASSED [ 33%]
test_example.py::test_sum[6-6-12] PASSED [ 50%]
test_example.py::test_sum[6--1-5] PASSED [ 66%]
test_example.py::test_sum[0-5-5] PASSED [ 83%]
test_example.py::test_sum_output_type PASSED [100%]
=================================== 6 passed in 0.02s ===================================
5. Pytest之Fixture的使用
- 用于在测试之间共享测试数据,分别在测试执行之前和之后执行设置方法
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
import pytest
def sum(num1, num2):
return num1 + num2
@pytest.fixture()
def get_sum_test_data():
return [(3, 5, 8),
(-2, -2, -4), (6, 6, 12), (6, -1, 5), (0, 5, 5)]
def test_sum(get_sum_test_data):
for data in get_sum_test_data:
num1 = data[0]
num2 = data[1]
expected = data[2]
assert sum(num1, num2) == expected
def test_sum_output_type():
assert type(sum(1, 2)) is int
- 执行查看结果
collected 2 items
test_example.py::test_sum PASSED [ 50%]
test_example.py::test_sum_output_type PASSED [100%]
=================================== 2 passed in 0.03s ===================================
- Scope of fixture
function
: 每次测试运行一次
class
: 每类测试运行一次
module
: 每个模块运行一次
session
: 每个会话运行一次 - 权重
function < class <module<session
autouse=True
将默认使您套件中的每个测试都使用它例如1
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
import pytest
def sum(num1, num2):
return num1 + num2
@pytest.fixture(scope='session')
def get_sum_test_data():
return [(3, 5, 8),
(-2, -2, -4), (6, 6, 12), (6, -1, 5), (0, 5, 5)]
@pytest.fixture(autouse=True)
def setup_and_teardown():
print('\n获取数据')
yield
print('\n保存数据')
def test_sum(get_sum_test_data):
for data in get_sum_test_data:
num1 = data[0]
num2 = data[1]
expected = data[2]
assert sum(num1, num2) == expected
def test_sum_output_type():
assert type(sum(1, 2)) is int
- 执行后查看结果
pytest test_example.py -v -s
collected 2 items
test_example.py::test_sum
获取数据
PASSED
保存数据
test_example.py::test_sum_output_type
获取数据
PASSED
保存数据
=================================== 2 passed in 0.02s ===================================
例如2
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
import pytest
@pytest.fixture()
def setup():
print('在测试之前')
def test_one(setup):
print('测试1')
def test_two(setup):
print('测试2')
- 执行结果
(yiluo) ➜ pytest pytest -v -s fixture.py
======================== test session starts =========================
platform darwin -- Python 3.7.5, pytest-5.3.2, py-1.8.0, pluggy-0.13.1 --
cachedir: .pytest_cache
rootdir: /Users/joey/Code/pytest
plugins: allure-pytest-2.8.6, rerunfailures-5.0
collected 2 items
fixture.py::test_one 在测试之前
测试1
PASSED
fixture.py::test_two 在测试之前
测试2
PASSED
========================= 2 passed in 0.01s ==========================
fixture
返回值
import pytest
@pytest.fixture(params=[1, 2, 3])
def test_data(request):
return request.param
def test_assert_all(test_data):
print('test_data: %s' % test_data)
assert test_data != 5
(yiluo) ➜ pytest pytest -v -s fixture_param.py
======================== test session starts =========================
platform darwin -- Python 3.7.5, pytest-5.3.2, py-1.8.0, pluggy-0.13.1 -- /Users/joey/yiluo/bin/python3
cachedir: .pytest_cache
plugins: allure-pytest-2.8.6, rerunfailures-5.0
collected 3 items
fixture_param.py::test_assert_all[1] test_data: 1
PASSED
fixture_param.py::test_assert_all[2] test_data: 2
PASSED
fixture_param.py::test_assert_all[3] test_data: 3
PASSED
========================= 3 passed in 0.01s ==========================
6. pytest.mark
- skip — 跳过测试功能
- skipif — 如果满足特定条件,则跳过测试功能
- xfail — 如果满足特定条件,则会产生“预期的失败”结果
- parametrize执行对同一测试功能的多次调用
#!/usr/bin/python3
# 伊洛Yiluo
# https://yiluotalk.com
import pytest
def sum(num1, num2):
return num1 + num2
@pytest.mark.skip
def test_sum():
assert sum(3, 7) == 10
def test_sum_output_type():
assert type(sum(1, 2)) is int
- 执行查看结果
collected 2 items
test_example.py::test_sum SKIPPED [ 50%]
test_example.py::test_sum_output_type PASSED [100%]
============================= 1 passed, 1 skipped in 0.01s ==============================
- 成功跳过测试用例
- 运行的方式
名称中带有“ validate”字符串的所有测试
pytest -k “validate”
排除名称中带有“ db”的测试,但包括“ validate”
pytest -k “validate and not db”
运行文件夹demo_tests中的所有测试文件
pytest demo_tests/
运行测试类TestClassDemo的单个方法test_method
pytest demo_tests/test_example.py::TestClassDemo::test_method
运行一个名为TestClassDemo的测试类
pytest demo_tests/test_example.py::TestClassDemo
运行一个名为test_sum的测试函数
pytest demo_tests/test_example.py::test_sum
以详细模式运行测试
pytest -v demo_tests/
运行包括打印语句的测试
pytest -s demo_tests/
仅运行上次运行失败的测试
pytest — lf
欢迎下方【戳一下】【点赞】
Author:伊洛Yiluo
愿你享受每一天,Just Enjoy !