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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM