Python蟒蛇书学习笔记——第十一章 测试代码
本章主要提到如果使用Python模块unittest中的工具来测试代码,还将学习编写测试用例,可以学到测试通过和测试不通过时的表现,以及如何改进代码。还将学习如何测试函数和类,并将知道该为项目编写多少测试。
下面为本笔记的目录,可以点击目录跳转到对应的部分阅读。
文章目录
- Python蟒蛇书学习笔记——第十一章 测试代码
- 11.1 测试函数
- 11.1.1 单元测试与单元用例
- 11.1.2 可通过的测试
- 11.1.3 未通过的测试
- 11.2 测试类
- 11.2.1 各种断言方法
- 11.2.2 一个要测试的类
11.1 测试函数
11.1.1 单元测试与单元用例
单元测试:用于核实函数的某个方面没有问题。
测试用例:一组单元测试,它们一道核实函数在各种情形下的行为均符合要求。
全覆盖:包含一整套完整的单元测试,涵盖了各种可能的函数使用方式。
11.1.2 可通过的测试
下面我们测试一个例子来看看可通过的测试会有什么输出结果。在main.py中,编写一个get_name函数,用于连接姓氏和名,组成完整的人名。
#main.py
def get_name(first,last):
full_name = f"{first} {last}"
return full_name.title()
我们再创建一个文件test.py,用于测试main.py里面的get_name函数是否运行正常。
#test.py
import unittest #导入unittest模块
from main import get_name #导入main.py里面的get_game函数
class NameTestCase(unittest.TestCase): #用于测试的类,必须继承unittest.TestCase类
def test_full_name(self): #创建一个函数用于测试
full_name=get_name('john','limit')
self.assertEqual(full_name,'John Limit') #断言,判断两个数据是否一致
if __name__ == '__main__': #用于判断是否以该程序作为主程序运行,如果是则开始测试
unittest.main()
上面的NameTestCase类命名可以任意,但最好能让程序员读懂这是用于测试的模块。它必须继承unittest.TestCase类。
倒数第二行的if语句用来检查特殊变量______name______。在Python中,如果这个文件作为主程序运行,则______name______将被设置为’main’。在此处检查这个是为了调用unittest.main()来运行调试用例。若这个文件不作为主程序运行,则调试的模块不会执行。
此时程序的输出如下:
.
----------------------------------------------------------------------
Ran 1 test in 0.005s
OK
第一个句点表示有一个测试通过了。接下来的一行指出Python运行了一个测试,消耗的时间为0.005s。最后的OK表示所该测试用例中的所有单元测试都通过了。
11.1.3 未通过的测试
接着11.1.2,我们将其中的test.py中用于比较的语句修改一下:
self.assertEqual(full_name,'john limit') #原语句:self.assertEqual(full_name,'John Limit')
再次运行,程序输出如下:
F
======================================================================
FAIL: test_first_last_name (__main__.NameTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\lenovo\Desktop\test.py", line 6, in test_first_last_name
self.assertEqual(name,'john limit')
AssertionError: 'John Limit' != 'john limit'
- John Limit
? ^ ^
+ john limit
? ^ ^
----------------------------------------------------------------------
Ran 1 test in 0.006s
FAILED (failures=1)
在这段信息中,第一行输出的“F”表示测试用例中有一个单元测试导致了错误。接下来,我们可以看到错误来源的地方:在______main______.NameTestCache类中的test_first_last_name()函数内发生了错误。然后我们就可以看到一个标准的Traceback,里面指出函数所返回的结果与预期的结果不一致。
11.2 测试类
在11.1中,我们学习了测试函数的方法。在这一部分,我们来一起学习测试类的方法。
11.2.1 各种断言方法
Python在unittest.TestCase中提供了很多断言方法。下表中罗列了6个常见的断言方法,使用这些方法可以核实返回的值是否等于预期的值:若相等,则返回True;否则返回False。
方法 | 用途 |
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中 |
11.2.2 一个要测试的类
下面我们以用于管理匿名调查的类为例进行测试。此处我们需要使用三个文件:AS.py用来存储管理匿名调查的类;main.py负责调用该类并进行收集匿名回应;test.py用于对结果进行测试。这三个文件的内容分别如下。
#AS.py
class AnonymousSurvey:
def __init__(self,question):
self.question=question
self.responses=[] #用于存储匿名回应
def show_question(self): #在屏幕上打印出问题
print(self.question)
def store_response(self,new_response): #把匿名回应附加到列表中
self.responses.append(new_response)
def show_results(self):
print("Survey results:")
for response in self.responses: #逐个打印匿名回应
print(f"- {response}")
#main.py
from AS 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.\n")
while True:
response = input('language:')
if response == 'q':
break
my_survey.store_response(response)
print('\nThank you to everyone who paticipated in the survey!')
my_survey.show_results()
#test.py
import unittest
from AS import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
def setUp(self):
"""创建一个调查对象和一组答案,供使用的测试方法使用。"""
question = 'What language did you first learn to speak?'
self.my_survey = AnonymousSurvey(question)
self.responses = ['English','Spanish','Mandarin']
def test_store_three_responses(self):
for response in self.responses:
self.my_survey.store_response(response)
for response in self.responses:
self.assertIn(response,self.my_survey.responses) #判断每个response是否都在列表内
if __name__ == '__main__':
unittest.main()
当我们运行main.py时,所得的结果如下:
What language did you first learn to speak?
Enter q at any time to quit.
language:English
language:Spanish
language:Chinese
language:Cantonese
language:q
Thank you to everyone who paticipated in the survey!
Survey results:
- English
- Spanish
- Chinese
- Cantonese
当我们运行test.py时,所得的结果如下:
.
----------------------------------------------------------------------
Ran 1 test in 0.005s
OK