Please enable Javascript to view the contents

Pytest 入门学习

 ·  ☕ 3 分钟

Pytest 测试框架使用简单、插件丰富、功能强大,被广泛用于 Python 自动化测试。本文主要介绍一些 Pytest 的基本概念和使用方法。

1. 运行机制

第一步,Pytest 从命令行或文件中读取配置

第二步,在指定目录下查找并导入 conftest.py 文件

第三步,查找满足匹配条件的测试文件,通常是 test_ 开头的 py 文件

第四步,执行 session 或 module 类型的 fixture

第四步,查找并执行类、函数中,定义的测试用例

2. pytest.ini 和 conftest.py 文件

首先看下测试的文件组织方式:

1
2
3
4
5
6
7
8
/ -
  | - pytest.ini  # pytest 的配置文件
  | - tests
    |
    | - conftest.py  # 全局通用的配置和功能
    | - fun_module   # 某个模块的测试
          | - test_a.py  # 该模块下的测试
          | - conftest.py  # 该模块下通用的配置和功能

执行 Pytest 时,不仅可以使用命令行传递运行时参数,还可以使用配置文件。Pytest 查找配置文件的顺序是:

1
2
3
4
5
path/pytest.ini
path/setup.cfg     # must also contain [pytest] section to match
path/tox.ini       # must also contain [pytest] section to match
pytest.ini
...                # all the way down to the root

通常在项目下放置 pytest.ini 文件,配置相关参数即可。

pytest.ini:

1
2
3
4
5
6
7
[pytest]
# 指定测试目录
testpaths  = tests
# 指定测试用例文件的命名格式
python_files = test_*.py
# 指定 conftest 文件的路径
pytest_plugins = tests

tests/conftest.py 全局依赖的配置

1
2
def pytest_configure():
    pass

运行测试时,执行命令:

1
# pytest . -s

3. pytest.fixture

fixture 是 Pytest 引入的概念,是 Pytest 提供的强大功能之一。下面来看看具体的用法:

3.1 直接作为常量使用

1
2
3
4
5
6
@pytest.fixture()
def remote_api():
    return 'success'

def test_remote_api(remote_api):
    assert remote_api == 'success'

3.2 作为前置函数运行

fixture 允许在执行测试用例之前,先执行一些准备动作。

1
2
3
4
5
6
7
8
9
import pytest

@pytest.fixture()
def before():
    pass

@pytest.mark.usefixtures("before")
def test_1():
    pass

通过 autouse 和 scope,可以完成很多测试用例的准备工作。

3.3 作用域 - scope

通过 scope 参数声明作用域,可选项有四个,默认值为 function:

  • function,函数级,每个测试函数都会执行一次
  • class, 类级别,每个测试类执行一次,所有方法都可以使用
  • module,模块级,每个模块执行一次,模块内函数和方法都可使用
  • session,会话级,一次测试只执行一次,所有被找到的函数和方法都可用
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@pytest.fixture(scope='function')
def func_scope():
    pass

@pytest.fixture(scope='module')
def mod_scope():
    pass

@pytest.fixture(scope='session')
def sess_scope():
    pass

@pytest.fixture(scope='class')
def class_scope():
    pass

4. pytest.mark

pytest.mark 的作用是对测试用例进行标记,从而更精细化地控制测试用例。

marker 不需要事先定义好就能使用,下面是一个例子:

1
2
3
4
5
6
7
import pytest

A = pytest.mark.A

@A
def test_A():
    assert True

一些内置的 marker :

  • skip,跳过被装饰的测试用例
  • skipif,传递一个条件判断,满足时跳过测试
  • xfail,如果执行失败则认为是通过,成功则认为失败
  • parametrize,批量给测试用例提供数据。如果 parametrize 的参数名称和 fixture 名称一样,会覆盖 fixture。
1
2
3
4
5
6
@pytest.mark.parametrize('name',
                      ['12345',
                       'abcdef',
                       '0a1b2c3'])
def test_name_length(passwd):
    assert len(passwd) == 6

5. 常用插件

5.1 pytest-cov

pytest-cov 是一个自动检测测试覆盖率的插件。使用示例:

1
# pytest --cov=myproj tests/

5.2 pytest-mock

mock 是为了屏蔽一些依赖项。依赖项应该有单独的测试用例,每一个测试只需要关注自身功能是否正常。使用示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import os

class UnixFS:

    @staticmethod
    def rm(filename):
        os.remove(filename)

def test_unix_fs(mocker):
    mocker.patch('os.remove')
    UnixFS.rm('file')
    os.remove.assert_called_once_with('file')

5.3 pytest-html

pytest-html 是一个能自动生成 HTML 格式测试报告的插件。使用示例:

1
# pytest --html=report.html

5.4 pytest-django

pytest-django 为 Django 应用和项目添加了 Pytest 支持。具体来说,pytest-django 引入了使用 pytest fixture 测试 Django 项目的能力,并且比标准的 Django 测试套件运行得更快。


微信公众号
作者
微信公众号