...

Pytest简单入门

Pytest是一个易用强大灵活的功能测试框架。

  • 易用: 用例编写简单, 断言方便
  • 强大: 全能的mark, 强大的fixtures
  • 灵活: 灵活的执行控制及丰富的插件

官方文档:https://docs.pytest.org/en/stable/index.html

安装方法

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
posted @ 2025-06-25 17:06  韩志超  阅读(111)  评论(0)    收藏  举报