编写函数或类时还可以为其编写测试,通过测试,可确定代码面对各种输入都能够按照要求的那样工作
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 + ".")
Python标准库中的模块 unittest 提供了代码测试工具,单元测试用于核实函数的某个方面没有问题
测试用例是一组单元测试,这些单元测试一起核实函数在各种情形的测试
全覆盖测试用例包含一整套单元测试,涵盖了何种可能的函数使用方式
要为函数编写测试用例,可先导入模块 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()
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 中
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()
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都打印一个字符,如果测试用例包含很多单元测试,需要运行很长时间,就可以通过观察这些结果来获悉有多少个测试通过了