pytest的断言管理
1、什么是断言
pytest的断言使用python中的assert函数。断言内容为一个表达式,只要表达式的最终结果为True,那么断言通过,用例执行成功,否则用例执行失败。
2、断言的分类与使用
pytest使用python的assert函数,支持显示常见的python子表达式的值,包括:调用、属性、比较、二进制和一元运算符。
也就是说,python语言有多少种判断,assert就有多少种断言,包括断言函数返回值是否相等、断言表达式执行后的结果是否正确、各种不同比较运算符的断言、比较各种数据类型(字符串、列表、字典、集合)不同的断言。
2.1 验证函数返回值是否相等
断言函数返回了某个值:
def test():
return 3
# 断言test()函数返回值是否等于4
det test_f():
assert test() == 4
2.2 表达式断言
通过表达式运算后的结果进行真假判断。
a = 5
# 如果值是偶数,断言成功;如果是奇数,则断言失败
def test_exp():
assert a%2 == 0
2.3 比较类型断言
2.3.1 相同数据类型的比较断言
比较类型断言包括相等、不等、包含、不包含、真、假等判断,以及长列表中的详细断言。
# 比较
def test_1():
assert 1<3
assert 100>90
assert 10==10
# 真假
def test_true():
assert (100>90) is True
# 包含
def test_in_dict():
assert "test" in "test teacher"
# 不包含
def test_in_dict():
assert "hello" not in "test teacher"
总结:
assert xx
:判断xx为真
assert not xx
:判断xx不为真
assert a in b
:判断b包含a
assert a==b
:判断a等于b
assert a!=b
:判断a不等于b
2.3.2 不同数据类型的比较断言
对于不同数据类型进行比较断言时,直接使用assert
语句,可能会导致错误或者不直观的测试结果。
例如:一个整数和一个字符串,直接使用
assert
,会提示TypeError
那么针对这种情况,如何处理呢?以下有4种处理方式:
2.3.2.1 使用pytest.raises
捕获异常
import pytest
def test_compare_different_types():
with pytest.raises(TypeError):
assert 1 == "1" # 直接比较整数和字符串
2.3.2.2 使用pytest
的assert
扩展
从pytest 6.0版本开始,引入了几个用于类型检查的断言,例如assert.is_instance()
和assert.is_not_instance()
,这使得类型检查更加直观和灵活。
def test_compare_types():
value = 1
assert isinstance(value, int) # 使用内置的isinstance检查类型
2.3.2.3 自定义比较函数
def compare_types(expected, actual):
if not isinstance(expected, type(actual)):
raise TypeError(f"Expected type {type(expected)}, but got {type(actual)}")
return expected == actual
def test_custom_compare():
assert compare_types(1, "1") # 自定义比较函数抛出TypeError
2.3.2.4 使用第三方库
还有一些第三方库,如hypothesis,提供了强大的数据生成和属性测试功能,可以用来测试不同类型的数据。
from hypothesis import given, strategies as st
import pytest
@given(st.integers(), st.text())
def test_hypothesis_type_comparison(x, y):
with pytest.raises(TypeError):
assert x == y # 使用Hypothesis测试不同类型的数据比较
总结:
选择哪种方法取决于你的具体需求和测试场景。
对于简单的类型检查和预期异常捕获,使用pytest.raises
或内置的isinstance()
通常是足够的。
对于更复杂的测试逻辑,自定义函数或使用第三方库可能更合适。
2.4 触发一个指定异常的断言
在pytest中,如果你想要测试某个代码块是否抛出了指定类型的异常,你可以使用pytest的内置断言raises
。
这个断言允许你指定一个异常类,并确保当你的测试运行时,该代码块确实抛出了你指定的异常类型。
示例1:测试代码块是否抛出异常
import pytest
# 假设有一个函数
def devide(x, y):
return x/y
# 验证函数是否在y为0时抛出ZeroDivisionError
def test_divide_by_zero():
with pytest.raises(ZeroDivisionError):
divide(1, 0)
示例2:测试代码块抛出指定异常并捕获异常对象
def test_divide_by_zero_and_capture_exception():
with pytest.raises(ZeroDivisionError) as e:
divide(1, 0)
assert str(e.value) == "division by zero" # 根据Python版本的不同,错误消息可能不同
示例3:测试代码块抛出不同类型的异常
如果想要测试代码块抛出不同类型的异常,可以通过传递一个元组给raises来实现
def test_divide_and_capture_multiple_exceptions():
# 如果divide('a', 'b')抛出了ZeroDivisionError或TypeError中的任何一种,测试就会通过
with pytest.raises((ZeroDivisionError, TypeError)):
divide('a', 'b') # 这会引发TypeError,因为不能将字符串用作除数
注意:
1、确保测试的函数名以
test_
开头
2、使用with pytest.raises()
,确保代码确实会抛出异常。如果代码没有抛出异常,而测试通过,则需要重新检查你的代码逻辑或者测试用例编写逻辑
3、为失败断言添加自定义说明
使用pytest测试时候,有时候标准的断言assert
可能不足以清晰地说明为什么测试失败,为提供更详细的失败信息,可以通过以下几种方式来增加断言。
3.1 使用pytest.fail()
pytest.fail()
运行在直接测试红抛出失败,同时可以添加自定义的失败信息。
import pytest
def test():
if is_false:
pytest.fail("自定义的失败信息")
3.2 使用assert
并提供额外的信息
python3.5开始,assert
语句支持一个可选的消息参数,这可以在断言失败时提供额外信息。
def test():
assert condition, "自定义的失败信息"
3.3 使用pytest
的fail
fixture
在pytest中定义一个fail的fixture,并在其中使用pytest.fail()
来抛出自定义失败的信息。
import pytest
@pytest.fixture
def fail():
return pytest.fail
def test(fail):
if is_false:
fail("自定义的失败信息")
3.4 使用pytest
的raises
上下文管理器
使用raises
上下文管理器,可以在某个代码块上抛出异常
def test_example():
with pytest.raises(Exception, match="自定义的异常信息"):
some_code_that_should_raise()
3.5 使用pytest
的assert
替代品pytest.raises
和match参数
在某个代码块抛出特定类型的异常,可以使用pytest.raises
和match参数。
def test_example():
with pytest.raises(ValueError, match="自定义的错误信息"):
raise ValueError("自定义的错误信息")
总结:
1、对于简单的断言失败,使用
assert
消息参数或者pytest.fail()
2、处理复杂的异常或验证,使用pytest.raises
和match参数会更合适
4、Assert各种类型断言
在Python的pytest测试框架中,有多种方式可以断言(assert)不同类型的条件,以确保代码的正确性。
4.1 基本断言
最基本和常用的断言是assert语句,它用于检查表达式是否为True。
def test_basic_assert():
x = 5
assert x == 5, "x should be 5"
4.2 类型断言
可以使用isinstance()函数来检查一个对象的类型。
def test_type_assert():
x = 5
assert isinstance(x, int), "x should be an integer"
4.3 集合和列表的断言
对于集合和列表,可以使用in来检查元素是否存在,使用==来比较集合或列表的内容。
def test_collection_assert():
my_list = [1, 2, 3]
assert 2 in my_list, "2 should be in the list"
assert my_list == [1, 2, 3], "The list should be [1, 2, 3]"
4.4 使用pytest内置的断言重写
pytest提供了一些内置的断言重写,使得断言更加丰富和易于理解。
assert与pytest.raises()结合使用来测试异常
import pytest
def test_exception():
with pytest.raises(ZeroDivisionError):
1 / 0
assert与pytest.approx()结合使用来测试浮点数近似相等
def test_approx():
assert pytest.approx(1.00001) == 1.0 # 可以容忍一定的浮点数误差
4.5 使用第三方库如numpy的断言工具
如果你在使用numpy数组,可以使用numpy.testing模块中的断言函数。
import numpy as np
from numpy.testing import assert_array_equal, assert_allclose
def test_numpy_assert():
a = np.array([1, 2, 3])
b = np.array([1, 2, 3])
assert_array_equal(a, b) # 检查数组内容是否完全相等
assert_allclose(a, b) # 检查数组内容是否在容差范围内近似相等(用于浮点数)
4.6 使用unittest风格的断言(如果需要)
虽然pytest有自己的断言方式,但你也可以在测试函数中使用unittest的断言方法,前提是导入它们。
import unittest
import pytest # 同时使用pytest框架的好处是无需单独导入unittest模块的断言方法,因为pytest已经提供了类似的机制。但如果你确实需要,可以这样做:
from unittest import TestCase # 注意:通常不需要这样做,因为pytest有自己的断言方式。这里只是为了展示如何导入。
class TestExample(TestCase): # 使用unittest的风格编写测试类(不常用)
def test_something(self):
self.assertEqual(1, 1) # 使用unittest的assertEqual方法进行断言(通常不推荐)
1、推荐使用pytest自己的断言方式,因为它们更简洁、更易于阅读和理解。例如,使用assert x == y而不是self.assertEqual(x, y)。这样可以使测试代码更加简洁和一致。
2、如果使用第三方库如numpy,则可以使用该库提供的断言工具。