如果固定装置中有异常,则Pytest类级固定装置将为每种方法运行

时间:2019-01-18 14:04:17

标签: python pytest

我正在使用pytest编写一些测试,该测试需要一个环境变量来运行测试功能。因此,我创建了一个固定装置,它将检查环境变量是否存在或否则退出。下面是我的代码。

import os
import sys

import pytest

from ..factorial import fact


@pytest.fixture(scope='class')
def pre(request):
    print('************setting up************')

    pwd = os.environ.get('PASSWD', None)
    if pwd is not None:
        request.cls.pwd = pwd
    else:
        sys.exit('This test requires your password, '
                 'please run export PASSWD=<yourPassword>')


@pytest.mark.usefixtures('pre')
class TestFactorial:
    def test_postive(self):
        assert fact(5) == 120

    def test_false(self):
        assert fact(6) == 720

设置环境变量后,我将获得预期的输出,如下所示,灯具实际上每个类运行一次。

collected 2 items                                                                                                                                                                                                  

test_factorial.py ************setting up************
..

============================================================================================= 2 passed in 0.01 seconds ===

现在,当未设置环境变量时,整个灯具将运行两次。下面是输出

collected 2 items                                                                                                                                                                                                  

test_factorial.py ************setting up************
E************setting up************
E

====================================================================================================== ERRORS ======================================================================================================
___________________________________________________________________________________ ERROR at setup of TestFactorial.test_postive ___________________________________________________________________________________

request = <SubRequest 'pre' for <Function test_postive>>

    @pytest.fixture(scope='class')
    def pre(request):
        print('************setting up************')

        pwd = os.environ.get('PASSWD', None)
        if pwd is not None:
            request.cls.pwd = pwd
        else:
>           sys.exit('This test requires your password, '
                     'please run export PASSWD=<yourPassword>')
E           SystemExit: This test requires your password, please run export PASSWD=<yourPassword>

test_factorial.py:17: SystemExit
____________________________________________________________________________________ ERROR at setup of TestFactorial.test_false ____________________________________________________________________________________

request = <SubRequest 'pre' for <Function test_false>>

    @pytest.fixture(scope='class')
    def pre(request):
        print('************setting up************')

        pwd = os.environ.get('PASSWD', None)
        if pwd is not None:
            request.cls.pwd = pwd
        else:
>           sys.exit('This test requires your password, '
                     'please run export PASSWD=<yourPassword>')
E           SystemExit: This test requires your password, please run export PASSWD=<yourPassword>

test_factorial.py:17: SystemExit

我期望会引发异常,程序将退出,甚至不会到达TestFactorial类。但这表明夹具实际上在类中的每个测试方法上运行了两次。

这是预期的行为吗?还是我在了解灯具的实际工作时缺少什么?

如果这确实是预期的,那么我如何实现这种行为:如果未设置环境变量,则测试不应运行?

编辑1

我对代码进行了一些更改,以实际查看夹具中是否存在异常,并且该夹具是否针对每种方法运行。下面是更新的代码和结果

import os
import sys
from random import randint   # edit

import pytest

from ..factorial import fact


@pytest.fixture(scope='class')
def pre(request):
    print('************setting up************')

    pwd = os.environ.get('PASSWD', None)
    if pwd is not None:
        print(randint(1, 100))    # edit
        request.cls.pwd = randint(1, 100)
    else:
        print(randint(1, 100))    # edit
        sys.exit('This test requires your password, '
                 'please run export PASSWD=<yourPassword>')

@pytest.mark.usefixtures('pre')
class TestFactorial:
    def test_postive(self):
        assert fact(5) == 120

    def test_false(self):
        assert fact(6) == 720

设置环境变量时的输出

pytest -sq test_factorial.py
************setting up************
67
..
2 passed in 0.01 seconds

因此该课程只运行了一次。

未设置环境变量时的输出

pytest -sq test_factorial.py
************setting up************
69
E************setting up************
82
E
====================================================================================================== ERRORS ======================================================================================================
___________________________________________________________________________________ ERROR at setup of TestFactorial.test_postive ___________________________________________________________________________________

request = <SubRequest 'pre' for <Function test_postive>>

    @pytest.fixture(scope='class')
    def pre(request):
        print('************setting up************')

        pwd = os.environ.get('PASSWD', None)
        if pwd is not None:
            print(randint(1, 100))
            request.cls.pwd = randint(1, 100)
        else:
            print(randint(1, 100))
>           sys.exit('This test requires your password, '
                     'please run export PASSWD=<yourPassword>')
E           SystemExit: This test requires your password, please run export PASSWD=<yourPassword>

test_factorial.py:20: SystemExit
____________________________________________________________________________________ ERROR at setup of TestFactorial.test_false ____________________________________________________________________________________

request = <SubRequest 'pre' for <Function test_false>>

    @pytest.fixture(scope='class')
    def pre(request):
        print('************setting up************')

        pwd = os.environ.get('PASSWD', None)
        if pwd is not None:
            print(randint(1, 100))
            request.cls.pwd = randint(1, 100)
        else:
            print(randint(1, 100))
>           sys.exit('This test requires your password, '
                     'please run export PASSWD=<yourPassword>')
E           SystemExit: This test requires your password, please run export PASSWD=<yourPassword>

test_factorial.py:20: SystemExit
2 error in 0.03 seconds

请注意,每种情况下打印的随机数都不同,因此这表明装置实际上触发了两次,对于该类中的每种方法一次。

这是非常奇怪的行为。有任何线索吗?

2 个答案:

答案 0 :(得分:1)

pytest捕获SystemExit异常,这在您考虑时是合理的:如果您正在测试碰巧调用sys.exit的函数,则您不希望此事件关闭整个系统测试套件。

使用pytest.exit代替sys.exit,这向pytest表示您确实要关闭测试套件。

答案 1 :(得分:0)

通过使用灯具内的pytest.skip可以达到预期的效果。这样,如果灯具抛出一些异常,将跳过使用灯具的测试。