此文已由作者吴琪惠授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
使用assert语言进行断言
pytest允许您使用标准的python assert方法来验证期望值,例如:
# content of test_assert1.pydef f(): return 3def test_function(): assert f() == 4
断言函数会返回某个值,如果断言失败,会看到函数的返回值:
$ pytest test_assert1.py ======= test session starts ======== platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items test_assert1.py F ======= FAILURES ======== _______ test_function ________ def test_function():> assert f() == 4E assert 3 == 4E + where 3 = f() test_assert1.py:5: AssertionError ======= 1 failed in 0.12 seconds ========
pytest支持最常见的表达式(包括调用、熟悉、比较、二进制、一元操作符),这允许你不需要使用python惯用的代码结构,且不会丢失缺省信息。
但是,如果你指定一个断言如下:
assert a % 2 == 0, "value was odd, should be even"
那么,因为找不到缺省断言,这句会直接出现在traceback。
异常断言
使用pytest.raises进行异常断言:
import pytestdef test_zero_division(): with pytest.raises(ZeroDivisionError): 1 / 0
如果你需要访问时间的异常信息;
def test_recursion_depth(): with pytest.raises(RuntimeError) as excinfo: def f(): f() f() assert 'maximum recursion' in str(excinfo.value)
excinfo是一个ExceptionInfo实例,是由实际的异常抛出之后包装的。需要关心的属性有 .type, .value 和 .traceback
3.0版本的改动:
你可以使用meassage参数来自定义一个失败消息:
>>> with raises(ZeroDivisionError, message="Expecting ZeroDivisionError"):... pass... Failed: Expecting ZeroDivisionError
若你想要python2.4版本也可以适用,还可以使用其他两个方式:
pytest.raises(ExpectedException, func, *args, **kwargs)pytest.raises(ExpectedException, "func(*args, **kwargs)")
上面两个执行含有args和kwargs的特殊方法,并且断言给定的ExpectedException。报告将会提供有用的错误输出信息,比如 no exceptin 或者 wrong exception
注意,我们也可以给pytest.mark.xfail指定 raises 参数,这样用例失败之后会给出一个更加自定义的错误异常:
@pytest.mark.xfail(raises=IndexError)def test_f(): f()
针对你自己故意抛出的测试异常,使用pytest.raises的方式更好,而使用@pytest.mark.xfail 类似的检查功能可能是用于更好的记录不固定的bug
如果你想要测试一个正则表达式匹配的字符串异常,有点类似unittest里的TestCase.assertRaiseRegexp方法,可以使用ExceptionInfo.match方法:
import pytestdef myfunc(): raise ValueError("Exception 123 raised")def test_match(): with pytest.raises(ValueError) as excinfo: myfunc() excinfo.match(r'.* 123 .*')
match方法的正则表达式参数是匹配python里的re.search方法,所以,在上面的例子中 exeinfo.match('123')可以正常的被匹配到。
警告断言(2.8版本)
使用pytest.warns
比较上下文敏感词
# content of test_assert2.pydef test_set_comparison(): set1 = set("1308") set2 = set("8035") assert set1 == set2
运行:
$ pytest test_assert2.py ======= test session starts ======== platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items test_assert2.py F ======= FAILURES ======== _______ test_set_comparison ________ def test_set_comparison(): set1 = set("1308") set2 = set("8035") > assert set1 == set2 E assert {'0', '1', '3', '8'} == {'0', '3', '5', '8'} E Extra items in the left set: E '1'E Extra items in the right set: E '5'E Use -v to get the full diff test_assert2.py:5: AssertionError ======= 1 failed in 0.12 seconds ========
几个用例的特别比较:
1.比较长字符串:显示了diff
2.标记长序列:第一个失败的index
3.比价字典:不相等的条目
自定义断言
regexp匹配方法的参数匹配与re.search函数。所以在上面的例子中excinfo.match(“123”)工作。
网易云免费体验馆,0成本体验20+款云产品!
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 浅谈容器监控和网易云计算基础服务实践
【推荐】 Android标题栏(1)