Pytest使用简介

Pytest是一种基于python的测试框架,用于编写和运行测试代码。pytest主要用来测试API,但也可以进行一些复杂的测试,像测试数据库或UI等。

Pytest 的优势:

  • Pytest 可以并行执行多个tests, 减少 test-suite 的执行时间 [第八章]
  • Pytest 可以自动地检测测试文件或测试函数,不需要被显示地提及 [第二章]
  1. test_*.py 文件
  2.  *_test.py 文件
  3. test* 函数 
  • Pytest 允许我们在运行过程中跳过一些test,执行整个test-suite的子集 [第三,四,五,六章]
  • Pytest 免费开源,易学

(一)pytest 安装

安装 pytest: pip3 install pytest
查看 pytest 是否安装成功:pip3 show pytest

若安装成功,将会有如下显示

Name: pytest

Version: 5.3.5

Summary: pytest: simple powerful testing with Python

Home-page: https://docs.pytest.org/en/latest/

Author: Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others

Author-email: None

License: MIT license

Location: /usr/local/lib/python3.7/site-packages

Requires: pluggy, py, importlib-metadata, more-itertools, wcwidth, attrs, packaging

Required-by: 

(二)Pytest 测试文件/函数

2.1. Pytest 测试文件Pytest命令会自动运行当前目录下所有' test_*.py'  和 '_test.py' 文件 [1], 自动默认这些文件是测试文件。当然,我们也可以显示地指示要要运行的测试文件或测试目录。

Running pytest without mentioning a filename will run all files of format test_*.py or *_test.py in the current directory and subdirectories. Pytest automatically identifies those files as test files. We can make pytest run other filenames by explicitly mentioning them.

pytest a.py
pytest dirname

2.2. Pytest 测试函数:Pytest需要被测试函数以‘test’开头命名,不以'test' 开头的函数会被pytest自动忽略,pytest不可以像指定文件一样显示地指定被测函数,即测试函数必须以'test'开头。

Pytest requires the test function names to start with test. Function names which are not of format test* are not considered as test functions by pytest. We cannot explicitly make pytest consider any function not starting with test as a test function.

【例子1】创建Pytest文件夹,新建文件 test_nn.py 和 test_greater.py 和 test.py. 目录结构如下

Pytest

|- test.py

|- test_great.py: test_greater(); test_greater_equal(); test_less();

|- test_nn.py: testx(); test_great_haha();

运行 pytest 命令,只显示 test_great.py 和 test_nn.py 文件,因为[1],其中 test_great.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
View Code

运行pytest 和 pytest -v 命令,运行结果分别如下左右图所示,-v 显示更

      

(三)Pytest 可以选择性测试完整test-suite的某个子集(subset)

3.1. 依照文件名匹配的方式选择测试子集 (select tests to run based on substring matching of test names)

pytest -k <substring> -v

针对【例子1】

pytest -k great -v 命令 ('great' 对应 <substring>项) 执行所有带有great的测试, 

注意:pytest -k 'substring' -v: 可识别当前目录下所有匹配文件中带有 ‘substring’ 的测试函数。

3.2. 根据 标记 选择测试组进行测试 (select tests groups to run based on the markers applied)

添加相关包:import pytest
插入标记:@pytest.mark.<markname> 运行带标记的测试:pytest -m <markname> -v

[例子2] 带标记 (marker) 的 test_mark.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
View Code

(四)Pytest 通过 Fixture 和 conftest.py 加载测试所需调用

@pytest.fixture

Fixture 是测试的输入,测试被执行前, 涉及到的 fixture 会被执行到。Pytest 提供了 @pytest.fixture 将该部分代码自动附加到测试函数中

【注意】(1) 如果不加 @pytest.fixture 的话,这部分被测试函数调用的代码不会加载进入测试函数,pytest运行时会报错 ...

            (2) @pytest.fixture 的作用域是当前文件,在其他文件中调用该 fixture 对应的函数会报错.We cannot use that fixture in another test file

Fixtures are functions, which will run before each test function to which it is applied. Fixtures are used to feed some data to the tests such as database connections, URLs to test and some sort of input data. Therefore, instead of runnng the same code for every test, we can attach fixture to the tests and it will run and return the data to the test before executing each test.

【例子3.1】创建 test_div.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
View Code

为了克服(2)的限制, 在多个测试文件中调用 Fixture, 我们需要 conftest.py 统一定义存储 Fixture

【例子3.2】新建 conftest.py 内容如下

import pytest
@pytest.fixture
def input_value():
    input = 39
    return input
View Code
# content of file 'test_14'
def test_divisible_14(input_value):
    assert input_value%14 ==0 

# content of file 'test_15'
def test_divisible_15(input_value):
    assert input_value%15 ==0

# content of file 'test_16'
def test_divisible_16(input_value):
    assert input_value%16 ==0
View Code

运行 pytest -k divisible -v 时,由于conftest.py 文件已声明 fixture, 所以input_value() 函数会自动加载到每次调用之前,测试正常进行

(五)Pytest指定测试,验证实际输出和期望输出是否一致 

Pytest 用 @pytest.mark.parametrize() 测试指定的<input, output>对

【例子4】添加@pytest.mark.parametrize()子句如下

import pytest

@pytest.mark.parametrize("num,output",[(1,11),(2,22),(3,35),(4,44)])
def test_multiplication_11(num,output):
    assert 11*num == output
View Code

 (六)Pytest 跳过某些测试/屏蔽某些测试错

@pytest.mark.skip 用来掉过某些测试
@pytest.mark.xfail  用来屏蔽某些测试的错误

【例子5】新建 test_op.py 文件,内容如下

import pytest

@pytest.mark.xfail
@pytest.mark.great
def test_greater():
    num = 100
    assert num > 100

@pytest.mark.great
def test_greater_equal():
    num = 100
    assert num >= 200

@pytest.mark.skip
@pytest.mark.others
def test_divisible(input_value):
    assert input_value < 200
View Code

运行 pytest test_op.py 运行结果如下,test_greater() 错误被屏蔽,test_greater_equal()正常报错,test_divisible()被测试跳过

 

(七)Pytest测试停止

cmd: pytest --maxfail = <num>

当检测出的错误个数等于num时,pytest 测试结束,不在对后面的代码进行测试

(八)Pytest 并行测试

pip install pytest-xdist  // 安装pytest 并行测试工具
pytest -n <num>        // runs in <num> workers

(九)Pytest 将测试结果记录到 xml 文件中

pytest -v --junitxml=<filename>

【例子6】 pytest -v --junitxml="result.xml"

 

参考(Reference)

[1] https://www.tutorialspoint.com/pytest/index.htm

posted on 2020-03-03 03:49  猪伯  阅读(1625)  评论(0编辑  收藏  举报

导航