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

时间:2014-03-25 07:09:52

标签: python pytest

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

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

7 个答案:

答案 0 :(得分:35)

py.test灯具是实现您目的的技术上适当的方法。

你只需要定义一个类似的夹具:

@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声明您的灯具,将为同一模块中定义的每个测试功能自动调用它。

那就是说,有一点需要注意。在设置/拆解时断言是一种有争议的做法。我认为py.test主要作者不喜欢它(我也不喜欢它,所以这可能会影响我自己的感知),所以你可能会遇到一些问题或粗糙的边缘

答案 1 :(得分:8)

灯具正是您想要的。 这就是他们的目的。

是否使用 pytest样式灯具,或设置拆卸(模块,类或方法级别)xUnit样式灯具,取决于环境和个人品味。

根据您所描述的内容,您似乎可以使用pytest autouse fixtures 或xUnit样式函数级别setup_function()/teardown_function()

Pytest你已经完全覆盖了。这么多,或许这是一个信息消防软件。

答案 2 :(得分:7)

您可以使用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. @pytest.fixture(autouse=True)from the docs“有时,您可能希望自动调用固定装置,而无需显式声明函数参数或usefixtures装饰器。” ,此固定装置将在每次执行测试时运行。

  2. # Setup: fill with any logic you want,此逻辑将在实际运行每个测试之前执行。根据您的情况,您可以添加将在实际测试之前执行的assert语句。

  3. yield,如评论中所示,这是进行测试的地方

  4. # Teardown : fill with any logic you want,此逻辑将在每次测试后执行。无论在运行期间发生什么情况,都可以确保运行此逻辑。 测试。

注意:在pytest中,执行测试时测试失败和错误之间有区别。失败表示测试以某种方式失败。 错误提示您无法进行适当的测试。

请考虑以下示例:

在测试运行前声明失败->错误

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

测试运行后声明失败->错误

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 Fail

测试通过->通过

import pytest


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

def test():
    assert True

答案 3 :(得分:5)

您可以使用模块级别设置/拆卸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,以便为每个测试运行它。

如果你想使用目录中所有测试通用的东西你可以使用包/目录级别的装置鼻子框架

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 '''

答案 4 :(得分:4)

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

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

测试方法都命名为:" 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'>>

答案 5 :(得分:0)

答案 6 :(得分:0)

默认情况下,灯具有scope=function。所以,如果您只使用

这样的定义
@pytest.fixture
def fixture_func(self)

默认为(范围=&#39;功能&#39;)。

因此,每次测试后都会调用fixture函数中的任何最终结果。

价: 1. http://programeveryday.com/post/pytest-creating-and-using-fixtures-for-streamlined-testing/