1、注意環境:html
python2.7python
unittest2 [定製修改] 參見本人博客 python unittest 深刻failfast及實際應用【示例】windows
windows10app
2、代碼自說話:python2.7
# coding:utf-8 ''' Created on 2015年9月10日 @author: laughlast ''' import os import sys import copy import unittest2 import HTMLTestRunner def is_prime(number): '''return true if *number* is prime. ''' if number <= 1: return False for element in range(2, number): if number % element == 0: return False return True def get_next_prime(number): '''get the closest prime larger then *number*. ''' index = number while True: index = index + 1 if is_prime(index): return index return None class PrimesTestsBase(unittest2.TestCase): u'''測試一個整數是否爲素數以及求一個整數後面的下一個素數(全ok) ''' _NopeMsg = '{} should be not a prime!' _OkMsg = '{} should be a prime!' @classmethod def setUpClass(cls): '''demo setUpClass: begin ''' print 'begin' @classmethod def tearDownClass(cls): '''demo tearDownClass() ''' print 'end' def test_is_1_prime(self): '''1 should not be prime! ''' self.assertFalse(is_prime(1), self._NopeMsg.format(1)) def test_is_2_prime(self): '''2 should be prime! ''' self.assertTrue(is_prime(2), self._OkMsg.format(2)) def test_is_3_prime(self): '''3 should not be prime! ''' self.assertTrue(is_prime(3), self._OkMsg.format(3)) def test_is_4_prime(self): '''4 should not be prime! ''' self.assertFalse(is_prime(4), self._NopeMsg.format(4)) def test_is_5_prime(self): '''5 should be prime! ''' self.assertTrue(is_prime(5), self._OkMsg.format(5)) def test_is_negtive_prime(self): '''negtive should be not prime ''' for k in range(-1, -10, -1): self.assertFalse(is_prime(k), self._NopeMsg.format(k)) class PrimesTestsWithRunTestOverrided(PrimesTestsBase): u'''複寫TestCase的"runTest" 方法 ''' def runTest(self): '''pass''' assert True class PrimesTestsWithRunOverrided(PrimesTestsBase): u'''複寫TestCase的"run"方法 ''' def run(self, result=None): '''overriding the "run" to set result.failfast etc''' if result is None: result = unittest2.TestResult(verbosity=2) result.failfast = True super(PrimesTestsBase, self).run(result) def test_is_4_prime(self): '''4 should not be prime!''' self.fail(self._NopeMsg.format(4)) class PrimesTestsWith4thFailedAsExpected(PrimesTestsBase): u'''複寫第4個測試方法使其失敗並以 "expectedFailure" 裝飾包裝 ''' # take the test failed as 'expected failures' instead of 'failed' @unittest2.expectedFailure def test_is_4_prime(self): '''4 should not be prime!''' self.fail(self._NopeMsg.format(4)) class PrimesTestsWith4thFailed(PrimesTestsBase): u'''複寫第4個測試方法使其失敗 ''' def test_is_4_prime(self): '''4 should not be prime!''' self.fail(self._NopeMsg.format(4)) class RunUnittestDemo(unittest2.TestCase): u'''測試 unittest 不一樣的運行測試方法 ''' def setUp(self): self.tloader = unittest2.defaultTestLoader self.trunner = unittest2.TextTestRunner(verbosity=2, failfast=True) def test_run_With4thFailed(self): u'''運行包含一個失敗的測試方法 ''' tsuite = self.tloader.loadTestsFromTestCase(PrimesTestsWith4thFailed) tresult = self.trunner.run(tsuite) # unittest2.TestCase的longMessage缺省爲True,在trace信息後添加用戶信息 assert self.longMessage assert tresult.failures[0][1].index(PrimesTestsBase._NopeMsg.format(4)) assert not tresult.wasSuccessful() if self.trunner.failfast: assert tresult.testsRun is 4 else: assert tresult.testsRun is tsuite.countTestCases() def test_run_With4thFailedAsExpected(self): u'''運行包含一個失敗的並以指望失敗包裝裝飾的測試方法 ''' tsuite = self.tloader.loadTestsFromTestCase(PrimesTestsWith4thFailedAsExpected) self.trunner.failfast = True tresult = self.trunner.run(tsuite) assert tresult.wasSuccessful() assert tresult.testsRun is tsuite.countTestCases() def test_run_WithRunTestOverrided(self): u'''運行包含一個runTest實現的測試方法 ''' # 測試案例TestCaseClass無參數實例化缺省執行其 runTest 方法 tresult = PrimesTestsWithRunTestOverrided().run() assert tresult.testsRun is 1 and tresult.wasSuccessful() # TestLoader缺省加載 test 開頭的測試方法(不包括 runTest) tsuite = self.tloader.loadTestsFromTestCase(PrimesTestsWithRunTestOverrided) tresult = self.trunner.run(tsuite) assert tresult.testsRun is tsuite.countTestCases() \ and tsuite.countTestCases() is 6 def test_run_WithRunOverrided(self): u'''複寫TestCase類中的run(result),經過設置result參數控制執行流程等 ''' tsuite = self.tloader.loadTestsFromTestCase(PrimesTestsWithRunOverrided) tresult = self.trunner.run(tsuite) assert not tresult.wasSuccessful() # 對應run()中result.failfast爲True,跳過執行失敗案例後面的兩個案例執行 assert tresult.testsRun is tsuite.countTestCases() - 2 def test_run_verify_testsuite_runned(self): u'''檢查測試執行後的 TestSuite 實例自己變化 ''' tresult = unittest2.TestResult() tsuite = unittest2.TestSuite([PrimesTestsBase('test_is_1_prime')]) tsuitedcp = copy.deepcopy(tsuite) tsuitescp = copy.copy(tsuite) tsuite.run(tresult) assert tresult.wasSuccessful() \ and tresult.testsRun is 1 # 測試案例執行後,所在測試集中再也不保留其實例引用(被設爲None) assert tsuite._tests == [None] \ and tsuite.countTestCases() is 1\ and tsuite._removed_tests is 1 # copy引用的非深度copy有問題 assert tsuite == tsuitescp and tsuite is not tsuitescp tsuite.addTest(PrimesTestsBase('test_is_2_prime')) # TestSuite 以addTest添加測試案例時是在持有的測試序列後append with self.assertRaises(TypeError): # 新測試案例追加到測試序列列表中原來執行過的案例後 assert tsuite._tests[0] is None \ and isinstance(tsuite._tests[1], PrimesTestsBase) # 沿用的tsuite中原已執行案例的引用被替換爲None,固然 TypeError tsuite(tresult) # deepcopy沒有問題 assert tsuitedcp.run(tresult).wasSuccessful() def test_run_verify_testloader(self): u'''驗證TestLoader加載測試案例的其它方法 ''' import test_unittest_demo fullname_tm = 'test_unittest_demo.PrimesTestsBase.test_is_1_prime' relativename_tm = 'PrimesTestsBase.test_is_1_prime' tsuite1 = self.tloader.loadTestsFromName(fullname_tm) tsuite2 = self.tloader.loadTestsFromName(relativename_tm, test_unittest_demo) tsuite3 = self.tloader.loadTestsFromNames([fullname_tm]) tsuite4 = self.tloader.loadTestsFromNames([relativename_tm], test_unittest_demo) assert tsuite1.countTestCases() == tsuite2.countTestCases()\ == tsuite3.countTestCases() == tsuite4.countTestCases() == 1 fullname_tc = 'test_unittest_demo.PrimesTestsBase' relativename_tc = 'PrimesTestsBase' tsuite1 = self.tloader.loadTestsFromName(fullname_tc) tsuite2 = self.tloader.loadTestsFromName(relativename_tc, test_unittest_demo) assert tsuite1.countTestCases() == tsuite2.countTestCases() == 6 tpath = os.path.split(os.path.realpath(__file__))[0] # 最簡單 tsuite1 = self.tloader.loadTestsFromName('test_unittest_demo') # 經常使用也實用 tsuite2 = self.tloader.discover(tpath, 'test*unittest*.py') # 最快(不用額外導入解析) tsuite3 = self.tloader.loadTestsFromModule(test_unittest_demo, False) assert tsuite1.countTestCases() == tsuite2.countTestCases()\ == tsuite3.countTestCases() def test_run_single_testmethod(self): u'''運行本例中其它地方沒有出現的單個測試方法案例 ''' # tresult可爲如下測試執行方法共享,注意測試結果 tresult = unittest2.TestResult() assert PrimesTestsBase('test_is_1_prime').run(tresult).wasSuccessful()\ and tresult.wasSuccessful() and tresult.testsRun is 1 # 測試案例TestCaseClass無參數實例化缺省執行其 runTest 方法 assert PrimesTestsWithRunTestOverrided().run(tresult).wasSuccessful()\ and tresult.wasSuccessful() and tresult.testsRun is 2 tsuite = unittest2.TestSuite() tsuite.addTest(PrimesTestsBase('test_is_1_prime')) # 避免直接在連續獨立測試中使用上一執行過的 TestSuite 實例,參見例中另外demo方法 tsuitecopy = copy.deepcopy(tsuite) tsuite.run(tresult) assert tresult.wasSuccessful() and tresult.testsRun is 3 # TestSuite自調用是實現 '__call__'來內部引用run(*a,**k) tsuitecopy(tresult) assert tresult.wasSuccessful() and tresult.testsRun is 4 if __name__ == '__main__': tloader = unittest2.defaultTestLoader tpath = os.path.split(os.path.realpath(__file__))[0] tsuite = tloader.discover(tpath, 'test*unittest*.py') # trunner = unittest2.TextTestRunner(verbosity=2, failfast=True) # tresult = trunner.run(tsuite) # assert not tresult.wasSuccessful() # print tresult treport = file(tpath + '\\test_primes.html', 'wb') htrunner = HTMLTestRunner.HTMLTestRunner(stream=treport, verbosity=2, title='test primes and unittest', description='test primes and unittest demos report') htresult = htrunner.run(tsuite) treport.close() print htresult
3、測試結果
ide