在 py.test 的每个测试之前和之后运行代码?

我想在测试套件中的每个测试之前和之后运行额外的安装和拆卸检查。我研究过固定装置,但不确定它们是否是正确的方法。我需要在每个测试之前运行安装代码,并且在每个测试之后运行拆卸检查。

我的用例正在检查不能正确清理的代码: 它会留下临时文件。在我的设置中,我将检查文件,并在拆卸我也检查文件。如果有额外的文件,我希望测试失败。

149263 次浏览

您可以使用装饰器,但是以编程的方式,所以您不需要在每个方法中放置装饰器。

我在下一个代码中假设了几件事:

测试方法都命名为: “ testXXX ()” 修饰符被添加到实现测试方法的相同模块中。

def test1():
print ("Testing hello world")


def test2():
print ("Testing hello world 2")


#This is the decorator
class TestChecker(object):
def __init__(self, testfn, *args, **kwargs):
self.testfn = testfn


def pretest(self):
print ('precheck %s' % str(self.testfn))
def posttest(self):
print ('postcheck %s' % str(self.testfn))
def __call__(self):
self.pretest()
self.testfn()
self.posttest()




for fn in dir() :
if fn.startswith('test'):
locals()[fn] = TestChecker(locals()[fn])

现在如果你调用测试方法..。

test1()
test2()

输出应该是这样的:

precheck <function test1 at 0x10078cc20>
Testing hello world
postcheck <function test1 at 0x10078cc20>
precheck <function test2 at 0x10078ccb0>
Testing hello world 2
postcheck <function test2 at 0x10078ccb0>

如果您将测试方法作为类方法,那么该方法也是有效的:

class TestClass(object):
@classmethod
def my_test(cls):
print ("Testing from class method")


for fn in dir(TestClass) :
if not fn.startswith('__'):
setattr(TestClass, fn, TestChecker(getattr(TestClass, fn)))

打给 TestClass.my_test()的电话将打印:

precheck <bound method type.my_test of <class '__main__.TestClass'>>
Testing from class method
postcheck <bound method type.my_test of <class '__main__.TestClass'>>

Test fixture 是实现目标的一种技术上足够的方法。

你只需要定义一个这样的装置:

@pytest.fixture(autouse=True)
def run_around_tests():
# Code that will run before your test, for example:
files_before = # ... do something to check the existing files
# A test function will be run at this point
yield
# Code that will run after your test, for example:
files_after = # ... do something to check the existing files
assert files_before == files_after

通过使用 autouse=True声明您的 fixture,它将被同一模块中定义的每个测试函数自动调用。

尽管如此,还是有一点需要注意。在安装/拆卸时断言是一种有争议的做法。我的印象是 py.test 的主要作者不喜欢它(我也不喜欢它,所以这可能会影响我自己的看法) ,所以当您向前推进时可能会遇到一些问题或粗糙的边缘。

你可以使用 Pytest 的模块级设置/拆卸装置。

这是链接

Http://pytest.org/latest/xunit_setup.html

它的工作原理如下:

 def setup_module(module):
""" setup any state specific to the execution of the given module."""


def teardown_module(module):
""" teardown any state that was previously setup with a setup_module
method."""


Test_Class():
def test_01():
#test 1 Code

它将在测试前调用 setup_module,在测试完成后调用 teardown_module

您可以在每个测试脚本中包含这个 fixture,以便为每个测试运行它。

如果您希望使用某个目录中所有测试都通用的内容,那么可以使用包/目录级 fixture 鼻子框架

Http://pythontesting.net/framework/nose/nose-fixture-reference/#package

在包的 __init__.py文件中可以包括以下内容

     def setup_package():
'''Set up your environment for test package'''


def teardown_package():
'''revert the state '''

固定装置正是你想要的。 这就是设计它们的目的。

是否使用 最小型的固定装置,或者 设计拆除(模块、类或方法级别) xUnit 风格的 fixture,取决于环境和个人喜好。

从您所描述的来看,似乎您可以使用 最简单的汽车用固定装置
或 xUnit 样式函数级别 Setup _ function ()/teardown _ function ()

Pytest 把你完全包围了,以至于可能是一条信息的消防水管。

默认情况下,夹具有 scope=function

@pytest.fixture
def fixture_func(self)

它默认为 (scope='function')

因此,fixture 函数中的任何终结器都将在每次测试之后调用。

您可以使用 fixture来实现您想要的结果。

import pytest


@pytest.fixture(autouse=True)
def run_before_and_after_tests(tmpdir):
"""Fixture to execute asserts before and after a test is run"""
# Setup: fill with any logic you want


yield # this is where the testing happens


# Teardown : fill with any logic you want

详细说明

  1. 因此,这个装置将在每次执行测试时运行。

  2. # Setup: fill with any logic you want,这个逻辑将在每个测试实际运行之前执行。在您的示例中,您可以添加将在实际测试之前执行的断言语句。

  3. yield,正如注释中指出的,这是测试发生的地方

  4. # Teardown : fill with any logic you want,这个逻辑将在每次测试后执行。控件期间发生的任何事情都保证运行此逻辑 测试。

注意: 在 pytest中,失败的测试和执行测试时的错误是有区别的。失败表示测试在某种程度上失败。 “错误”表示您无法进行正确的测试。

考虑以下例子:

在运行测试之前断言失败-> ERROR

import pytest




@pytest.fixture(autouse=True)
def run_around_tests():
assert False # This will generate an error when running tests
yield
assert True


def test():
assert True


测试运行后,断言失败-> ERROR

import pytest




@pytest.fixture(autouse=True)
def run_around_tests():
assert True
yield
assert False


def test():
assert True

测试失败-> 失败

import pytest




@pytest.fixture(autouse=True)
def run_around_tests():
assert True
yield
assert True


def test():
assert False


测试通过-> 通过

import pytest




@pytest.fixture(autouse=True)
def run_around_tests():
assert True
yield
assert True


def test():
assert True

这是一个古老的问题,但我个人从 医生中找到了另一种解决方法: 使用 pytest.ini文件:

[pytest]
usefixtures = my_setup_and_tear_down
import pytest


@pytest.fixture
def my_setup_and_tear_down():


# SETUP
# Write here the logic that you need for the setUp


yield # this statement will let the tests execute


# TEARDOWN
# Write here the logic that you need after each tests

关于屈服语句以及它如何允许运行测试: 给你