Unittest框架

Unittest框架詳解

  • Test Fixture,就是Setup()和TearDown() Test Case()
  • Test Case,一個Test Case就是一個測試用例,他們都是unittest.TestCase類的子類的方法
  • Test Suite,Test Suite是一個測試用例集合,基本上你用不到它,用unittest.main()或者其它發現機制來運行全部的測試用例就對了。 :)
  • Test runner,這是單元測試結果的呈現接口,你能夠定製本身喜歡的呈現方式,好比GUI界面,基本上你也用不到它。 

unittest單元測試框架不只能夠適用於單元測試,還能夠適用WEB自動化測試用例的開發與執行,該測試框架可組織執行測試用例,而且提供了豐富的斷言方法,判斷測試用例是否經過,最終生成測試結果。今天就總結下如何使用unittest單元測試框架來進行接口自動化測試。html

 

目錄:

1、unittest模塊的各個屬性說明

  先來聊一聊unittest模塊的各個屬性,所謂知己知彼方能百戰百勝,瞭解unittest的各個屬性,對於後續編寫用例有很大的幫助。web

1.unittest的屬性以下

['BaseTestSuite', 'FunctionTestCase', 'SkipTest', ' TestCase', 'TestLoader', 'TestProgram', 'TestResult', ' TestSuite', 'TextTestResult', ' TextTestRunner', '_TextTestResult', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__unittest', 'case', ' defaultTestLoader', 'expectedFailure', 'findTestCases', 'getTestCaseNames', 'installHandler', 'loader', ' main', 'makeSuite', 'registerResult', 'removeHandler', 'removeResult', 'result', 'runner', 'signals', ' skip', ' skipIf', ' skipUnless', 'suite', 'util']
 
說明:
unittest.TestCase:TestCase類,全部測試用例類繼承的基本類。
class BaiduTest(unittest.TestCase):

unittest.main():使用她能夠方便的將一個單元測試模塊變爲可直接運行的測試腳本,main()方法使用TestLoader類來搜索全部包含在該模塊中以「test」命名開頭的測試方法,並自動執行他們。執行方法的默認順序是:根據ASCII碼的順序加載測試用例,數字與字母的順序爲:0-9,A-Z,a-z。因此以A開頭的測試用例方法會優先執行,以a開頭會後執行。
 
unittest.TestSuite():unittest框架的TestSuite()類是用來建立測試套件的。
 
unittest.TextTextRunner():unittest框架的TextTextRunner()類,經過該類下面的run()方法來運行suite所組裝的測試用例,入參爲suite測試套件。
 
unittest.defaultTestLoader(): defaultTestLoader()類,經過該類下面的discover()方法可自動更具測試目錄start_dir匹配查找測試用例文件(test*.py),並將查找到的測試用例組裝到測試套件,所以能夠直接經過run()方法執行discover。用法以下:
 
discover=unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')

 
unittest.skip():裝飾器,當運行用例時,有些用例可能不想執行等,可用裝飾器暫時屏蔽該條測試用例。一種常見的用法就是好比說想調試某一個測試用例,想先屏蔽其餘用例就能夠用裝飾器屏蔽。
 
@unittest.skip(reason): skip(reason)裝飾器:無條件跳過裝飾的測試,並說明跳過測試的緣由。
 
@unittest.skipIf(reason): skipIf(condition,reason)裝飾器:條件爲真時,跳過裝飾的測試,並說明跳過測試的緣由。
 
@unittest.skipUnless(reason): skipUnless(condition,reason)裝飾器:條件爲假時,跳過裝飾的測試,並說明跳過測試的緣由。
 
@unittest.expectedFailure(): expectedFailure()測試標記爲失敗。
 

2.TestCase類的屬性以下:

['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_addSkip', '_baseAssertEqual', '_classSetupFailed', '_deprecate', '_diffThreshold', '_formatMessage', '_getAssertEqualityFunc', '_truncateMessage', 'addCleanup', 'addTypeEqualityFunc', 'assertAlmostEqual', 'assertAlmostEquals', 'assertDictContainsSubset', 'assertDictEqual', ' assertEqual', 'assertEquals', ' assertFalse', 'assertGreater', 'assertGreaterEqual', ' assertIn', ' assertIs', ' assertIsInstance', ' assertIsNone', ' assertIsNot', ' assertIsNotNone', 'assertItemsEqual', 'assertLess', 'assertLessEqual', 'assertListEqual', 'assertMultiLineEqual', 'assertNotAlmostEqual', 'assertNotAlmostEquals', ' assertNotEqual', 'assertNotEquals', ' assertNotIn', ' assertNotIsInstance', 'assertNotRegexpMatches', 'assertRaises', 'assertRaisesRegexp', 'assertRegexpMatches', 'assertSequenceEqual', 'assertSetEqual', ' assertTrue', 'assertTupleEqual', 'assert_', 'countTestCases', 'debug', 'defaultTestResult', 'doCleanups', 'fail', 'failIf', 'failIfAlmostEqual', 'failIfEqual', 'failUnless', 'failUnlessAlmostEqual', 'failUnlessEqual', 'failUnlessRaises', 'failureException', 'id', 'longMessage', 'maxDiff', 'run', ' setUp', ' setUpClass', 'shortDescription', 'skipTest', ' tearDown', ' tearDownClass']
 
說明:
 
setUp():setUp()方法用於測試用例執行前的初始化工做。如測試用例中須要訪問數據庫,能夠在setUp中創建數據庫鏈接並進行初始化。如測試用例須要登陸web,能夠先實例化瀏覽器。
 
tearDown():tearDown()方法用於測試用例執行以後的善後工做。如關閉數據庫鏈接。關閉瀏覽器。
 
assert*():一些斷言方法:在執行測試用例的過程當中,最終用例是否執行經過,是經過判斷測試獲得的實際結果和預期結果是否相等決定的。
 
assertEqual(a,b,[msg='測試失敗時打印的信息']):斷言a和b是否相等,相等則測試用例經過。
 
assertNotEqual(a,b,[msg='測試失敗時打印的信息']):斷言a和b是否相等,不相等則測試用例經過。
 
assertTrue(x,[msg='測試失敗時打印的信息']):斷言x是否True,是True則測試用例經過。
 
assertFalse(x,[msg='測試失敗時打印的信息']):斷言x是否False,是False則測試用例經過。
 
assertIs(a,b,[msg='測試失敗時打印的信息']):斷言a是不是b,是則測試用例經過。
 
assertNotIs(a,b,[msg='測試失敗時打印的信息']):斷言a是不是b,不是則測試用例經過。
 
assertIsNone(x,[msg='測試失敗時打印的信息']):斷言x是否None,是None則測試用例經過。
 
assertIsNotNone(x,[msg='測試失敗時打印的信息']):斷言x是否None,不是None則測試用例經過。
 
assertIn(a,b,[msg='測試失敗時打印的信息']):斷言a是否在b中,在b中則測試用例經過。
 
assertNotIn(a,b,[msg='測試失敗時打印的信息']):斷言a是否在b中,不在b中則測試用例經過。
 
assertIsInstance(a,b,[msg='測試失敗時打印的信息']):斷言a是是b的一個實例,是則測試用例經過。
 
assertNotIsInstance(a,b,[msg='測試失敗時打印的信息']):斷言a是是b的一個實例,不是則測試用例經過。
 

3.TestSuite類的屬性以下:(組織用例時須要用到)

['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_addClassOrModuleLevelException', '_get_previous_module', '_handleClassSetUp', '_handleModuleFixture', '_handleModuleTearDown', '_tearDownPreviousClass', '_tests', ' addTest', 'addTests', 'countTestCases', 'debug', 'run']
說明:
addTest(): addTest()方法是將測試用例添加到測試套件中,以下方,是將test_baidu模塊下的BaiduTest類下的test_baidu測試用例添加到測試套件。
suite = unittest.TestSuite()
suite.addTest(test_baidu.BaiduTest('test_baidu'))

 

4.TextTextRunner的屬性以下:(組織用例時須要用到)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_makeResult', 'buffer', 'descriptions', 'failfast', 'resultclass', 'run', 'stream', 'verbosity']
說明:
run(): run()方法是運行測試套件的測試用例,入參爲suite測試套件。
runner = unittest.TextTestRunner()
runner.run(suite)

 

2、使用unittest框架編寫測試用例思路

設計基本思路以下:
 
 1 import unittest
 2 
 3 class Test(unittest.TestCase):
 4     def setUp(self):
 5         print('set up !!')
 6 
 7     def test_case1(self):
 8         print('case_1.....')
 9 
10     def test_case2(self):
11         print('case_2.....')
12 
13     def tearDown(self):
14         print('teardonw!!!')
15 
16 if __name__ == '__main__':
17     unittest.main() #main  運行
18 
19     # suite = unittest.TestSuite()
20     # suite.addTest(Test('test_case2'))
21     # suite.addTest(Test('test_case1'))
22     # runner = unittest.TextTestRunner()
23     # runner.run(suite) #使用TestSuite添加測試套件,使用TextTestRunner.run 執行測試套件
24 
25     # test_dir = './'
26     # discover = unittest.defaultTestLoader.discover(test_dir,pattern='unittest_*.py')
27     # runner = unittest.TextTestRunner()
28     # runner.run(discover)

來個小練習:

 1 # -*- coding:utf-8 -*-
 2 # 1.先設置編碼,utf-8可支持中英文,如上,通常放在第一行
 3 
 4 # 2.註釋:包括記錄建立時間,建立人,項目名稱。
 5 '''
 6 Created on 2018-7-30
 7 @author: Baylor
 8 Project:使用unittest框架編寫測試用例思路
 9 '''
10 # 3.導入unittest模塊
11 
12 import unittest
13 # 4.定義測試類,父類爲unittest.TestCase。
14 # 可繼承unittest.TestCase的方法,如setUp和tearDown方法,不過此方法能夠在子類重寫,覆蓋父類方法。
15 # 可繼承unittest.TestCase的各類斷言方法。
16 class Test(unittest.TestCase):
17     # 5.定義setUp()方法用於測試用例執行前的初始化工做。
18     # 注意,全部類中方法的入參爲self,定義方法的變量也要「self.變量」
19     # 注意,輸入的值爲字符型的須要轉爲int型
20     def setUp(self):
21         self.number = input('Enter a number:')
22         self.number = int(self.number)
23 
24     # 6.定義測試用例,以「test_」開頭命名的方法
25     # 注意,方法的入參爲self
26     # 可以使用unittest.TestCase類下面的各類斷言方法用於對測試結果的判斷
27     # 可定義多個測試用例
28     # 最重要的就是該部分
29     def test_case1(self):
30         print(self.number)
31         self.assertEqual(self.number, 10, msg='Your input is not 10')
32 
33     def test_case2(self):
34         print(self.number)
35         self.assertEqual(self.number, 20, msg='Your input is not 20')
36 
37     @unittest.skip('暫時跳過用例3的測試')
38     def test_case3(self):
39         print(self.number)
40         self.assertEqual(self.number, 30, msg='Your input is not 30')
41 
42     # 7.定義tearDown()方法用於測試用例執行以後的善後工做。
43     # 注意,方法的入參爲self
44     def tearDown(self):
45         print('Test over')
46 
47 
48 # 8若是直接運行該文件(__name__值爲__main__),則執行如下語句,經常使用於測試腳本是否可以正常運行
49 if __name__ == '__main__':  # 快捷輸入 main   tab補齊
50     # 8.1執行測試用例方案一以下:
51     # unittest.main()方法會搜索該模塊下全部以test開頭的測試用例方法,並自動執行它們。
52     # 執行順序是命名順序:先執行test_case1,再執行test_case2
53     unittest.main()
54 
55 
56 '''
57 #8.2執行測試用例方案二以下:
58 #8.2.1先構造測試集
59 #8.2.1.1實例化測試套件
60     suite=unittest.TestSuite()
61 #8.2.1.2將測試用例加載到測試套件中。
62 #執行順序是安裝加載順序:先執行test_case2,再執行test_case1
63     suite.addTest(Test('test_case2'))
64     suite.addTest(Test('test_case1'))
65 #8.2.2執行測試用例
66 #8.2.2.1實例化TextTestRunner類
67     runner=unittest.TextTestRunner()
68 #8.2.2.2使用run()方法運行測試套件(即運行測試套件中的全部用例)
69     runner.run(suite)
70 '''
71 
72 '''
73 #8.3執行測試用例方案三以下:
74 #8.3.1構造測試集(簡化了方案二中先要建立測試套件而後再依次加載測試用例)
75 #執行順序同方案一:執行順序是命名順序:先執行test_case1,再執行test_case2
76     test_dir = './'
77     discover = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')
78 #8.3.2執行測試用例
79 #8.3.2.1實例化TextTestRunner類
80     runner=unittest.TextTestRunner()
81 #8.3.2.2使用run()方法運行測試套件(即運行測試套件中的全部用例)
82     runner.run(discover)   
83 '''
84 
85 print(1111)

 

使用方案一執行測試用例結果以下:

Enter a number:10
10
Test over
Enter a number: .10
Fs
Ran 3 tests in 6.092s
FAILED (failures=1, skipped=1)
10
Test over
由於先執行test_case1,再執行test_case2,因此第一次輸入10時,執行經過,返回. 第二次輸入10時,執行不經過,返回F,最終一個用例經過,一個用例失敗,還有一個用例是直接跳過的(裝飾器)。
 使用方案二執行測試用例結果以下:
Enter a number:10
10
Test over
Enter a number: F10
.
Ran 2 tests in 4.973s
FAILED (failures=1) 
10
Test over
由於先執行test_case2,再執行test_case1,因此第一次輸入10時,執行不經過,返回F , 第二次輸入10時,執行經過,返回. ,最終一個用例經過,一個用例失敗。
使用方案三執行測試用例結果以下(執行測試用例順序同方案一):
Enter a number:10
10
Test over
Enter a number: .10
Fs
Ran 3 tests in 6.092s
FAILED (failures=1, skipped=1)
10
Test over
由於先執行test_case1,再執行test_case2,因此第一次輸入10時,執行經過,返回. 第二次輸入10時,執行不經過,返回F,最終一個用例經過,一個用例失敗,還有一個用例是直接跳過的(裝飾器)。
 

3、使用unittest框架編寫測試用例實例

目錄結構:數據庫

百度電影接口用例 Test Case:瀏覽器

 1 # -*- coding:utf-8 -*-
 2 __author__ = 'chenjianguo'
 3 '''
 4 Created on 2016-7-22
 5 @author: Baylor
 6 Project:百度電影接口測試
 7 '''
 8 
 9 import unittest, requests
10 
11 class BaiduTest(unittest.TestCase):
12     def setUp(self):
13         self.base_url = "http://v.baidu.com/person_intro/?dtype=saleworks&pn=1&ps=12&wt=movie&id=76"
14 
15     def test_baidu(self):
16         self.title = requests.get(self.base_url)  # 變量self. 是爲了讓tearDown使用
17         # print(title.status_code)
18         self.assertEqual(self.title.status_code, 200, msg="接口未經過")
19 
20     def tearDown(self):
21         a = self.title.content.decode('utf8')
22         # print(eval(a))
23         print(eval(a)['movie']['typename'])
24         print('執行完畢。。。。')
25 
26 if __name__ == "__main__":
27     unittest.main()

 

豆瓣接口測試用例 Test Case:框架

 1 # -*- coding:utf-8 -*-
 2 __author__ = 'chenjianguo'
 3 '''
 4 Created on 2016-7-22
 5 @author: Baylor
 6 Project:豆瓣接口測試
 7 '''
 8 
 9 import unittest,requests
10 
11 class DoubanTest(unittest.TestCase):
12     @classmethod # 必須加這個  類方法
13     def setUpClass(cls):
14         print('我在什麼時候運行--setupclass') #全部用例執行以前運行它
15 
16     @classmethod
17     def tearDownClass(cls):
18         print('我在什麼時候運行--teardownclass')#全部用例執行完以後運行它
19 
20     def setUp(self):
21         self.base_url = "https://movie.douban.com/j/search_tags?type=movie&source=index"
22 
23     def test_douban(self):
24         self.title = requests.get(self.base_url) #變量self. 是爲了讓tearDown使用
25         # print(title.status_code)
26         # self.assertEqual(self.title.status_code,200, msg="接口未經過")
27         self.assertIs(self.title.status_code,200, msg="接口未經過")
28 
29     def tearDown(self):
30         print(self.title.content.decode('utf8'))
31         print('執行完畢。。。。')
32 
33 if __name__ == "__main__":
34     unittest.main()

 

web測試用例:經過測試套件TestSuite來組裝多個測試用例。

 1 # -*- coding:utf-8 -*-
 2 
 3 '''
 4 explain: 編寫接口測試用例
 5 '''
 6 
 7 import unittest
 8 from test_project.test_case import test_baidu
 9 from test_project.test_case import test_douban
10 
11 suite = unittest.TestSuite()
12 suite.addTest(test_baidu.BaiduTest('test_baidu'))
13 suite.addTest(test_douban.DoubanTest('test_douban'))
14 
15 if __name__ == '__main__':
16     # runner = unittest.TextTestRunner()
17     # runner.run(suite)
18 
19     # https://pan.baidu.com/s/1dcwD42ym6Hd5Di7Gy9_hxw #課件下載
20     import HTMLTestRunner
21     # f = open('report.html','wb')
22     # runner = HTMLTestRunner.HTMLTestRunner(stream=f,title='xxx報告',description='測試狀況')
23     # runner.run(xxx)
24 
25     # import xmlrunner
26     # report = xmlrunner.XMLTestRunner(output='TestLog')
27     # report.run(suite)
28 
29     import BeautifulReport
30     report = BeautifulReport.BeautifulReport(suite)
31     report.report(description='xxx測試', filename='report2.html',log_path='TestLog')
32     print(report.failure_count)  # 失敗的次數
33     print(report.success_count)  # 成功的次數

 

測試結果:less

說明:.表明用例執行經過,兩個點表示兩個用例執行經過。F表示用例執行不經過。

 資料補充

 1 class demoSkipTest(unittest.TestCase):
 2     a = 50
 3     b = 20
 4 
 5     def test_add(self):
 6         """加法"""
 7         result = self.a + self.b
 8         self.assertEqual(result, 40)
 9 
10     @unittest.skipIf(a > b, u"a>b就跳過")
11     def test_sub(self):
12         """減法"""
13         result = self.a - self.b
14         self.assertTrue(result == -30)
15 
16     @unittest.skipUnless(b == 0, u"除數爲0,則跳轉")
17     def test_div(self):
18         """除法"""
19         result = self.a / self.b
20         self.assertTrue(result == 1)
21 
22     @unittest.expectedFailure
23     def test_mul(self):
24         """乘法"""
25         result = self.a * self.b
26         self.assertTrue(result == 0)
27 
28 
29 if __name__ == "__main__":
30     unittest.main()
相關文章
相關標籤/搜索