11 测试代码
编写函数或类时还可以为其编写测试,通过测试,可确定代码面对各种输入都能够按照要求的那样工作
11.1 测试函数
name_function.py:一个简单的函数
def get_formatted_name(first, last):
"""生成整洁的姓名"""
full_name = first + ' ' + last
return full_name.title()
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 give me a last name: ")
if last == 'q':
break
formatter_name = get_formatted_name(first, last)
print("\tNeatly formatted name : " + formatter_name + ".")
11.1.1 单元测试和测试用例
Python标准库中的模块 unittest 提供了代码测试工具,单元测试用于核实函数的某个方面没有问题
测试用例是一组单元测试,这些单元测试一起核实函数在各种情形的测试
全覆盖测试用例包含一整套单元测试,涵盖了何种可能的函数使用方式
11.1.2 可能同的测试
要为函数编写测试用例,可先导入模块 unittest 以及要测试的函数,再创建一个继承 unittext.TestCase 的类,并编写一系列方法对函数行为的不同方面进行测试
断言方法用来核实得到的结果食肉与期望的结果一致
import unittest
from first import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""测试 name_function.py"""
def test_first_last(self):
"""能够正确处理像 Janis Joplin 这样的姓名吗?"""
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin')
unittest.main()
11.2 测试类
11.2.1 各种断言方法
asserEqual(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 一个要测试的类
AnonymousSurvey 类可用于进行简单的匿名调查
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('- ' + response)
from first import AnonymousSurvey
# 定义一个问题,并创建一个表示调查的 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 participated in survey!")
my_survey.show_results()
测试类:
import unittest
from first 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_response('English')
self.assertIn('English', my_survey.responses)
if __name__ == '__main__':
unittest.main()
11.2.4 方法 setUp()
unittest.TestCase 类包含方法 setUp(),Python将先运行他,再运行各个以 test_ 打头的方法,这样在编写的每个测试方法中都可以使用方法 setUp() 中创建对象了
方法 setUp() 做了两件事情:创建一个调查对象;创建了一个答案列表
可在 setUp() 方法中创建一些列实例并设置它们的属性,再在测试方法中直接使用这些实例
import unittest
from first import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
"""针对 AnonymousSurvey 类的测试"""
def setUp(self) -> None:
"""创建一个调查对象和一组答案,供使用的测试方法使用"""
question = "What language did you first learn to speak?"
self.my_survey = AnonymousSurvey(question)
self.responses = ['English', 'Spanish', 'Mandarin']
def test_store_single_response(self):
"""测试单个答案会被妥善的存储"""
self.my_survey.store_response(self.responses[0])
self.assertIn(self.responses[0], self.my_survey.responses)
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)
if __name__ == '__main__':
unittest.main()
运行测试用例时,没完成一个测试,Python都打印一个字符,如果测试用例包含很多单元测试,需要运行很长时间,就可以通过观察这些结果来获悉有多少个测试通过了