<h3>固定装置</h3>
<p>也可以将自动使用装置用于方法级别的设置/拆卸。由于fixture的灵活性,我更喜欢使用fixture—如果需要,您可以定义特定于类的方法setup/teardown(为每个测试方法运行)或方法特定的setup/teardown(仅为特定测试运行)。示例:</p>
<pre><code>import pytest
class TestFoo:
@pytest.fixture(autouse=True)
def foo(self):
print('\nTestFoo instance setting up')
yield
print('TestFoo instance tearing down')
class TestBar(TestFoo):
@pytest.fixture(autouse=True)
def bar(self, foo):
print('TestBar instance setting up')
yield
print('TestBar instance tearing down')
class TestBaz(TestBar):
@pytest.fixture(autouse=True)
def baz(self, bar):
print('TestBaz instance setting up')
yield
print('\nTestBaz instance tearing down')
def test_eggs(self):
assert True
def test_bacon(self):
assert True
</code></pre>
<p>测试执行结果:</p>
^{pr2}$
<p>请注意,我通过arg依赖项指定fixture的执行顺序(例如<code>def bar(self, foo):</code>所以<code>bar</code>是在<code>foo</code>之后执行的);如果省略参数,执行顺序<code>foo -> bar -> baz</code>就不能得到保证。如果不需要显式排序,可以安全地省略fixture参数。在</p>
<p>上面的示例,仅针对<code>TestBaz::test_bacon</code>扩展了设置/拆卸:</p>
<pre><code>class TestBaz(TestBar):
@pytest.fixture(autouse=True)
def baz(self, bar):
print('TestBaz instance setting up')
yield
print('\nTestBaz instance tearing down')
@pytest.fixture
def bacon_specific(self):
print('bacon specific test setup')
yield
print('\nbacon specific teardown')
def test_eggs(self):
assert True
@pytest.mark.usefixtures('bacon_specific')
def test_bacon(self):
assert True
</code></pre>
<p>执行结果:</p>
<pre><code>...
test_spam.py::TestBaz::test_bacon
TestFoo instance setting up
TestBar instance setting up
TestBaz instance setting up
bacon specific test setup
PASSED
bacon specific teardown
TestBaz instance tearing down
TestBar instance tearing down
TestFoo instance tearing down
</code></pre>
<p>通过将fixture范围调整为<code>class</code>,可以实现每个类的一次性设置/拆卸:</p>
<pre><code>class TestFoo:
@pytest.fixture(autouse=True, scope='class')
def foo(self):
print('\nTestFoo instance setting up')
yield
print('TestFoo instance tearing down')
class TestBar(TestFoo):
@pytest.fixture(autouse=True, scope='class')
def bar(self, foo):
print('TestBar instance setting up')
yield
print('TestBar instance tearing down')
class TestBaz(TestBar):
@pytest.fixture(autouse=True, scope='class')
def baz(self, bar):
print('TestBaz instance setting up')
yield
print('\nTestBaz instance tearing down')
def test_eggs(self):
assert True
def test_bacon(self):
assert True
</code></pre>
<p>执行:</p>
<pre><code>collected 2 items
test_spam2.py::TestBaz::test_eggs
TestFoo instance setting up
TestBar instance setting up
TestBaz instance setting up
PASSED
test_spam2.py::TestBaz::test_bacon PASSED
TestBaz instance tearing down
TestBar instance tearing down
TestFoo instance tearing down
</code></pre>
<h3>xUnit方法设置/拆卸</h3>
<p>您可以使用xUnit样式设置,特别是<a href="https://docs.pytest.org/en/latest/xunit_setup.html#method-and-function-level-setup-teardown" rel="nofollow noreferrer">Method and function level setup/teardown</a>;这些是常用的类方法,支持继承。示例:</p>
<pre><code>class TestFoo:
def setup_method(self):
print('\nTestFoo::setup_method called')
def teardown_method(self):
print('TestFoo::teardown_method called')
class TestBar(TestFoo):
def setup_method(self):
super().setup_method()
print('TestBar::setup_method called')
def teardown_method(self):
print('TestBar::teardown_method called')
super().teardown_method()
class TestBaz(TestBar):
def setup_method(self):
super().setup_method()
print('TestBaz::setup_method called')
def teardown_method(self):
print('\nTestBaz::teardown_method called')
super().teardown_method()
def test_eggs(self):
assert True
def test_bacon(self):
assert True
</code></pre>
<p>测试执行结果:</p>
<pre><code>collected 2 items
test_spam.py::TestBaz::test_eggs
TestFoo::setup_method called
TestBar::setup_method called
TestBaz::setup_method called
PASSED
TestBaz::teardown_method called
TestBar::teardown_method called
TestFoo::teardown_method called
test_spam.py::TestBaz::test_bacon
TestFoo::setup_method called
TestBar::setup_method called
TestBaz::setup_method called
PASSED
TestBaz::teardown_method called
TestBar::teardown_method called
TestFoo::teardown_method called
</code></pre>