我正在使用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
请注意,每种情况下打印的随机数都不同,因此这表明装置实际上触发了两次,对于该类中的每种方法一次。
这是非常奇怪的行为。有任何线索吗?
答案 0 :(得分:1)
pytest捕获SystemExit
异常,这在您考虑时是合理的:如果您正在测试碰巧调用sys.exit
的函数,则您不希望此事件关闭整个系统测试套件。
使用pytest.exit
代替sys.exit
,这向pytest表示您确实要关闭测试套件。
答案 1 :(得分:0)
通过使用灯具内的pytest.skip
可以达到预期的效果。这样,如果灯具抛出一些异常,将跳过使用灯具的测试。