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

时间:2022-04-24 19:20:53

I want to run additional setup and teardown checks before and after each test in my test suite. I've looked at fixtures but not sure on whether they are the correct approach. I need to run the setup code prior to each test and I need to run the teardown checks after each test.

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

My use-case is checking for code that doesn't cleanup correctly: it leaves temporary files. In my setup I will check the files and in the teardown I also check the files. If there are extra files I want the test to fail.

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

6 个解决方案

#1


23  

py.test fixtures are a technically adequate method to achieve your purpose.

py.test灯具是一种技术上足够的方法来实现您的目的。

You just need to define a fixture like that:

你只需要定义一个这样的夹具:

@pytest.yield_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

By declaring your fixture with autouse=True, it will be automatically invoked for each test function defined in the same module.

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

That said, there is one caveat. Asserting at setup/teardown is a controversial practice. I'm under the impression that the py.test main authors do not like it (I do not like it either, so that may colour my own perception), so you might run into some problems or rough edges as you go forward.

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

#2


7  

Fixtures are exactly what you want. That's what they are designed for.

夹具正是您想要的。这就是他们的设计目标。

Whether you use pytest style fixtures, or setup and teardown (module, class, or method level) xUnit style fixtures, depends on the circumstance and personal taste.

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

From what you are describing, it seems like you could use pytest autouse fixtures.
Or xUnit style function level setup_function()/teardown_function().

根据你的描述,似乎你可以使用pytest autouse灯具。或xUnit样式函数级别setup_function()/ teardown_function()。

Pytest has you completely covered. So much so that perhaps it's a fire hose of information.

Pytest让你完全覆盖。这么多,以至于它可能是一个信息消防软管。

#3


5  

You can use Module level setup/teardown Fixtures of Pytest.

您可以使用模块级别设置/拆卸Pytest灯具。

Here's the Link

这是链接

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

It Works as follows:

它的工作原理如下:

 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

It will call setup_module before this test and teardown_module after test completes.

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

You can include this fixture in each test-script to run it for each test.

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

IF you want to use something that is common to all tests in a directory You can use package/directory level fixtures nose framework

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

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

In __init__.py file of the package you can include following

在包的__init__.py文件中,您可以包含以下内容

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

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

#4


4  

You may use decorators but programatically, so you don't need to put the decorator in each method.

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

I'm assuming several things in next code:

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

The test methods are all named like: "testXXX()" The decorator is added to the same module where test methods are implemented.

测试方法都命名为:“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])

Now if you call the test methods...

现在,如果你打电话给测试方法......

test1()
test2()

The output should be something like:

输出应该是这样的:

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>

If you have test methods as class methods, the approach is also valid. For instance:

如果您将测试方法作为类方法,则该方法也是有效的。例如:

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

The call to TestClass.my_test() will print:

对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  

Take a look at python decorators https://wiki.python.org/moin/PythonDecorators

看看python decorators https://wiki.python.org/moin/PythonDecorators

#6


0  

Fixtures by default have scope=function. So, if you just use a definition such as

默认情况下,灯具具有scope = function。所以,如果你只是使用诸如的定义

@pytest.fixture
def fixture_func(self)

It defaults to (scope='function').

它默认为(scope ='function')。

So any finalizes in the fixture function will be called after each test.

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

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

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

#1


23  

py.test fixtures are a technically adequate method to achieve your purpose.

py.test灯具是一种技术上足够的方法来实现您的目的。

You just need to define a fixture like that:

你只需要定义一个这样的夹具:

@pytest.yield_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

By declaring your fixture with autouse=True, it will be automatically invoked for each test function defined in the same module.

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

That said, there is one caveat. Asserting at setup/teardown is a controversial practice. I'm under the impression that the py.test main authors do not like it (I do not like it either, so that may colour my own perception), so you might run into some problems or rough edges as you go forward.

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

#2


7  

Fixtures are exactly what you want. That's what they are designed for.

夹具正是您想要的。这就是他们的设计目标。

Whether you use pytest style fixtures, or setup and teardown (module, class, or method level) xUnit style fixtures, depends on the circumstance and personal taste.

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

From what you are describing, it seems like you could use pytest autouse fixtures.
Or xUnit style function level setup_function()/teardown_function().

根据你的描述,似乎你可以使用pytest autouse灯具。或xUnit样式函数级别setup_function()/ teardown_function()。

Pytest has you completely covered. So much so that perhaps it's a fire hose of information.

Pytest让你完全覆盖。这么多,以至于它可能是一个信息消防软管。

#3


5  

You can use Module level setup/teardown Fixtures of Pytest.

您可以使用模块级别设置/拆卸Pytest灯具。

Here's the Link

这是链接

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

It Works as follows:

它的工作原理如下:

 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

It will call setup_module before this test and teardown_module after test completes.

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

You can include this fixture in each test-script to run it for each test.

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

IF you want to use something that is common to all tests in a directory You can use package/directory level fixtures nose framework

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

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

In __init__.py file of the package you can include following

在包的__init__.py文件中,您可以包含以下内容

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

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

#4


4  

You may use decorators but programatically, so you don't need to put the decorator in each method.

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

I'm assuming several things in next code:

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

The test methods are all named like: "testXXX()" The decorator is added to the same module where test methods are implemented.

测试方法都命名为:“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])

Now if you call the test methods...

现在,如果你打电话给测试方法......

test1()
test2()

The output should be something like:

输出应该是这样的:

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>

If you have test methods as class methods, the approach is also valid. For instance:

如果您将测试方法作为类方法,则该方法也是有效的。例如:

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

The call to TestClass.my_test() will print:

对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  

Take a look at python decorators https://wiki.python.org/moin/PythonDecorators

看看python decorators https://wiki.python.org/moin/PythonDecorators

#6


0  

Fixtures by default have scope=function. So, if you just use a definition such as

默认情况下,灯具具有scope = function。所以,如果你只是使用诸如的定义

@pytest.fixture
def fixture_func(self)

It defaults to (scope='function').

它默认为(scope ='function')。

So any finalizes in the fixture function will be called after each test.

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

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

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