1.测试函数
要学习测试,首先要有代码,下面提供一个简单的例子。
def get_formatted_name(first, last):
"""生成简洁的i姓名"""
full_name = f"{first} {last}"
return full_name.title()
print("Enter 'q' at any time to quit")
while True:
first = input("\nPlease give me a first name")
if first == 'q':
break
last = input("\nPlease give me a last name")
if last == 'q':
break
name = get_formatted_name(first, last)
print(f"\tNearly formatted name: {name}.")
1.1单元测试和测试用例
Python标准库提供了unittest模块提供了测试代码的工具。单元测试用于核实代码在某个方面没有问题。测试用例是一组测试单元,它们一道核实函数在各种情形下都没有问题。
1.2进行测试
为函数编写测试用例,首先要导入模块unittest和要测试的函数,再创建一个继承unittest.TestCase的类,并编写一系列方法对函数的不同行为进行测试。下面是一个例子:
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""测试name_function.py。"""
def test_first_last_name(self):
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin')
if __name__ == '__main__':
unittest.main()
首先,导入模块unittest以及函数get_formatted_name(),然后,创建了一个名为NamesTestCase类用以继承unittest.TestCase。这个类的名字定义是要有描述性,同时必须包含Test字样。
该类只包含一个方法,用于测试函数get_formatted_name()的一个方面。注意,test_打头的方法,再该程序运行时都会自动运行。
self.assertEqual()处使用了unittest类最有用的功能之一:断言方法。断言方法核实得到的结果是否与期望的结果一致。断言方法有以下几类:
方法 | 用途 |
assertEqual(a,b) | 核实a==b |
assertNotEqual(a,b) | 核实a!=b |
assertTure(x) | 核实x为True |
assertFalse(x) | 核实x为False |
assertIn(item,list) | 核实item在list中 |
assertNotIn(item,list) | 核实item不在list中 |
还有一个要注意的点是,if代码块检查特殊变量 __name__ ,如果这个文件作为主程序执行,变量 __name__ 被设置为__main__。如果不是在主程序中执行,则该变量不改变。
若测试未通过,会出现错误代码,这时我们还会看到一个标准的traceback,来指出我们的问题。有了问题,就需要进行改正,这时就需要找出导致函数行为不符合预期的地方,并进行修改。
当然,我们也可以添加新的测试,即定义一个新的方法,进行相关测试。
2.测试类
上一节中,编写了针对单个函数的测试,下面在编写针对类的测试。
2.1一个要测试的类
类的测试与函数相似,你所做的工作大部分是测试类中方法的行为。下面编写一个要测试的类:
class AnonymousSurvey:
"""收集匿名调查问卷的答案"""
def __init__(self, question):
self.question = question
self.respones = []
def show_qusetion(self):
print(self.question)
def store_response(self, new_response):
self.respones.append(new_response)
def show_results(self):
print("Survey results")
for response in self.respones:
print(f"- {response}")
2.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_response('English')
self.assertIn('English', my_survey.respones)
if __name__ == '__main__':
unittest.main()
2.3方法setUp
只能收集一个答案的调查用途的作用不大,我们通常需要收集好多个,并且每次定义一个新方法就要创建一个AnonymousSurvey实例并不方便。所以,我们要用到unittest.TestCase类中包含的setUp方法。该方法只需要我们创建这些对象一次,就能在每个测试方法中使用它们。
下面使用该方法创建一个调查对象和一组答案。
import unittest
from Survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
"""针对AnonymousSurvey类进行测试"""
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('English', self.my_survey.respones)
def test_store_three_response(self):
for response in self.responses:
self.my_survey.store_response(response)
for response in self.responses:
self.assertIn(response, self.my_survey.respones)
if __name__ == '__main__':
unittest.main()
方法setUp做了两件事:创建一个调查对象,以及创建一个答案列表。存储这两样东西的变量名包含前缀self(即:存储在属性中)。因此,可以在类的任何地方使用它。