unittest中setUp与tearDown

在unittest中用例执行的先后顺序是根据数字、字母的先后顺序来判定的,如果要按照预定的顺序执行方法如下:

1.用字母、数字先后顺序排序(缺点:用例名称会不够美观、杂乱无章)

2.用testsuite控制用例加载顺序(缺点:当case较多时,逐个添加非常麻烦)

每次执行用例时,unittest.TestCase的类下每个test开头的方法(就是用例)时,都会执行setUp和tearDown

如下:

import unittest
 
class TestSetupTeardown(unittest.TestCase):
    def setUp(self):
        print('连接数据库成功...')
    def tearDown(self):
        print('关闭数据库。')
    def test_a(self):
        print('test_a')
    def test_b(self):
        print('test_b')
 
if __name__ == '__main__':
    unittest.main()

执行效果如下:

setUp连接数据库,tearDown关闭数据库,这样反复执行,无疑是会增加数据库服务器资源的损耗,且浪费时间

而且下一个用例的执行需要依赖上一个用例的执行结果时,应该怎么办?

1.在需要依赖的case中,将上一个case单独拎出来做一个公用的方法。然后在进入这个case时先调用该方法。例如caseB需要caseA返回的结果,那么我先将caseA封装成一个通用的方法,根据传入的参数不同返回不同的值。然后在caseB中获取返回的值,作为caseB开始前的另一种变相的 ‘setup’。代码如下:

import unittest

def set_A(a, b):
    a = a*2
    b = b*2
    return (a, b)

class Test_setup_and_teardwon(unittest.TestCase):

    def setUp(self):
        self.a = 2 
        self.b = 3
        print('set up over :')
        print('a = %s, b = %s \n'%(self.a, self.b))

    def tearDown(self):
        a = 0
        b = 0
        print('tear down over :')
        print('a = %s, b = %s'%(a, b))
        print('__________________________________________________________')

    def test_case_B(self):
        (a, b) = set_A(self.a, self.b)
        a = a*2
        b = b*2
        print('run B over :')
        print('a= %s, b = %s \n'%(a, b))

    def test_case_A(self):
        a = self.a*2
        b = self.b*2
        print('run A over :')
        print('a = %s, a = %s \n'%(a, b))

    def test_case_C(self):
        a = self.a*4
        b = self.b*4
        print('run C over :')
        print('a = %s, a = %s \n'%(a, b))

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTest(Test_setup_and_teardwon("test_case_A"))
    suite.addTest(Test_setup_and_teardwon("test_case_B"))
    suite.addTest(Test_setup_and_teardwon("test_case_C"))
    runner = unittest.TextTestRunner()
    runner.run(suite)

执行结果:

set up over :
.a = 2, b = 3 

run A over :
a = 4, a = 6 

tear down over :
a = 0, b = 0
__________________________________________________________
set up over :
a = 2, b = 3 

run B over :
a= 8, b = 12 

tear down over :
.a = 0, b = 0
__________________________________________________________
set up over :
a = 2, b = 3 

run C over :
.a = 8, a = 12 

tear down over :
a = 0, b = 0
__________________________________________________________

----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK
[Finished in 0.1s]

但是在测试用例难以解耦的情况下,每写下一个用例就要封装上一个用例的方法,这会导致代码长度翻倍增长。

因此在此处对于用例之间依赖性较强的模块,控制setUp和tearDown方法只执行一次很有必要

【解决方案】:

将setup()  和teardown() 换成setUpClass()和tearDownClass()

【注意事项】:

setUpClass():必须使用@classmethod 装饰器,  所有case运行之前只运行一次
tearDownClass():必须使用@classmethod装饰器, 所有case运行完之后只运行一次

执行效果如下:

import unittest
 
class TestSetupTeardown(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print('连接数据库成功...')
    @classmethod
    def tearDownClass(cls):
        print('关闭数据库。')
    def test_a(self):
        print('test_a')
    def test_b(self):
        print('test_b')
 
if __name__ == '__main__':
    unittest.main()

用例运行级别

  • 模块级(setup_module/teardown_module)开始于模块始末,全局的

  • 函数级(setup_function/teardown_function)只对函数用例生效(不在类中)

  • 类级(setup_class/teardown_class)只在类中前后运行一次(在类中)

  • 方法级(setup_method/teardown_method)开始于方法始末(在类中)

  • 类里面的(setup/teardown)运行在调用方法的前后

# coding:utf-8
import pytest
# 类和方法
 
def setup_module():
    print("setup_module:整个.py模块只执行一次")
    print("比如:所有用例开始前只打开一次浏览器")
 
def teardown_module():
    print("teardown_module:整个.py模块只执行一次")
    print("比如:所有用例结束只最后关闭浏览器")
 
def setup_function():
    print("setup_function:每个用例开始前都会执行")
 
def teardown_function():
    print("teardown_function:每个用例结束前都会执行")
 
def test_one():
    print("正在执行----test_one")
    x = "this"
    assert 'h' in x
 
def test_two():
    print("正在执行----test_two")
    x = "hello"
    assert 'h' in x
 
class TestCase():
 
    def setup_class(self):
        print("setup_class:类中所有用例执行之前")
 
    def teardown_class(self):
        print("teardown_class:类中所有用例执行之后")
 
    def setup(self):
        print("setup:类中每个用例执行之前")
    def teardown(self):
        print("teardown:类中每个用例执行之后")
    def setup_method(self):
        print("setup_method:类中每个用例执行之前")
    def teardown_method(self):
        print("teardown_method:类中每个用例执行之后")
 
    def test_three(self):
        print("正在执行----test_three")
        x = "this"
        assert 'h' in x
 
    def test_four(self):
        print("正在执行----test_four")
        x = "hello"
        assert  'h' in x
 
if __name__ == "__main__":
  pytest.main(["-s", "Testcase2.py"])

运行结果:

Testcase2.py setup_module:整个.py模块只执行一次
比如:所有用例开始前只打开一次浏览器
setup_function:每个用例开始前都会执行
.正在执行----test_one
teardown_function:每个用例结束前都会执行
setup_function:每个用例开始前都会执行
.正在执行----test_two
teardown_function:每个用例结束前都会执行
setup_class:类中所有用例执行之前
setup_method:类中每个用例执行之前
setup:类中每个用例执行之前
.正在执行----test_three
teardown:类中每个用例执行之后
teardown_method:类中每个用例执行之后
setup_method:类中每个用例执行之前
setup:类中每个用例执行之前
.正在执行----test_four
teardown:类中每个用例执行之后
teardown_method:类中每个用例执行之后
teardown_class:类中所有用例执行之后
teardown_module:整个.py模块只执行一次
比如:所有用例结束只最后关闭浏览器

setup_module/teardown_module的优先级是最大的,然后函数里面用到的setup_function/teardown_function与类里面的setup_class/teardown_class互不干涉

类里面的setup_method和teardown_method的功能和setup/teardown功能是一样的,一般二者用其中一个即可

 

 参考原文链接:

https://www.cnblogs.com/UncleYong/p/7076872.html

https://blog.csdn.net/qq_27261401/article/details/78312252

https://blog.csdn.net/yaoliuwei1426/article/details/82146316

 

posted @ 2020-02-01 14:27  snoweveryday  阅读(1572)  评论(0编辑  收藏  举报