Pytest的setup和teardown
Pytest的setup和teardown
pytest实际上是python自带测试框架unittest的扩展,那么pytest是如何实现unittest中的setup和teardown的呢?
pytest初始化的类别和作用域
模块级别(Module level setup/teardown):作用于一个模块内的所有class和def,对于所有class和def,setup和teardown只执行一次
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. """
eg:
#!/usr/bin/env/python # -*-coding:utf-8-*- import pytest """ 开始于模块始末,全局的 setup_module teardown_module """ def setup_module(): print "setup_module():在模块最之前执行\n" def teardown_module(): print "teardown_module:在模块之后执行" def setup_function(): print "setup_function():每个方法之前执行" def teardown_function(): print "teardown_function():每个方法之后执行\n" def test_01(): print "正在执行test1" x = "this" assert 'h' in x def add(a,b): return a+b def test_add(): print "正在执行test_add()" assert add(3,4) == 7
运行结果:setup_module --> setup_function --> test_01--> teardown_function --> setup_function --> test_add()--> teardown_function --> teardown_module
类级别(Class level setup/teardown):作用于一个class内中的所有test,所有用例只执行一次setup,当所有用例执行完成后,才会执行teardown
@classmethod def setup_class(cls): """ setup any state specific to the execution of the given class (which usually contains tests). """ @classmethod def teardown_class(cls): """ teardown any state that was previously setup with a call to setup_class. """
eg:
#!/usr/bin/env/python # -*-coding:utf-8-*- """ 在类之前和之后执行一次 setup_class teardown_class """ import pytest class TestClass(object): def setup_class(self): print "setup_class(self):每个类之前执行一次" def teardown_class(self): print "teardown_class(self):每个类之后执行一次" def add(self,a,b): print "这是加法运算" return a+b def test_01(self): print "正在执行test1" x = "this" assert 'h' in x def test_add(self): print "正在执行test_add()" assert self.add(3, 4) == 7
执行结果:
可以看出执行的顺序是 setup_class --》 test1 --》test_add()--》teardown_class
方法和函数级别(Method and function level setup/teardown):作用于单个测试用例,若用例没有执行(如被skip了)或失败了,则不会执行teardown
def setup_method(self, method): """ setup any state tied to the execution of the given method in a class. setup_method is invoked for every test method of a class. """ def teardown_method(self, method): """ teardown any state that was previously setup with a setup_method call. """
eg:
#!/usr/bin/env/python # -*-coding:utf-8-*- """ 开始于方法始末(在类中) setup_method teardown_method """ import pytest class TestMethod(object): def setup_class(self): print "setup_class(self):每个类之前执行一次\n" def teardown_class(self): print "teardown_class(self):每个类之后执行一次" def setup_method(self): print "setup_method(self):在每个方法之前执行" def teardown_method(self): print "teardown_method(self):在每个方法之后执行\n" def add(self,a,b): print "这是加法运算" return a+b def test_01(self): print "正在执行test1" x = "this" assert 'h' in x def test_add(self): print "正在执行test_add()" assert self.add(3, 4) == 7
执行结果: setup_class --》 setup_method -->test1 -->teardown_method --》setup_method --> test_add()--》teardown_method --> teardown_class
若用例直接写在模块中,而不是在类中,则用:
def setup_function(function): """ setup any state tied to the execution of the given function. Invoked for every test function in the module. """ def teardown_function(function): """ teardown any state that was previously setup with a setup_function call. """
eg:
#!/usr/bin/env/python # -*-coding:utf-8-*- import pytest """ 只对函数用例生效,不在类中 setup_function teardown_function """ def setup_function(): print "setup_function():每个方法之前执行" def teardown_function(): print "teardown_function():每个方法之后执行" def test_01(): print "正在执行test1" x = "this" assert 'h' in x def test_02(): print "正在执行test2" x = "hello" assert hasattr(x,"hello") def add(a,b): return a+b def test_add(): print "正在执行test_add()" assert add(3,4) == 7 if __name__=="__main__": pytest.main(["-s","test_function.py"])
运行结果为:(-s为了显示用例的打印信息 -q只显示结果不显示过程)
可以看出执行的结果是:
setup_function--》 test_01 --》teardown_function
setup_function--》 test_02 --》teardown_function
setup_function--》 test_add --》teardown_function
当类和函数都有的时候
#!/usr/bin/env/python # -*-coding:utf-8-*- """ 在类之前和之后执行一次 setup_class teardown_class """ import pytest def setup_module(): print "setup_module():在模块最之前执行\n" def teardown_module(): print "teardown_module:在模块之后执行" def setup_function(): print "setup_function():每个方法之前执行" def teardown_function(): print "teardown_function():每个方法之后执行\n" def test_10(): print "正在执行test1" x = "this" assert 'h' in x def add0(a,b): return a+b def test_add(): print "正在执行test_add()" assert add0(3,4) == 7 class TestClass(object): def setup_class(self): print "setup_class(self):每个类之前执行一次" def teardown_class(self): print "teardown_class(self):每个类之后执行一次" def add(self,a,b): print "这是加法运算" return a+b def test_01(self): print "正在执行test1" x = "this" assert 'h' in x def test_add(self): print "正在执行test_add()" assert self.add(3, 4) == 7 if __name__=="__main__": pytest.main(["-s","test_class0.py"])
运行结果:可以看出来,都互不影响,setup_module还是在最之前执行,所有之后执行。
setup_modele --> setup_function -->test1 -->teardown_function --> setuo_function -->test_add -->teardown_function -->setup_class -->teardown_class-->taerdown_module
pytest.fixture()装饰函数,结合yield实现初始化和teardown
举个例子(pytest)文档中的:
import smtplib import pytest @pytest.fixture(scope="module") def smtp(): smtp = smtplib.SMTP("smtp.gmail.com", 587, timeout=5) yield smtp # provide the fixture value print("teardown smtp") smtp.close()
pytest.fixture采用yield实现setup和teardown操作,yield提供的参数为函数名称
与setup_module类似,pytest.fixture可作用于一个模块内的所有def和class。区别在于,必须将pytest.fixture()装饰的函数作为参数传递给用例。
pytest.fixture()装饰的函数必须作为参数传递给用例吗?
- 将class中的smtp_ini都删除,class中的用例执行失败,def用例执行成功;
- 将class中test_send_text的smtp_ini保留,其余2个删除,class中的用例都执行成功?这是为什么呢?只有1个用力传入了参数,但所有用例都执行成功了。
- 将class和def中的smtp_ini都删除,用例全部执行失败。
总结
4种方式的作用域:
- setup_method:仅作用于class用例集中的用例,置于class内,每个用例都会调用一次
- setup_function:作用于独立的def用例,不可作用于class内的用例
- setup_class:作用于class用例集中的用例,置于class内,只在class用例执行的开始执行setup_class,结束时执行teardown_class
- setup_module:作用于模块内的所有用例,置于class外,只在所以用例的开始执行setup_module,结束时执行teardown_module
- pytest.fixture():作用于模块内的所有用例,但需要传递装饰函数为参数,可置于class内或class外
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY