測試程式碼
學習如何使用Pyhon模組unittest中的工具來測試程式碼
作者:雷蕾
(一)測試函式
學習測試,我們先建立要測試的程式碼(檔名為name_function.py):
def get_formatted_name(first,last):
'''生成整潔的姓名'''
full_name=f"{first} {last}"
return full_name.title()
示例中函式get_formatted_name()將名和姓合併成姓名 full_name:在名和姓之間加上一個空格並將其首字母大寫,然後返回結果。
為了核實函式get_formatted_name()像我們期望的那樣工作,我們來編寫一個使用該函式的程式(檔名為names.py):
from name_function import get_formatted_name
print("enter 'q' at any time to quit")
while True:
first=input("\nplease give me a first name:")
if first=='q':
break
last=input("please gvie me a last name:")
if last=='q':
break
formatted_name=get_formatted_name(first,last)
print(f"\tNeatl formatted name: {formatted_name}.")
程式碼行from name_function import get_formatted_name是這個程式從name_function.py中匯入get_formatted_name()。
該示例讓使用者輸入名和姓,並將整潔的姓名按格式列印出。
執行結果:
enter 'q' at any time to quit
please give me a first name:lee
please gvie me a last name:willie
Neatl formatted name: Lee Willie.
please give me a first name:q
(1)單元測試和測試用例
Python標準庫中的模組unittest提供了程式碼測試的工具。
單元測試用於核實函式的某個方面沒有問題;
測試用例是一組單元測試,它們是一道核實函式在各種情形下的行為都符合要求。良好的測試用例考慮到了函式可能收到的各種輸入,包含針對所有這些情形的測試。
全覆蓋的測試用例包含一整套單元測試,涵蓋了各種可能的函式使用方式。
(2)可通過的測試
要為函式編寫測試用例,可先匯入模組unittest和要測試的函式,再建立一個繼承unittes.TestCase的類,並編寫一系列方法對函式行為的不同方面進行測試。
#可通過的測試
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
'''測試name_function.py'''
def test_first_last_name(self):
'''能夠在正確處理像Janis Joplin這樣的姓名嗎?'''
formatted_name=get_formatted_name('janis','joplin')
self.assertEqual(formatted_name,'Janis Joplin')
if __name__=='__main__':
unittest.main()
在該示例中只包含了一個方法test_first_last_name(),它能夠檢查函式get_formatted_name()在給定的名和姓能否正確工作。
程式碼行import unittest是匯入了模組unittest
程式碼行from name_function import get_formatted_name是這個程式從name_function.py中匯入get_formatted_name()
程式碼行class NamesTestCase(unittest.TestCase):是建立了一個名為NamesTestCase的類,用於一系列針對函式get_formatted_name()的單元測試,在該類中,只包含一個方法test_first_last_name(),它用於測試函式get_formatted_name()的一個方面。
程式碼行 formatted_name=get_formatted_name(‘janis’,‘joplin’)是使用實參’janis’和joplin’呼叫get_formatted_name(),並將結果賦給變數formatted_name。
程式碼行 self.assertEqual(formatted_name,‘Janis Joplin’)使用了unittest類最有用的功能之一:斷言方法(核實得到的結果是否與期望的結果一致),示例中我們期望formatted_name的值為’Janis Joplin’,為檢查是否正確,我們呼叫了unittest的方法assertEqual(),並向它傳遞formatted_name和’Janis Joplin’。
ssertEqual(formatted_name,‘Janis Joplin’)的意思主要是將formatted_name的值與’Janis Joplin’進行比較。
執行結果:
.
----------------------------------------------------------------------
Ran 1 test in 0.008s
OK
>>>
第一行句點表示有一個測試通過了,接下來的一行指出了python執行了一個測試,消耗的時間為0.008s,最後的ok表示該測試用例中的所有單元測試都通過了。
(3)未通過的測試
當我們修改了要測試的程式碼(檔名為name_function_0.py):
def get_formatted_name(first,middle,last):
'''生成整潔的姓名'''
full_name=f"{first} {middle} {last}"
return full_name.title()
在這個示例中,函式比上一個示例多了一個形參’middle’,我們重新測試該程式看會發生什麼?
import unittest
from name_function_0 import get_formatted_name
class NamesTestCase(unittest.TestCase):
'''測試name_function.py'''
def test_first_last_name(self):
'''能夠在正確處理像Janis Joplin這樣的姓名嗎?'''
formatted_name=get_formatted_name('janis','joplin')
self.assertEqual(formatted_name,'Janis Joplin')
if __name__=='__main__':
unittest.main()
執行結果:
E
======================================================================
ERROR: test_first_last_name (__main__.NamesTestCase)
能夠在正確處理像Janis Joplin這樣的姓名嗎?
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\12184\Desktop\python_work\11_測試程式碼\test_name_function_0.py", line 10, in test_first_last_name
formatted_name=get_formatted_name('janis','joplin')
TypeError: get_formatted_name() missing 1 required positional argument: 'last'
----------------------------------------------------------------------
Ran 1 test in 0.010s
FAILED (errors=1)
我們來解讀報錯:
第一行字母指出測試用例中有一個單元測試導致了錯誤,之後指出是 test_first_last_name ()導致了錯誤,在traceback處指出了函式呼叫get_formatted_name(‘janis’,‘joplin’)有問題,TypeError指出是因為缺少了一個必不可少的位置實參(因為有3個形參,而我們只有2個實參值)。
(4)測試未通過怎麼辦
在上述示例中,我們已經知道了測試錯誤的原因,那為了測試通過,最佳的選擇我們可以讓形參’middle’的值變成可選的。
檔名為name_function_01.py
def get_formatted_name(first,last,middle=''):
'''生成整潔的姓名'''
if middle:
full_name=f"{first} {middle} {last}"
else:
full_name=f"{first} {last}"
return full_name.title()
重新測試:
import unittest
from name_function_01 import get_formatted_name
class NamesTestCase(unittest.TestCase):
'''測試name_function.py'''
def test_first_last_name(self):
'''能夠在正確處理像Janis Joplin這樣的姓名嗎?'''
formatted_name=get_formatted_name('janis','joplin')
self.assertEqual(formatted_name,'Janis Joplin')
if __name__=='__main__':
unittest.main()
執行結果:
----------------------------------------------------------------------
Ran 1 test in 0.015s
OK
>>>
我們可以看到:通過修改,測試用例通過了。
(二)測試類
在進行測試之前,我們先介紹unittest模組中的各種斷言方法:
方法———————————— 用途
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中
上述就是6種常用的斷言方法。
(1)一個要測試的類(檔名為survey.py)
class AnonymousSurvey:
'''收集匿名調查問卷的答案'''
def __init__(self,question):
'''儲存一個問題,併為儲存答案做準備'''
self.question=question
self.responses=[]
def show_question(self):
'''顯示調查問卷'''
print(self.question)
def store_responses(self,new_response):
'''儲存單份調查問卷'''
self.responses.append(new_response)
def show_result(self):
'''顯示收集到的所有答案'''
print("Survey result:")
for response in self.responses:
print(f"-{response}")
為了證明這個類能夠正確工作,我們編寫一個使用它的程式:
from survey import AnonymousSurvey
#定義一個問題,並建立一個調查。
question="what language did you first learn to speak?"
my_survey=AnonymousSurvey(question)
#顯示問題並儲存答案
my_survey.show_question()
print("enter 'q' at any time to quit")
while True:
response=input("language;")
if response=='q':
break
my_survey.store_responses(response)
#顯示調查結果
print("\nthank you to everyone who participated in the survey")
my_survey.show_result()
執行結果:
what language did you first learn to speak?
enter 'q' at any time to quit
language;English
language;Spanish
language;q
thank you to everyone who participated in the survey
Survey result:
-English
-Spanish
(2)測試AnonymousSurvey
import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
'''針對AnonymousSurvey類的測試'''
def test_store_single_response(self):
'''測試單個答案會被妥善儲存'''
question="what language did you first learn to speak"
my_survey=AnonymousSurvey(question)
my_survey.store_responses('English')
self.assertIn('English',my_survey.responses)
if __name__=='__main__':
unittest.main()
執行結果:
----------------------------------------------------------------------
Ran 1 test in 0.011s
OK
相關文章
- MYSQL程式碼顯示測試測試MySql
- 測試程式碼高亮
- 程式碼寫作測試
- 白盒測試程式碼應該怎麼測試
- 程式碼測試用例指南
- go 程式碼覆蓋率測試Go
- 使用 xunit 編寫測試程式碼
- C# 測試程式碼#if DEBUG使用C#
- 程式碼重構與單元測試——測試專案(二)
- 如何編寫優秀的測試程式碼|單元測試
- 前端頁面測試如何定位漏測程式碼前端
- 前端進階-編寫測試程式碼前端
- selenium(web端)淘寶測試程式碼Web
- 使用 Benchmark.NET 測試程式碼效能
- JavaScript實現佇列(程式碼+測試)JavaScript佇列
- 【效能測試】效能測試各知識第1篇:效能測試大綱【附程式碼文件】
- 測試程式
- Python學習之路10-測試程式碼Python
- php7連線mysql測試程式碼PHPMySql
- 不用寫程式碼,也能做好介面測試
- 軟體測試與程式碼安全詳解
- 無程式碼的啟動速度測試 with stagesepx
- 程式碼審計基礎--白盒測試
- 做軟體測試需要懂程式碼嗎?
- php 快取使用監控測試程式碼PHP快取
- selenium最佳化後的測試程式碼
- 程式碼重構與單元測試(一)
- 如何提高程式碼的可測試性
- Python物件導向之十二:程式碼測試Python物件
- 03----GD32E103RBT6----MISC測試程式碼[測試通過]
- 程式碼重構與單元測試——重構1的單元測試(四)
- 學會程式碼不是測試的終點而是測試開發的起點
- 微服務測試之靜態程式碼掃描微服務
- Java volatile 的測試(Java程式碼實戰-004)Java
- Eolink Apikit:HTTP 介面測試,零程式碼、快速上手APIHTTP
- 使用Spring AI和LLM生成Java測試程式碼SpringAIJava
- HelixQAC-軟體程式碼靜態測試工具
- 005 Web Assembly之測試康威遊戲程式碼Web遊戲