Python-基础入门-学习笔记(7):测试代码
Python-基础入门-学习笔记(7):测试代码
一、测试函数
1.单元测试和测试用例
Python标准库中的模块unittest提供了代码测试工具。单元测试用于核实函数的某个方面没有问题;测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。
2.可通过的测试
要为函数编写测试用例,可先导入模块unittest以及要测试的函数,再创建一个继承unittest.TestCase的类,并编写一系列方法对函数行为的不同方面进行测试。
#待测文件: name_function.py
def get_formatted_name(first,last):
"""生成整洁的姓名"""
full_name = first + ' ' + last
return full_name.title()
#测试
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""测试name_fnction.py"""
def test_first_last_name(self):
"""能够正确地处理姓名吗?"""
formatted_name = get_formatted_name('janis','joplin')
self.assertEqual(formatted_name,'Janis Joplin')
unittest.main()
我们创建了一个Test类,用来包含一系列针对get_formatted_name()的单元测试,并且要继承unittest.TestCase类。
通过调用unittest的方法assertEqual(),并向它传递了两个值判断是否相等。
第一行的句点表示有一个测试通过了,第二行表示测试消耗的时间,最后的OK表示该测试用例中的所有单元测试都通过了。
3.不能通过的测试
通过修改待测文件,使其出现错误,结果显示:
字母E代表测试用例中有一个单元测试导致了错误,之后是NameTestCase中的test_first_last_name()导致了错误,最后显示测试失败。
测试未通过时,请检查刚对函数所做的修改,找出导致函数行为不符合预期的修改。
4.添加新的测试
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""测试name_fnction.py"""
def test_first_last_name(self):
"""能够正确地处理姓名吗?"""
formatted_name = get_formatted_name('janis','joplin')
self.assertEqual(formatted_name,'Janis Joplin')
def test_first_last_middle_name(self):
"""能够正确地处理像Wolfgang Amadeus Mozart这样的姓名吗?"""
formatted_name = get_formatted_name(
'wolfgang','mozart','amadeus')
self.assertEqual(formatted_name,'Wolfgang Amadeus Mozart')
unittest.main()
方法名必须以test打头,这样它才会在我们运行test_name_function.py时自动运行。
练习
#city_function.py
def get_formatted_information(city,country):
"""生成一种格式"""
full_information = city + ',' + country
return full_information.title()
#代码正确性测试
import unittest
from city_function import get_formatted_information
class CityTestCase(unittest.TestCase):
"""测试city_function.py"""
def test_city_country(self):
"""能够正确处理格式"""
formatted_information = get_formatted_information('santiago','chile')
self.assertEqual(formatted_information,'Santiago,Chile')
unittest.main()
下面我们增加可选择性:
#city_function.py
def get_formatted_information(city,country,population=''):
"""生成一种格式"""
if population:
full_information = city + ',' + country + ',' + 'population:' + population
else:
full_information = city + ',' + country
return full_information.title()
#代码正确性测试
import unittest
from city_function import get_formatted_information
class CityTestCase(unittest.TestCase):
"""测试city_function.py"""
def test_city_country(self):
"""能够正确处理格式"""
formatted_information = get_formatted_information('santiago','chile')
self.assertEqual(formatted_information,'Santiago,Chile')
def test_city_country_population(self):
"""能够正确处理三个参数的格式"""
formatted_information = get_formatted_information('santiago','chile','50000000')
self.assertEqual(formatted_information,'Santiago,Chile,Population:50000000')
unittest.main()
二、测试类
1.各种断言方法
断言方法是用来检查你认为应该满足的条件是否确实满足。以下表格的断言你需要在继承unittest.TestCase的类中使用这些方法。
方法 | 用途 |
---|---|
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) | 核实ltem不在list中 |
2.一个要测试的类
对类的测试大部分要做的工作是测试类中方法的行为,但也有一些不同之处。
首先创建一个需要测试的类:
#survey.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 result: ")
for response in self.responses:
print('- ' +response)
之后创建一个程序验证是否可以正常使用:
from survey 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 the survey!")
my_survey.show_results()
最后使用方法assertIn()对类进行测试。
import unittest
from survey import AnonymousSurvey
class TsetAnonymousSurvey(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)
unittest.main() #让Python运行这个文件中的测试
3.方法setUp()
unittest.TestCase类包含方法setup(),让我们只需创建这些对象一次,并在每个测试方法中使用它们。如果你在TestCase类中包含了方法setup(),Python将先运行它,再运行各个以test_打头的方法。
import unittest
from survey import AnonymousSurvey
class TsetAnonymousSurvey(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(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.rsponses:
self.assertIn(response,self.my_survey.responses)
我们可以在setUp()方法中创建一系列实例并设置它们的属性,再在测试方法中直接使用这些实例。比在每个方法中都创建一下方便的多。
练习
- 编写一个需要测试的类
class Employee():
"""描述员工年薪"""
def __init__(self,first_name,last_name,annual_salary):
self.name = first_name + ' ' + last_name
self.salary = annual_salary
def describe_someone_annual_salary(self):
"""描述某人年薪"""
message = self.name.title()
message += " is " + str(self.salary) + " a year."
print(message)
return message
def give_raise(self,number=5000):
"""对年薪进行提高"""
new_salary = int(self.salary) + number
self.salary = str(new_salary)
- 创建一个实例进行简单的验证
from employee import Employee
#定义一个员工,并创建一个表示统计的Employee对象
my_employee = Employee('jay','chou',100000)
#显示员工信息
my_employee.describe_someone_annual_salary()
#表现良好涨工资
my_employee.give_raise(50000)
#涨工资后
my_employee.describe_someone_annual_salary()
- 测试这个类
import unittest
from employee import Employee
class TsetEmployee(unittest.TestCase):
"""针对Employee类的测试"""
def setUp(self):
"""创建一个调查对象,供使用的测试方法使用"""
self.my_employee = Employee('jay','chou',100000)
self.raises = [10000,20000,30000,40000]
def test_give_default_raise(self):
"""测试能否正确显示增加默认的年薪"""
result = self.my_employee.describe_someone_annual_salary()
self.assertEqual(result,'Jay Chou is 100000 a year.')
def test_give_custom_raise(self):
"""测试能否够正确显示增加指定的年薪"""
self.my_employee.give_raise(self.raises[0])
result = self.my_employee.describe_someone_annual_salary()
self.assertEqual(result,'Jay Chou is 110000 a year.')
unittest.main()
最终结果确认成功:
由于在类中添加了打印,所以最后的结果解释为:测试通过打印逗点,之后再打印信息。
如果去掉打印功能,则是大家普遍看到的测试通过状态。