Pytest是一个基于python的测试框架,用于编写和执行测试代码。在REST服务的今天,pytest主要用于API测试,尽管我们可以用pytest来编写简单到复杂的测试,即我们可以编写代码来测试API、数据库、UI等
Pytest的优点如下:
- Pytest可以并行运行多个测试,从而减少测试套件的执行时间。
-
如果没有明确提到,Pytest有自己的方式来自动检测测试文件和测试功能。
-
Pytest允许我们在执行过程中跳过测试的一个子集。
-
Pytest允许我们运行整个测试套件的一个子集。
-
Pytest是免费和开源的。
-
由于其简单的语法,pytest非常容易上手。
1.环境搭建
首先需要我们需要安装pytest安装包
pip install pytest # 后面可以加等号指定pytest的版本号
2.pytest识别测试函数和测试文件
运行pytest而不提及文件名,将运行当前目录和子目录中所有格式为 test_*.py 或 *_test.py 的文件。Pytest自动将这些文件识别为测试文件。我们 可以 通过明确提及其他文件名来使pytest运行这些文件。
Pytest要求测试函数名以 test 开头 。 非 test*** 格式的函数名不会被pytest认为是测试函数。我们 **不能 明确地让pytest将任何不以 test 开头的函数视为测试函数。
3.pytest基本测试
让我们按照下面的步骤来做 –
- 创建一个名为 automation 的新目录,并在命令行中导航到该目录。
-
创建一个名为 test_square.py 的文件,并在该文件中添加以下代码。
import math def test_sqrt(): num = 25 assert math.sqrt(num) == 5 def testsquare(): num = 7 assert 7*7 == 40 def tesequality(): assert 10 == 11
我们切换到 automation 目录下,在Termial中执行pytest
命令执行结束会产生下面的结果
test_square.py .F ============================================== FAILURES ============================================== ______________________________________________ testsquare _____________________________________________ def testsquare(): num=7 > assert 7*7 == 40 E assert (7 * 7) == 40 test_square.py:9: AssertionError ================================= 1 failed, 1 passed in 0.06 seconds =================================
其中几个关键的:
请看结果的第一行。它显示了文件名和结果。F代表测试失败,dot(.)代表测试成功。
.F 表示该文件测试有错误
E 后面跟的是具体的错误内容
test_square.py:9: AssertionError
表示:错误的文件,文件中的行数,以及错误类型
最后是测试摘要:可以看到,1个失败,1个通过
函数 tesequality 没有被执行,因为 pytest 不认为它是一个测试,因为它的名字不是 test*** 的格式 **。
现在,执行下面的命令,再看看结果 –
pytest -v
-v增加了语言文字的准确性。
test_square.py::test_sqrt PASSED
test_square.py::testsquare FAILED
============================================== FAILURES
==============================================
_____________________________________________ testsquare
_____________________________________________
def testsquare():
num = 7
> assert 7*7 == 40
E assert (7 * 7) == 40
test_square.py:9: AssertionError
================================= 1 failed, 1 passed in 0.04 seconds
=================================
现在的结果更能说明测试的失败和测试的通过。
注意 - pytest命令将执行当前目录和子目录中所有格式为 test_*** 或 ***_test 的文件。
4.Pytest 文件执行
在本章中,我们将学习如何执行单个测试文件和多个测试文件。我们已经创建了一个测试文件 test_square.py 。创建一个新的测试文件 test_compare.py ,代码如下:
def test_greater():
num = 100
assert num > 100
def test_greater_equal():
num = 100
assert num >= 100
def test_less():
num = 100
assert num < 200
执行命令
pytest -v
得到结果
=============================================================== test session starts ================================================================
platform linux2 -- Python 2.7.18, pytest-4.6.9, py-1.8.1, pluggy-0.13.0 -- /usr/bin/python2
cachedir: .pytest_cache
rootdir: /home/zeekr/PycharmProjects/pytest_num
collected 6 items
test_compare.py::test_greater FAILED [ 16%]
test_compare.py::test_greater_equal PASSED [ 33%]
test_compare.py::test_less PASSED [ 50%]
test_square.py::test_sqrt PASSED [ 66%]
test_square.py::testsquare PASSED [ 83%]
test_square.py::testquality FAILED [100%]
===================================================================== FAILURES =====================================================================
___________________________________________________________________ test_greater ___________________________________________________________________
def test_greater():
num = 100
> assert num > 100
E assert 100 > 100
test_compare.py:3: AssertionError
___________________________________________________________________ testquality ____________________________________________________________________
def testquality():
> assert 10 == 11
E assert 10 == 11
E -10
E +11
test_square.py:15: AssertionError
======================================================== 2 failed, 4 passed in 0.03 seconds ========================================================
我们可以看到直接执行了两个py文件的测试,最后测试摘要我们也可以看到2个错误,4个通过,错误的具体内容也是可以看到的
现在我们如果想要对单个的py文件进行测试的话,可以采用下面的命令
pytest test_compare.py -v
上述命令将只执行文件 test_compare.py 中的测试 。 我们的结果将是
=============================================================== test session starts ================================================================
platform linux2 -- Python 2.7.18, pytest-4.6.9, py-1.8.1, pluggy-0.13.0 -- /usr/bin/python2
cachedir: .pytest_cache
rootdir: /home/zeekr/PycharmProjects/pytest_num
collected 3 items
test_compare.py::test_greater FAILED [ 33%]
test_compare.py::test_greater_equal PASSED [ 66%]
test_compare.py::test_less PASSED [100%]
===================================================================== FAILURES =====================================================================
___________________________________________________________________ test_greater ___________________________________________________________________
def test_greater():
num = 100
> assert num > 100
E assert 100 > 100
test_compare.py:3: AssertionError
======================================================== 1 failed, 2 passed in 0.01 seconds ========================================================
这次只针对了test_compare.py 文件进行了测试,1个错误,3个通过,错误在该文件的第三行
5.Pytest 执行测试套件的一个子集
在一个真实的场景中,我们将有多个测试文件,每个文件将有一些测试。测试将涵盖各种模块和功能。假设,我们只想运行一个特定的测试集;我们如何去做呢?
Pytest提供了两种方法来运行测试套件的子集。
- 根据测试名称的子串匹配,选择要运行的测试。
- 根据应用的标记选择要运行的测试组。
命令大概如下:
pytest -k <substring> -v
-k <substring>
代表要在测试名称中搜索的子串。
现在,运行以下命令-
pytest -k great -v
这将执行所有名称中含有 ‘great ‘一词的测试。在本例中,它们是 test_greater() 和 test_greater_equal() 。 请看下面的结果:
=============================================================== test session starts ================================================================
platform linux2 -- Python 2.7.18, pytest-4.6.9, py-1.8.1, pluggy-0.13.0 -- /usr/bin/python2
cachedir: .pytest_cache
rootdir: /home/zeekr/PycharmProjects/pytest_num
collected 6 items / 4 deselected / 2 selected
test_compare.py::test_greater FAILED [ 50%]
test_compare.py::test_greater_equal PASSED [100%]
===================================================================== FAILURES =====================================================================
___________________________________________________________________ test_greater ___________________________________________________________________
def test_greater():
num = 100
> assert num > 100
E assert 100 > 100
test_compare.py:3: AssertionError
================================================= 1 failed, 1 passed, 4 deselected in 0.02 seconds =================================================
他仅仅只测试了名字包含greater,1个错误,2个通过,4个主动取消:这是因为这些测试名称中不包含 great 这个词
6.Pytest 对测试进行分组
这个其实是需要我们在py文件中倒入pytest,然后把pytest作为装饰器加在要被测试的函数,这样就可以进行一个分组
import pytest
@pytest.mark.<markername> # markername是自己自定义的名字
Pytest允许我们在测试函数上使用标记。标记是用来给测试函数设置各种功能/属性的。Pytest提供了许多内置的标记,如xfail, skip和parametrize。除此之外,用户可以创建自己的标记名称
要使用标记,我们必须在测试文件中 导入pytest 模块。我们可以为测试定义自己的标记名称,并运行具有这些标记名称的测试。
要运行标记的测试,我们可以使用下面的语法 —:
pytest -m <markername> -v
用以下代码更新我们的测试文件 test_compare.py 和 test_square.py 。我们正在定义3个标记 --great, square, others
test_compare.py
import pytest
@pytest.mark.great
def test_greater():
num = 100
assert num > 100
@pytest.mark.great
def test_greater_equal():
num = 100
assert num >= 100
@pytest.mark.others
def test_less():
num = 100
assert num < 200
test_square.py
import pytest
import math
@pytest.mark.square
def test_sqrt():
num = 25
assert math.sqrt(num) == 5
@pytest.mark.square
def testsquare():
num = 7
assert 7*7 == 40
@pytest.mark.others
def test_equality():
assert 10 == 11
现在要运行标记为 **others ** 测试,运行以下命令
pytest -m others -v
# 我们也可以指定python版本
python3 -m pytest others -v
这个只会对others进行测试
7.有时候我们有的测试用例在该次测试中是不需要用到的,这个时候我们可以给这些测试用例添加装饰器跳过该测试用例
通过pytest.mark.skip()或者pytest.makr.skipif()条件表达式,跳过指定的测试用例
固件(Fixture)
固件就是一些预处理的函数,pytest会在执行测试函数前(或者执行后)加载运行这些固件,常见的应用场景就有数据库的连接和关闭(设备连接和关闭)
我们首先设置,然后在后续我们的测试用例上面就可以使用到我们预处理的数据
import pytest
@pytest.fixture()
def postcode():
return "hello"
def test_count(postcode):
assert postcode == "hello"
这个断言的测试用例是没问题的,他会通过固件拿到postcode的值,然后在测试用例中使用到这个值就是预处理后的