Python 如何使用测试正确设置和拆除我的 pytest 类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26405380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I correctly setup and teardown my pytest class with tests?
提问by avasin
I am using selenium for end to end testing and I can't get how to use setup_classand teardown_classmethods.
我正在使用 selenium 进行端到端测试,但我不知道如何使用setup_class和teardown_class方法。
I need to set up browser in setup_classmethod, then perform a bunch of tests defined as class methods and finally quit browser in teardown_class method.
我需要在setup_class方法中设置浏览器,然后执行一系列定义为类方法的测试,最后在teardown_class 方法中退出浏览器。
But logically it seems bad solution, because in fact my tests will work not with class, but with object. I pass selfparam inside every test method, so I can access objects' vars:
但从逻辑上讲,这似乎是一个糟糕的解决方案,因为实际上我的测试不适用于类,而是适用于对象。我self在每个测试方法中传递参数,所以我可以访问对象的变量:
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
And it even seems not to be correct to create browser instance for class.. It should be created for every object separately, right?
甚至为类创建浏览器实例似乎也不正确......它应该为每个对象单独创建,对吧?
So, I need to use __init__and __del__methods instead of setup_classand teardown_class?
所以,我需要使用__init__and__del__方法而不是setup_classand teardown_class?
回答by Bruno Oliveira
When you write "tests defined as class methods", do you really mean class methods(methods which receive its classas first parameter) or just regular methods (methods which receive an instanceas first parameter)?
当您编写“定义为类方法的测试”时,您的意思是类方法(接收其类作为第一个参数的方法)还是只是常规方法(接收实例作为第一个参数的方法)?
Since your example uses selffor the test methods I'm assuming the latter, so you just need to use setup_methodinstead:
由于您的示例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
The test method instance is passed to setup_methodand teardown_method, but can be ignored if your setup/teardown code doesn't need to know the testing context. More information can be found here.
测试方法实例传递给setup_methodand teardown_method,但如果您的设置/拆卸代码不需要知道测试上下文,则可以忽略。可以在此处找到更多信息。
I also recommend that you familiarize yourself with py.test's fixtures, as they are a more powerful concept.
我还建议您熟悉 py.test 的fixtures,因为它们是一个更强大的概念。
回答by ecoe
As @Bruno suggested, using pytest fixtures is another solution that is accessible for both test classes or even just simple test functions. Here's an example testing python2.7 functions:
正如@Bruno 建议的那样,使用 pytest 固定装置是另一种解决方案,可用于两个测试类甚至只是简单的测试函数。这是一个测试 python2.7 函数的示例:
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..."
So, running test_1...produces:
所以,运行test_1...产生:
I setup... and now I'm testing things...
I setup ... but now I'm torn down...
Notice that stuff_i_setupis referenced in the fixture, allowing that object to be setupand torn downfor the test it's interacting with. You can imagine this could be useful for a persistent object, such as a hypothetical database or some connection, that must be cleared before each test runs to keep them isolated.
请注意,stuff_i_setup在fixture 中引用了该对象,从而允许该对象存在setup并torn down进行与之交互的测试。您可以想象这对于持久性对象(例如假设的数据库或某个连接)可能很有用,在每次测试运行之前必须清除这些对象以保持它们之间的隔离。
回答by Everett Toews
According to Fixture finalization / executing teardown codeuse of addfinalizeris "historical".
根据Fixture 最终确定/执行拆卸代码的使用addfinalizer是“历史性的”。
As historical note, another way to write teardown code is by accepting a request object into your fixture function and can call its request.addfinalizer one or multiple times:
作为历史记录,另一种编写拆卸代码的方法是接受一个请求对象到你的夹具函数中,并且可以一次或多次调用它的 request.addfinalizer:
The current best practice for setup and teardown is to use yield
当前设置和拆卸的最佳实践是使用 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))
Running it results in
运行它会导致
$ 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 ===
回答by Okken
Your code should work just as you expect it to if you add @classmethoddecorators.
如果您添加@classmethod装饰器,您的代码应该像您期望的那样工作。
@classmethod
def setup_class(cls):
"Runs once per class"
@classmethod
def teardown_class(cls):
"Runs at end of class"
See http://pythontesting.net/framework/pytest/pytest-xunit-style-fixtures/
见http://pythontesting.net/framework/pytest/pytest-xunit-style-fixtures/
回答by Kiran Vemuri
This might help http://docs.pytest.org/en/latest/xunit_setup.html
这可能有助于http://docs.pytest.org/en/latest/xunit_setup.html
In my test suite, I group my test cases into classes. For the setup and teardown I need for all the test cases in that class, I use the setup_class(cls)and teardown_class(cls)classmethods.
在我的测试套件中,我将我的测试用例分组到类中。对于该类中所有测试用例的设置和拆卸,我使用setup_class(cls)和teardown_class(cls)类方法。
And for the setup and teardown I need for each of the test case, I use the setup_method(method)and teardown_method(methods)
对于每个测试用例所需的设置和拆卸,我使用setup_method(method)和teardown_method(methods)
Example:
例子:
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
Now when I run my tests, when the TestClass execution is starting, it logs the details for when it is beginning execution, when it is ending execution and same for the methods..
现在,当我运行测试时,当 TestClass 执行开始时,它会记录开始执行的时间、结束执行的时间以及方法的详细信息。
You can add up other setup and teardown steps you might have in the respective locations.
您可以在相应位置添加其他设置和拆卸步骤。
Hope it helps!
希望能帮助到你!

