Python 基礎入門前六篇:php
這是第七篇,也是這個基礎入門系列的最後一篇內容,簡單介紹如何採用 unittest
模型編寫測試用例。java
首先是給出用於測試的代碼,以下所示,這是一個接收姓和名而後返回整潔的姓名的函數:python
def get_formatted_name(first, last):
full_name = first + ' ' + last
return full_name.title()
複製代碼
簡單的測試代碼:c++
first = 'kobe'
last = 'bryant'
print(get_formatted_name(first, last)) # 輸出 Kobe Bryant
複製代碼
在 Python 標準庫中的模塊 unittest
提供了代碼測試工具。這裏介紹幾個名詞的含義:git
一般,最初只須要對函數的重要行爲編寫測試便可,等項目被普遍使用時才考慮全覆蓋。github
接下來就開始介紹如何採用 unittest
對代碼進行測試。正則表達式
首先是須要導入 unittest
模塊,而後建立一個繼承 unittest.TestCase
的類,並編寫一系列類方法對函數的不一樣行爲進行測試,以下代碼所示:算法
import unittest
class NamesTestCase(unittest.TestCase):
''' 測試生成名字函數的類 '''
def test_first_last_name(self):
formatted_name = get_formatted_name('kobe', 'bryant')
self.assertEqual(formatted_name, 'Kobe Bryant')
unittest.main()
複製代碼
輸出結果以下,顯示運行的測試樣例是 1 個,耗時是 0.001s。編程
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
複製代碼
上述是給了一個能夠經過的例子,而若是測試不經過,輸出是怎樣的呢,以下所示:bash
# 添加中間名
def get_formatted_name(first, middel, last):
full_name = first + ' ' + middle + ' ' + last
return full_name.title()
class NamesTestCase(unittest.TestCase):
''' 測試生成名字函數的類 '''
# 不能經過的例子
def test_first_name(self):
formatted_name = get_formatted_name('kobe', 'bryant')
self.assertEqual(formatted_name, 'Kobe Bryant')
unittest.main()
複製代碼
輸出結果以下,這裏會打印錯誤發生的地方和錯誤緣由:
E
======================================================================
ERROR: test_first_last_middle_name (__main__.NamesTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "E:/Python_Notes/Practise/unittest_practise.py", line 39, in test_first_last_middle_name
formatted_name = get_formatted_name('kobe', 'bryant')
TypeError: get_formatted_name() missing 1 required positional argument: 'middle'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
複製代碼
很明顯是由於缺乏 middle
參數,若是但願經過測試,能夠將原函數進行以下修改:
def get_formatted_name(first, last, middle=''):
''' 接收姓和名而後返回完整的姓名 :param first: :param last: :return: '''
if middle:
full_name = first + ' ' + middle + ' ' + last
else:
full_name = first + ' ' + last
return full_name.title()
複製代碼
而後添加新的測試方法,繼續運行,就能夠測試經過。
def test_first_last_middle_name(self):
formatted_name = get_formatted_name('kobe', 'bryant', 'snake')
self.assertEqual(formatted_name, 'Kobe Snake Bryant')
複製代碼
上一小節介紹了給函數寫測試的代碼,接下來介紹如何編寫針對類的測試。
在 unitest.TestCase
類中提供了不少斷言方法,上一小節就採用了 assertEqual
這一個判斷給定兩個參數是否相等的斷言方法,下面給出經常使用的 6 個斷言方法:
方法 | 用途 |
---|---|
assertEqual(a, b) | 覈實 a == b |
assertNotEqual(a, b) | 覈實 a != b |
assertTrue(x) | 覈實 x 是 True |
assertFalse(x) | 覈實 x 是 False |
assertIn(item, list) | 覈實 item 在 list 中 |
assertNotIn(item, list) | 覈實 item 不在 list 中 |
這些方法都只能在繼承了 unittest.TestCase
的類中使用這些方法。
首先,編寫用於進行測試的類,代碼以下所示,這是一個用於管理匿名調查問卷答案的類:
class AnonymousSurvey():
''' 收集匿名調查問卷的答案 '''
def __init__(self, question):
''' :param question: '''
self.question = question
self.responses = []
def show_question(self):
''' 顯示問卷 :return: '''
print(self.question)
def store_response(self, new_response):
''' 存儲單份調查問卷 :param new_response: :return: '''
self.responses.append(new_response)
def show_results(self):
''' 顯示全部答卷 :return: '''
print('Survey results:')
for response in self.responses:
print('- ' + response)
複製代碼
這個類包含三個方法,分別是顯示問題、存儲單份問卷以及展現全部調查問卷,下面是一個使用例子:
def use_anonymous_survey():
question = "世上最好的語言是?"
language_survey = AnonymousSurvey(question)
# 顯示問題
language_survey.show_question()
# 添加問卷
language_survey.store_response('php')
language_survey.store_response('python')
language_survey.store_response('c++')
language_survey.store_response('java')
language_survey.store_response('go')
# 展現全部問卷
language_survey.show_results()
if __name__ == '__main__':
use_anonymous_survey()
複製代碼
輸出結果以下:
世上最好的語言是?
Survey results:
- php
- python
- c++
- java
- go
複製代碼
而後就開始編寫對該類的測試代碼,一樣建立一個類,繼承 unittest.TestCase
,而後類方法進行測試,代碼以下所示:
import unittest
class TestAnonmyousSurvey(unittest.TestCase):
def test_store_single_response(self):
''' 測試保存單份問卷的方法 :return: '''
question = "世上最好的語言是?"
language_survey = AnonymousSurvey(question)
language_survey.store_response('php')
self.assertIn('php', language_survey.responses)
unittest.main()
複製代碼
上述代碼採用了 assertIn
斷言方法來測試函數 store_response()
。
這裏還能夠繼續測試可否存儲更多的問卷,以下所示,測試存儲三份問卷:
def test_store_three_response(self):
question = "世上最好的語言是?"
language_survey = AnonymousSurvey(question)
responses = ['c++', 'php', 'python']
for response in responses:
language_survey.store_response(response)
for response in responses:
self.assertIn(response, language_survey.responses)
複製代碼
最後,在 unittest.TestCase
中其實包含一個方法 setUp()
,它的做用相似類的初始化方法 __init()__
,它會在各類以 test_
開頭的方法運行前先運行,因此能夠在這個方法裏建立對象,避免在每一個測試方法都須要建立一遍,因此上述代碼能夠修改成:
class TestAnonmyousSurvey(unittest.TestCase):
def setUp(self):
''' 建立一個調查對象和一組答案 :return: '''
question = "世上最好的語言是?"
self.language_survey = AnonymousSurvey(question)
self.responses = ['c++', 'php', 'python']
def test_store_single_response(self):
''' 測試保存單份問卷的方法 :return: '''
self.language_survey.store_response(self.responses[1])
self.assertIn('php', self.language_survey.responses)
def test_store_three_response(self):
for response in self.responses:
self.language_survey.store_response(response)
for response in self.responses:
self.assertIn(response, self.language_survey.responses)
複製代碼
運行後,輸出結果以下:
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
複製代碼
注意,這裏運行成功,打印一個句號,由於是運行兩個測試方法成功,因此打印了兩個句號;若是運行出錯,打印一個 E
;測試致使斷言失敗,打印一個 F
。
參考
Python 的基礎入門系列就介紹到這裏,最初第一篇初步制定的計劃是以下所示:
恰好基本都介紹上述 10 個方面的知識,後續還會有進階的知識點,包括函數和類的高級知識點,正則表達式,網絡編程方面的如進程和線程知識,固然還會總結或者翻譯一些不錯的介紹 Python 技巧的文章,以及一些經常使用庫的使用方法,好比 numpy、pandas、matplotlib 等等。
固然,還有就是努力作一些有趣的項目。
本文的代碼例子也都上傳到個人 Github 上:
歡迎關注個人微信公衆號--算法猿的成長,或者掃描下方的二維碼,你們一塊兒交流,學習和進步!