pytest 2.测试用例setup和teardown以及使用@pytest.fixture()装饰器来实现部分用例的前后置,param参数化,ids(不显示unicode编码),name(别名)
之前我写的unittest的setup和teardown,还有setupClass和teardownClass(需要配合@classmethod装饰器一起使用),接下来就介绍pytest的类似于这类的固件。
(1.setup_function、teardown_function 2.setup_class、teardown_class 3.setup_method、teardown_method 4.setup_module、teardown_module)
setup/teardown和unittest里面的setup/teardown是一样的功能,这里setup_method和teardown_method的功能和setup/teardown功能是一样的,优先级是先执行setup_method,在执行setup。一般二者用其中一个即可,就不详细介绍了。setup_class和teardown_class等价于unittest里面的setupClass和teardownClass
一、函数级的(setup_function、teardown_function)只对函数用例生效,而且不在类中使用
#!/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
二、类级的(setup_class、teardown_class)在类中使用,类执行之前运行一次,类执行之后运行一次
#!/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
三、类中方法级的(setup_method、teardown_method)在每一个方法之前执行一次,在每一个方法之后执行一次,和setup和teardown一样
#!/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
四、模块级的(setup_module、teardown_module)全局的,在模块执行前运行一遍,在模块执行后运行一遍
#!/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
五、当类和函数都有的时候
#!/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()装饰器来实现部分用例的前后置。
""" scope:表示的是被@pytest.fixture标记的方法的作用于。 function(默认),class,module,package/session params: 参数化(支持:列表[],元祖(),字典列表[{}{}{}],字典原则({}{}{})) autouse: 自动使用(True),默认是False(不自动执行)如果,所有的方法都去使用的话,那么就设置成True,方法调用里面也不需要在传入。 ids: 当时用params参数化时,给每一个值设置一个变量名,意义不大。 name: 表示给被@pytest.fixture标记的方法取一个别名 """ import pytest @pytest.fixture(scope="function") def my_fixture(): print("这是前置的方法") yield # 加上yield实现后置 print("这是后置的方法") class TestMashang: def test_01_shuguo(self): print('\n测试蜀国') def test_02_weiguo(self, my_fixture): print('\n测试魏国') # 预期: # 蜀国没有前置 # 魏国有前置 # 这是只有一个去使用my_fixture if __name__ == '__main__': pytest.main(['-vs'])
这是结果:
当所有方法都需要传my_fixture的时候,那就只需要设置autouse=True就可以
import pytest @pytest.fixture(scope="function", autouse=True) def my_fixture(): print("这是前置的方法") yield # 加上yield实现后置 print("这是后置的方法") class TestMashang: def test_01_shuguo(self): print('\n测试蜀国') def test_02_weiguo(self): print('\n测试魏国') if __name__ == '__main__': pytest.main(['-vs'])
结果:
参数化:
当 return 返回去的时候,就会把值传给要调用的方法里面。
import pytest @pytest.fixture(scope="function", params=['刘备', '张飞', '关羽']) def my_fixture(): # print("这是前置的方法") # yield # 加上yield实现后置 # print("这是后置的方法") return "success" # return的值会传入到需要用的函数里面 # return request.param class TestMashang: def test_01_shuguo(self, my_fixture): print('\n测试蜀国') print('-------------'+str(my_fixture)) def test_02_weiguo(self): print('\n测试魏国')
结果:
当用request传的时候:
import pytest @pytest.fixture(scope="function", params=['刘备', '张飞', '关羽']) def my_fixture(request): # return "success" # return的值会传入到需要用的函数里面 return request.param class TestMashang: def test_01_shuguo(self, my_fixture): print('\n测试蜀国') print('-------------'+str(my_fixture)) def test_02_weiguo(self): print('\n测试魏国')
结果:
如果想要用前后置,还想要参数,那么yield和return不可以一起用。只能用一个。:return和yield都是返回的意思,但是return的后面不能有代码,yield返回后面可以接代码。
import pytest @pytest.fixture(scope="function", params=['刘备', '张飞', '关羽']) def my_fixture(request): print("这是前置的方法") yield request.param # 加上yield实现后置 print("这是后置的方法") # return "success" # return的值会传入到需要用的函数里面 # return request.param class TestMashang: def test_01_shuguo(self, my_fixture): print('\n测试蜀国') print('-------------'+str(my_fixture)) def test_02_weiguo(self): print('\n测试魏国')
结果:
ids:起个别名,比如以上的执行后,显示的是unicode编码,用ids改变变量
改了之后:
import pytest @pytest.fixture(scope="function", params=['刘备', '张飞', '关羽'], ids=['lb', 'zf', 'gy']) def my_fixture(request): print("这是前置的方法") yield request.param # 加上yield实现后置 print("这是后置的方法") # return "success" # return的值会传入到需要用的函数里面 # return request.param class TestMashang: def test_01_shuguo(self, my_fixture): print('\n测试蜀国') print('-------------'+str(my_fixture)) def test_02_weiguo(self): print('\n测试魏国')
结果:
name:就是给方法起个别名:把上面的my_fixture换成了别名而已;当取了别名之后,原来的名称my_fixture就用不了了
import pytest @pytest.fixture(scope="function", params=['刘备', '张飞', '关羽'], ids=['lb', 'zf', 'gy'], name='inputparam') def my_fixture(request): print("这是前置的方法") yield request.param # 加上yield实现后置 print("这是后置的方法") # return "success" # return的值会传入到需要用的函数里面 # return request.param class TestMashang: def test_01_shuguo(self, inputparam): print('\n测试蜀国') print('-------------'+str(inputparam)) def test_02_weiguo(self): print('\n测试魏国')