溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python unittest單元測試框架總結(jié)

發(fā)布時間:2020-08-28 00:53:16 來源:腳本之家 閱讀:183 作者:jiedou1991 欄目:開發(fā)技術(shù)

什么是單元測試

單元測試是用來對一個模塊、一個函數(shù)或者一個類來進行正確性檢驗的測試工作。

比如對于函數(shù)abs(),我們可以編寫的測試用例為:

(1)輸入正數(shù),比如1、1.2、0.99,期待返回值與輸入相同

(2)輸入復(fù)數(shù),比如-1、-1.2、-0.99,期待返回值與輸入相反

(3)輸入0,期待返回0

(4)輸入非數(shù)值類型,比如None、[]、{}、期待拋出TypeError

把上面這些測試用例放到一個測試模塊里,就是一個完整的單元測試

 unittest工作原理

unittest中最核心的四部分是:TestCase,TestSuite,TestRunner,TestFixture

(1)一個TestCase的實例就是一個測試用例。測試用例就是指一個完整的測試流程,包括測試前準(zhǔn)備環(huán)境的搭建(setUp),執(zhí)行測試代碼(run),以及測試后環(huán)境的還原(tearDown)。元測試(unit test)的本質(zhì)也就在這里,一個測試用例是一個完整的測試單元,通過運行這個測試單元,可以對某一個問題進行驗證。

(2)而多個測試用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite。

(3)TestLoader是用來加載TestCase到TestSuite中的。

(4)TextTestRunner是來執(zhí)行測試用例的,其中的run(test)會執(zhí)行TestSuite/TestCase中的run(result)方法

(5)測試的結(jié)果會保存到TextTestResult實例中,包括運行了多少測試用例,成功了多少,失敗了多少等信息。

 綜上,整個流程就是首先要寫好TestCase,然后由TestLoader加載TestCase到TestSuite,然后由TextTestRunner來運行TestSuite,運行的結(jié)果保存在TextTestResult中,整個過程集成在unittest.main模塊中。

python unittest簡介

unittest是python下的單元測試框架,是java JUnit的python版本, 跟其它語言下的單元測試框架風(fēng)格類似,unittest支持自動化測試、共享setup和teardown代碼、測試聚合成集、獨立于報告框架。unittest模塊提供了一個豐富的工具集用于構(gòu)建和執(zhí)行用例,先看一個入門的例子:

import unittest

class TestStringMethods(unittest.TestCase):

def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO') 
  def test_isupper(self):
    self.assertTrue('FOO'.isupper())
    self.assertFalse('Foo'.isupper())

  def test_split(self):
    s = 'hello world'
    self.assertEqual(s.split(), ['hello', 'world'])
    # check that s.split fails when the separator is not a string
    with self.assertRaises(TypeError):
      s.split(2)

if __name__ == '__main__':
  unittest.main()

可以通過繼承unittest.TestCase創(chuàng)建一個測試用例TestStringMethods,在這個用例中定義了測試函數(shù),這些函數(shù)名字都以”test”開頭,在執(zhí)行測試用例TestStringMethods時,這些方法會被自動調(diào)用。每個測試函數(shù)中都調(diào)用了assertTrue()和assertFalse()方法檢查預(yù)期結(jié)果,或者使用assertRaises()確認產(chǎn)生了一個特定異?!,F(xiàn)在來看一下這段代碼的運行結(jié)果:

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

OK

有時我們需要在用例執(zhí)行前后做一些工作如初始化和清理,這就需要實現(xiàn)setUp()和tearDown()方法

import unittest

class WidgetTestCase(unittest.TestCase):
  def setUp(self):
    print("setUp()")

  def test_1(self):
    print("test_1")

  def test_2(self):
    print("test_2")

  def tearDown(self):
    print("tearDown()")

if __name__ == '__main__':
  unittest.main()

運行結(jié)果:

setUp()
.test_1
tearDown()
setUp()
.test_2
tearDown()
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

注:如果setUp()執(zhí)行成功(沒有異常發(fā)生),那么無論測試方法是否通過,tearDown()都會被執(zhí)行
根據(jù)所測的特性測試用例被組合在一起,通過調(diào)用unittest.main(),unittest測試框架會自動收集所有模塊的測試用例然后執(zhí)行。

import unittest

class WidgetTestCase(unittest.TestCase):
  def setUp(self):
    print("WidgetTestCase setUp()")

  def test_Widget(self):
    print("test_Widget")

  def tearDown(self):
    print("WidgetTestCase tearDown()")

class FuncTestCase(unittest.TestCase):
  def setUp(self):
    print("FuncTestCase setUp()")

  def test_func(self):
    print("test_func")

  def tearDown(self):
    print("FuncTestCase tearDown()")


if __name__ == '__main__':
  unittest.main()

 運行結(jié)果:

FuncTestCase setUp()                                                 
test_func                                                            
FuncTestCase tearDown()                                              
.WidgetTestCase setUp()                                              
test_Widget                                                          
WidgetTestCase tearDown()                                            
.                                                                    
----------------------------------------------------------------------
Ran 2 tests in 0.003s                                                

OK  

如果想構(gòu)建自已的用例集,只需要這么做:

import unittest

class WidgetTestCase(unittest.TestCase):
  def setUp(self):
    print("WidgetTestCase setUp()")

  def test_Widget(self):
    print("test_Widget")

  def tearDown(self):
    print("WidgetTestCase tearDown()")

class FuncTestCase(unittest.TestCase):
  def setUp(self):
    print("FuncTestCase setUp()")

  def test_func(self):
    print("test_func")

  def tearDown(self):
    print("FuncTestCase tearDown()")

def suite():
  suite = unittest.TestSuite()
  suite.addTest(FuncTestCase('test_func'))
  return suite

if __name__ == '__main__':
  runner=unittest.TextTestRunner()
  runner.run(suite())

運行結(jié)果:

FuncTestCase setUp()
test_func
FuncTestCase tearDown()
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

unittest中相關(guān)類和函數(shù)

在unittest中 TestCase類的實例代表邏輯測試單元,這個類通常被當(dāng)作測試類的基類使用, TestCase類實現(xiàn)了許多測試相關(guān)的接口,主要是以下三組方法:

1.執(zhí)行測試用例的方法

setUp()
#在每個測試方法之前執(zhí)行,這個方法引發(fā)的異常會被認為是錯誤,而非測試失敗,默認實現(xiàn)是不做任何事
tearDown()
#在每個測試方法之后執(zhí)行,即使測試方法拋出異常tearDown()方法仍會執(zhí)行,并且只有setUp()成功執(zhí)行時tearDown()才會執(zhí)行,
#同樣這個方法引發(fā)的異常會被認為是錯誤,而非測試失敗。默認實現(xiàn)是不做任何事
setUpClass()
#在一個測試類的所有測試方法執(zhí)行之前執(zhí)行,相當(dāng)于google test中的SetUpTestCase()方法,setUpClass()必須被裝飾成一個classmethod()
@classmethod
def setUpClass(cls):
  ...
tearDownClass()
#在一個測試類的所有測試方法執(zhí)行之后執(zhí)行,相當(dāng)于google test中的TearDownTestCase()方法,tearDownClass()必須被裝飾成一個classmethod()
@classmethod
def tearDownClass(cls):
  ...

2.檢查條件和報告錯誤的方法

Method Checks that New in
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b 3.1
assertIsNot(a, b) a is not b 3.1
assertIsNone(x) x is None 3.1
assertIsNotNone(x) x is not None 3.1
assertIn(a, b) a in b 3.1
assertNotIn(a, b) a not in b 3.1
assertIsInstance(a, b) isinstance(a, b) 3.2
assertNotIsInstance(a, b) not isinstance(a, b) 3.2
assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) raises exc
assertRaisesRegex(exc, r, fun, *args, **kwds) fun(*args, **kwds) raises exc and the message matches regex r 3.1
assertWarns(warn, fun, *args, **kwds) fun(*args, **kwds) raises warn 3.2
assertNotAlmostEqual(a, b) round(a-b, 7) != 0
assertGreater(a, b) a > b 3.1
assertGreaterEqual(a, b) a >= b 3.1
assertLess(a, b) a < b 3.1
assertLessEqual(a, b) a <= b 3.1
assertRegex(s, r) r.search(s) 3.1
assertNotRegex(s, r) not r.search(s) 3.2
assertCountEqual(a, b) a and b have the same elements in the same number, regardless of their order 3.2
assertWarnsRegex(warn, r, fun, *args, **kwds) fun(*args, **kwds) raises warn and the message matches regex r 3.2
assertLogs(logger, level) The with block logs on logger with minimum level 3.4
assertMultiLineEqual(a, b) strings 3.1
assertSequenceEqual(a, b) sequences 3.1
assertListEqual(a, b) lists 3.1
assertTupleEqual(a, b) tuples 3.1
assertSetEqual(a, b) sets or frozensets 3.1
assertDictEqual(a, b) dicts 3.1

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI