pyTest官方手册(Release 4.2)之蹩脚翻译(3)

Chapter 3 在现有测试套中使用pytest

pytest可以与大多数现有的测试套一起使用,但他的测试行为与其他的测试工具(如nose或者python的默认的unittest)有差异.
在使用此部分之前,您需要安装pytest。

3.1 与现有的测试套一起运行pytest

比如说你想要修改某处的已有的代码库,在将代码拉到你的开发环境后并且设置好python的环境后,你需要在你的工程的根目录下运行:

cd <repository>
pip install -e . #解决环境依赖可以通过"python setup.py develop"或"conda develop"(都没用过。。。囧)

这将在site-packages中设置一个symlink到你的代码,允许你在运行测试的时候编辑代码,就好像你已经安装了这个package一样。(这段看得我莫名其妙,想了一下,作者的本意应该是,如果想对某个类似github的库进行测试,但是测试代码跟库代码又不好放一起的话,就用这个命令行搞一下)
设置项目为开发模式,可以避免每次运行测试时都需要重新install。

当然,也可以考虑使用tox库。

Chapter 4 在测试用例中编写和上报断言

4.1 使用断言语句

pytest允许你在测试用例中使用标准的python断言。如下:

# test_assert1.py中的内容
def f():
    return 3

def test_function():
    assert f() == 4

本例中的函数期望返回一个固定的值。如果该断言失败了,你会看到该函数的返回值:

$ pytest test_assert1.py 
============================= test session starts ==============================
platform darwin -- Python 3.7.2, pytest-4.2.1, py-1.7.0, pluggy-0.8.1
rootdir: /Users/david/Downloads/myPython/translate, inifile:
collected 1 item                                                               

test_assert1.py F                                                        [100%]

=================================== FAILURES ===================================
________________________________ test_function _________________________________

    def test_function():
>       assert f() == 4
E       assert 3 == 4
E        +  where 3 = f()

test_assert1.py:5: AssertionError
=========================== 1 failed in 0.07 seconds ===========================

pytest支持显示常见的子表达式的值,包括调用,属性,比较以及二元和一元运算符。(参看Demo of Python failure reports with purest 这允许你使用你习惯的python的在不丢失内省信息的情况下构造代码。(什么是内省信息?更详细的内部输出信息?)
如果你为断言指定了输出信息,那么不会输出任何内省信息,而是在traceback中直接输出指定的信息:

assert a % 2 ==0, "value was odd, should be even"

更多断言内省信息请参考Advanced assertion introspection

4.2 异常的断言

你可以在上下文中使用pytest.raises来对异常产生断言:

 import pytest
 
 def test_zero_division():
    with pytest.raise(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.
你可以通过match参数来使用正则表达式来匹配一个异常是否发生:

import pytest
def myfunc():
    raise ValueError("Exception 123 raised")
    
def test_match():
    with pytest.raises(ValueError, match=r'.* 123 .*'):
        myfunc()

参数match与re.search行为是一致的,所以上面的match='123’能够正确的匹配到myfunc抛出的异常。
pytest.raises的另一种使用方法是传递一个函数给它,该函数使用给定的参数,并且最终判断该函数是否产生了期望的断言:

pytest.raises(ExpectedException, func, *args, **kwargs)

测试报告会提供你一些帮助信息,比如是没有异常还是抛出了错误的异常。

注意也可以在pytest.mark.xfail中使用raises来检查测试用例是否是因为抛出了异常而失败:

@pytest.mark.xfail(raises=IndexError)
def test_f():
    f()

使用pytest.raises更适合测试自己的代码故意引发的异常。
而使用@pytest.mark.xfail和检查函数更适合那些记录的未修复的bug(也就是那些应该发生的异常)或者依赖项中的异常。 (这两个场景在测试过程中是不一样的)

4.3 告警的断言

2.8 引入
你可以通过pytest.warns来判断是否产生了特定的告警。

4.4 上下文比较

2.0 引入
pytest支持在进行比较时提供上下文的相关敏感信息:

# test_assert2.py
def test_set_comparison():
    set1 = set("1308")
    set2 = set("8035")
    assert set1 == set2

运行如下:

$ pytest test_assert2.py 
============================= test session starts ==============================
platform darwin -- Python 3.7.2, pytest-4.2.1, py-1.7.0, pluggy-0.8.1
rootdir: /Users/david/Downloads/myPython/translate, inifile:
collected 1 item                                                               

test_assert2.py F                                                        [100%]

=================================== FAILURES ===================================
_____________________________ test_set_comparison ______________________________

    def test_set_comparison():
        set1 = set("1308")
        set2 = set("8035")
>       assert set1 == set2
E       AssertionError: 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:4: AssertionError
=========================== 1 failed in 0.07 seconds ===========================

4.5 为断言增加注释

你可以通过实现钩子函数pytest_assertrepr_compare来为断言增加自己的描述:

pytest_assertrepr_compare(config, op, left, right)

该钩子返回失败的断言中的注释。
如果没有自定义注释,返回None,否则返回一个字符串列表。列表中的字符串使用换行符来连接,同时字符串中的所有换行符都会被转义。
注意,除了第一行以外,其他所有行都会进行缩进,目的是将第一行作为摘要。

Parameters config(_pytest.config.Config) - pytest config object

下面的示例在conftest.py中实现了该钩子函数,改变了Foo的对象的注释:

# conftest.py
from test_foocompare import Foo
def pytest_assertrepr_compare(op, left, right):
    if isinstance(left, Foo) and isinstance(right, Foo) and op == "==":
        return ['Comparing Foo instance:', ' vals: %s != %s' % (left.val, right.val)]

定义测试对象:

# test_foocompare.py
class Foo(object):
    def __init__(self, val):
        self.val = val
    def __eq__(self, other):
        return self.val == other.val
        
def test_compare():
    f1 = Foo(1)
    f2 = Foo(2)
    assert f1 == f2

运行这个测试,可以在测试结果中看到自定义的注释:

$ pytest -q test_foocompare.py
F [100%]
================================= FAILURES =================================
_______________________________ test_compare _______________________________
def test_compare():
f1 = Foo(1)
f2 = Foo(2)
> assert f1 == f2
E assert Comparing Foo instances:
E vals: 1 != 2
test_foocompare.py:11: AssertionError
1 failed in 0.12 seconds

4.6 高级断言内省

偷懒没翻。。。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值