2023年pytest自动化测试框架教程 - 断言 - assert
迪丽瓦拉
2024-05-10 10:04:55
0

以下总结基于:7.2.x

官网:https://docs.pytest.org/en/7.2.x/how-to/assert.html

延续Python标准库中的assert语句进行断言

支持显示常见的子表达式的值,包括调用、属性、比较以及二元和一元运算符

官方的例子:https://docs.pytest.org/en/7.2.x/example/reportingdemo.html#tbreportdemo

实战例子:判定接口返回的code是否为200

import requestsdef get_user_info_api(user_id: int):"""获取指定user_id的用户信息并返回"""payload = {'user_id': user_id}response = requests.get('https://www.example.com/user', params=payload)return response.json()def test_api_status():"""判定接口返回的`code`是否为`200`"""code = get_user_info_api(user_id=1)['code']assert code == 200# assert code == 200, '返回的code非200,请检查.'  可以指定断言的msg

给预期异常断言

使用场景:测试时预计可能会发生某些异常,如RuntimeError/ZeroDivisionError/ValueError,可以使用pytest.raises()来管理上下文

  • 例子1:pytest.raises()捕获到预期的异常
import pytestdef test_zero_division():"""1 / 0 会引发`ZeroDivisionError`异常,`pytest.raises()`捕获到预期的异常,用例执行成功相当于`python`中的`try except`捕获异常"""with pytest.raises(ZeroDivisionError):1 / 0# 成功捕获后,做一些其他操作
  • 例子2:pytest.raises()未能捕获到预期的异常
def test_no_zero_division():"""如果没有发生预期的异常,则该测试用例会执行失败"""with pytest.raises(ZeroDivisionError):1 / 1# def test_zero_division():#     with pytest.raises(ZeroDivisionError):# >       1 / 1# E   Failed: DID NOT RAISE 
  • 例子3:获取异常的具体信息
import pytestdef test_user_status_value():"""exc_info是`ExceptionInfo`的实例"""with pytest.raises(ValueError) as exc_info:raise ValueError('用户状态必须为0.')assert exc_info.type is ValueErrorassert exc_info.value.args[0] == '用户状态必须为0.'  # 要获取到实际的value,需要用`.args[0]`assert exc_info.traceback is None# >       assert exc_info.traceback is None# E       AssertionError: assert [] is None# E        +  where [] = .traceback
  • 例子4:正则匹配异常
import pytest# 正则匹配异常
def test_match_raise():"""正则匹配异常"""with pytest.raises(ValueError, match=r".* 1234 .*"):  # 底层通过`re.search`来正则匹配raise ValueError("Exception 123 raised")# with pytest.raises(ValueError, match=r".* 1234 .*"):# >    raise ValueError("Exception 123 raised")# E    AssertionError: Regex pattern did not match.# E    Regex: '.* 1234 .*'#      Input: 'Exception 123 raised'

标记预计会执行失败的测试用例

使用@pytest.mark.xfail()语法糖来标记

使用场景:期望该用例未来执行会失败,但是不会影响测试用例继续往下执行

注意:如果执行失败,结果会被标记为XFAIL,同时不会输出错误信息;相反,被标记@pytest.mark.xfail()的测试用例如果执行成功,结果会被标记为XPASS

import pytest@pytest.mark.xfail()
def test_expected_fail():"""执行失败的用例,会被标记为`XFAIL`"""assert '这个用例预期会失败' == ''  # test_raise.py::test_expected_fail XFAIL@pytest.mark.xfail()
def test_expected_fail():"""执行成功的用例,会被标记为`XPASS`"""assert 1 == 1  # test_raise.py::test_expected_fail XPASSclass TestXfail():"""被`@pytest.mark.xfail()`标记后,不会影响后续用例执行"""@pytest.mark.xfail()def test_expected_fail(self):assert 1 == 2def test_success(self):assert 1 == 1# test_raise.py::TestXfail::test_expected_fail XFAIL# test_raise.py::TestXfail::test_success PASSED

pytest.raises()@pytest.mark.xfail()使用区别

  • 对未来已知可能会发生的异常,建议使用pytest.raises()
  • 对系统中未修复的bug未完全实现的case,建议使用@pytest.mark.xfail()来标记,后续变更,类似// TODO

附:pytest.raises()API说明

官方:https://docs.pytest.org/en/7.2.x/reference/reference.html#pytest.raises

import pytestpytest.raises(ExpectedException, func, *args, **kwargs)
# 可以传递一个将使用给定的 *args 和 **kwargs 执行的func,并断言引发了给定的ExpectedException

相关内容