如何通过测试正确设置和拆除我的pytest类?

时间:2014-10-16 13:12:42

标签: python class python-2.7 object pytest

我使用selenium进行端到端测试,但我无法了解如何使用setup_classteardown_class方法。

我需要在setup_class方法中设置浏览器,然后执行一系列定义为类方法的测试,最后在teardown_clas方法中退出浏览器。

但从逻辑上讲,这似乎是一个糟糕的解决方案,因为实际上我的测试不是用于类,而是用于对象。我在每个测试方法中都传递了self param,因此我可以访问对象'瓦尔:

class TestClass:

    def setup_class(cls):
        pass

    def test_buttons(self, data):
        # self.$attribute can be used, but not cls.$attribute?  
        pass

    def test_buttons2(self, data):
        # self.$attribute can be used, but not cls.$attribute?
        pass

    def teardown_class(cls):
        pass

为类创建浏览器实例似乎不正确..它应该分别为每个对象创建,对吧?

那么,我需要使用__init____del__方法而不是setup_classteardown_class

6 个答案:

答案 0 :(得分:49)

根据Fixture finalization / executing teardown code,使用addfinalizer是“历史性的”。

  

作为历史记录,另一种编写拆卸代码的方法是将一个请求对象接受到fixture函数中,并可以一次或多次调用其request.addfinalizer:

目前设置和拆解的最佳做法是使用yield

import pytest

@pytest.fixture()
def resource():
    print("setup")
    yield "resource"
    print("teardown")

class TestResource(object):
    def test_that_depends_on_resource(self, resource):
        print("testing {}".format(resource))

运行它会导致

$ py.test --capture=no pytest_yield.py
=== test session starts ===
platform darwin -- Python 2.7.10, pytest-3.0.2, py-1.4.31, pluggy-0.3.1
collected 1 items

pytest_yield.py setup
testing resource
.teardown


=== 1 passed in 0.01 seconds ===

答案 1 :(得分:37)

当你编写“定义为类方法的测试”时,你真的是指类方法(接收作为第一个参数的方法) )或只是常规方法(接收实例作为第一个参数的方法)?

由于您的示例使用self作为测试方法,我假设后者,所以您只需要使用setup_method代替:

class Test:

    def setup_method(self, test_method):
        # configure self.attribute

    def teardown_method(self, test_method):
        # tear down self.attribute

    def test_buttons(self):
        # use self.attribute for test

测试方法实例传递给setup_methodteardown_method,但如果您的setup / teardown代码不需要知道测试上下文,则可以忽略它。可以找到更多信息here

我还建议您熟悉py.test的fixtures,因为它们是一个更强大的概念。

答案 2 :(得分:17)

正如@Bruno建议的那样,使用pytest fixtures是另一种解决方案,可以为两个测试类甚至只是简单的测试函数访问。 Here's an example testing python2.7 functions

import pytest

@pytest.fixture(scope='function')
def some_resource(request):
    stuff_i_setup = ["I setup"]

    def some_teardown():
        stuff_i_setup[0] += " ... but now I'm torn down..."
        print stuff_i_setup[0]
    request.addfinalizer(some_teardown)

    return stuff_i_setup[0]

def test_1_that_needs_resource(some_resource):
    print some_resource + "... and now I'm testing things..."

因此,运行test_1...会产生:

I setup... and now I'm testing things...
I setup ... but now I'm torn down...

请注意,夹具中引用了stuff_i_setup,允许该对象为setuptorn down进行与之交互的测试。您可以想象这对于持久对象(例如假设数据库或某些连接)非常有用,必须在每次测试运行之前将其清除以保持隔离。

答案 3 :(得分:14)

这可能会有助http://docs.pytest.org/en/latest/xunit_setup.html

在我的测试套件中,我将测试用例分组到类中。对于我需要该类中所有测试用例的设置和拆解,我使用setup_class(cls)teardown_class(cls)类方法。

对于每个测试用例我需要的设置和拆解,我使用setup_method(method)teardown_method(methods)

示例:

lh = <got log handler from logger module>

class TestClass:
    @classmethod
    def setup_class(cls):
        lh.info("starting class: {} execution".format(cls.__name__))

    @classmethod
    def teardown_class(cls):
        lh.info("starting class: {} execution".format(cls.__name__))

    def setup_method(self, method):
        lh.info("starting execution of tc: {}".format(method.__name__))

    def teardown_method(self, method):
        lh.info("starting execution of tc: {}".format(method.__name__))

    def test_tc1(self):
        <tc_content>
        assert 

    def test_tc2(self):
        <tc_content>
        assert

现在,当我运行我的测试时,当TestClass执行开始时,它会记录开始执行时的详细信息,结束执行时的详细信息以及方法的相同内容。

您可以在相应位置添加其他设置和拆卸步骤。

希望它有所帮助!

答案 4 :(得分:10)

如果添加@classmethod装饰器,您的代码应该按预期工作。

@classmethod 
def setup_class(cls):
    "Runs once per class"

@classmethod 
def teardown_class(cls):
    "Runs at end of class"

请参阅http://pythontesting.net/framework/pytest/pytest-xunit-style-fixtures/

答案 5 :(得分:1)

import pytest
class Test:
    @pytest.fixture()
    def setUp(self):
        print("setup")
        yield "resource"
        print("teardown")

    def test_that_depends_on_resource(self, setUp):
        print("testing {}".format(setUp))

要运行:

pytest nam_of_the_module.py -v