# name_function.py
def get_formatted_name(first, last):"""生成整洁的姓名"""full_name = f"{first} {last}"return full_name.title()
# names.py
from name_function import get_formatted_nameprint("Enter 'q' at any time to quit.")
while True:first = input("Please give me a first name: ")if first == 'q':breaklast = input("Please give me a last name: ")if last == 'q':breakformatted_name = get_formatted_name(first, last)print(f"\tNeatly formatted name: {formatted_name}.")
Python标准库中的模块unittest提供了代码测试工具。
单元测试用于核实函数的某个方面没有问题。
测试用例是一组单元测试,它们一道核实函数在各种情形下的行为都符合要求。
全覆盖的测试用例包含一整套单元测试,覆盖了各种可能的函数使用方式。
要为函数编写测试用例,可先导入模块unittest和要测试的函数,再创建一个继承unittest.TestCase的类,并编写一系列方法对函数行为的不同方面进行测试。
# test_name_function.py
import unittest
from name_function import get_formatted_name
# 类必须继承unittest.TestCase
# 运行test_name_function.py时,所有以test_打头的方法都将自动运行
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_,这个变量是在程序执行时设置的
# 如果这个文件作为主程序执行,变量_name_将被设置为'_main_'
# 这里,调用unittest.main()来运行测试用例
# 如果这个文件被测试框架导入,变量_name_的值将不是'_main_',因此不会调用unittest.main()
if _name_ == '_main_':unittest.main()
图结果
第一行的句点表明有一个测试用例通过了。接下来的一行指出Python运行了一个测试,消耗的时间不到0.001秒。最后的OK表明该测试用例中的所有单元测试都通过了。
# name_function.py
def get_formatted_name(first, middle, last):"""生成整洁的姓名"""full_name = f"{first} {middle} {last}"return full_name.title()
再次运行test_name_function.py时,输出如下:
图结果
# name_function.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()
再次运行test_name_function.py时,输出如下:
图结果
# test_name_function.py
import unittest
from name_function import get_formatted_nameclass 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')def test_first_last_middle_name(self):"""能够正确地处理像Wolfgang Amadeus Mozarta这样的姓名吗?"""formatted_name = get_formatted_name('wolfgang', 'amadeus', 'mozarta')self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozarta')if _name_ == '_main_':unittest.main()
动手试一试
表11-1
# survey.py
class AnonymousSurvey:"""收集匿名调查问卷的答案"""def _init_(self, question):"""存储一个问题,并为存储答案做准备"""self.question = questionself.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}")
from survey import AnonymousSurveyquestion = "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':breakmy_survey.store_response(response)print("Thank you to everyone who participate in the survey!")
my_survey.show_results()
# test_survey.py
import unittest
from survey import AnonymousSurveyclass 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)def test_store_three_responses(self):"""测试三个答案会被妥善地存储"""question = "What language did you first learn to speak?"my_survey = AnonymousSurvey(question)responses = ['English', 'Spanish', 'Mandarin']for response in responses:my_survey.store_response(response)for response in responses:self.assertIn(response, my_survey.responses)if _name_ == '_main_':unittest.main()
# test_survey.py
import unittest
from survey import AnonymousSurveyclass TestAnonymousSurvey(unittest.TestCase):"""针对AnonymousSurvey类的测试"""# 如果在TestCase类中包含了方法setUp(),Python将先运行它,再运行各个以test_打头的方法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_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 responses:self.assertIn(response, self.my_survey.responses)if _name_ == '_main_':unittest.main()
运行测试用例时,每完成一个单元测试,Python都打印一个字符:测试通过时打印一个句点,测试引发错误时打印一个E,而测试导致断言失败时则打印一个F。
动手试一试