前言
之前的博客学习了针对单个函数的测试,今天学习一下如何编写针对类的测试,因为很多程序都会用到类,证明你的类能够正确运行对工作大有裨益!接下来开始学习!
目录
之前的博客学习了针对单个函数的测试,今天学习一下如何编写针对类的测试,因为很多程序都会用到类,证明你的类能够正确运行对工作大有裨益!接下来开始学习!
1、各种断言方法
2、一个要测试的类
3、测试AnonymousSurvey 类
4、方法setUp()
5、课后练习
6、小结
1、各种断言方法
Python在unittest.TestCase类中提供了很多断言方法。前面说过,断言方法检查你认为应 该满足的条件是否确实满足。如果该条件确实满足,你对程序行为的假设就得到了确认,你就可 以确信其中没有错误。如果你认为应该满足的条件实际上并不满足,Python将引发异常。 你只能在继承unittest.TestCase的类中使用这些方法,下面来看看如何在测试类时使用其中的一个。
2、一个要测试的类
类的测试与函数的测试相似——你所做的大部分工作都是测试类中方法的行为,但存在一些不同之处,下面来编写一个类进行测试。来看一个帮助管理匿名调查的类:
survey.py
#定义一个帮助管理匿名调查的类
class AnonymousSurvey():
def __init__(self,question):
self.question = question
self.response = []
def show_question(self):
print(question)
def store_response(self,new_response):
self.response.append(new_response)
def show_results(self):
print("Survey results:")
for response in responses:
print('- '+response)
language_survey.py
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()
AnonymousSurvey类可用于进行简单的匿名调查。假设我们将它放在了模块survey中,并想进 行改进:让每位用户都可输入多个答案;编写一个方法,它只列出不同的答案,并指出每个答案 出现了多少次;再编写一个类,用于管理非匿名调查。 进行上述修改存在风险,可能会影响AnonymousSurvey类的当前行为。例如,允许每位用户输 入多个答案时,可能不小心修改了处理单个答案的方式。要确认在开发这个模块时没有破坏既有 行为,可以编写针对这个类的测试。
3、测试AnonymousSurvey 类
下面来编写一个测试,对AnonymousSurvey类的行为的一个方面进行验证:如果用户面对调查 问题时只提供了一个答案,这个答案也能被妥善地存储。为此,我们将在这个答案被存储后,使 用方法assertIn()来核实它包含在答案列表中:
# _*_ coding:utf-8 _*_
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.store_response)
def test_store_three_response(self):
"""测试三个答案会被妥善地存储"""
question = "What language did you first learn to speak?"
my_survey = AnonymousSurvey(question)
response = ['English','Spanish','Mandarin']
for response in responses:
my_survey.store_response(response)
for response in responses:
self.assertIn(response,my_survey.store_response)
unittest.main()
输出结果:
Testing started at 16:48 ...
D:\python北风\venv\Scripts\python.exe "D:\PyCharm 2018.3.5\helpers\pycharm\_jb_unittest_runner.py" --path D:/python北风/chapter10测试代码/test_survey.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
4、方法setUp()
unittest.TestCase类包含方法setUp(),让我们只需创建这些对象一 次,并在每个测试方法中使用它们。如果你在TestCase类中包含了方法setUp(),Python将先运行 它,再运行各个以test_打头的方法。这样,在你编写的每个测试方法中都可使用在方法setUp() 中创建的对象了。
下面使用setUp()来创建一个调查对象和一组答案,供方法test_store_single_response()和 test_store_three_responses()使用:
# _*_ coding:utf-8 _*_
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):
"""测试单个答案会被妥善地存储"""
# question = "What language did you first learn to speak?"
# my_survey = AnonymousSurvey(question)
# my_survey.store_response('English')
# self.assertIn('English',my_survey.store_response)
self.my_survey.store_response(self.responses[0])
self.assertIn(self.responses[0],self.my_survey.store_responses)
def test_store_three_response(self):
"""测试三个答案会被妥善地存储"""
# question = "What language did you first learn to speak?"
# my_survey = AnonymousSurvey(question)
# response = ['English','Spanish','Mandarin']
# for response in responses:
# my_survey.store_response(response)
# for response in responses:
# self.assertIn(response,my_survey.store_response)
for response in responses:
self.my_survey.store_response(response)
for response in responses:
self.assertIn(response,self.my_survey.responses)
unittest.main()
5、课后练习
11-3 雇员:编写一个名为 Employee 的类,其方法__init__()接受名、姓和年薪,并 将它们都存储在属性中。编写一个名为 give_raise()的方法,它默认将年薪增加 5000 美元,但也能够接受其他的年薪增加量。
为 Employee 编写一个测试用例,其中包含两个测试方法:test_give_default_ raise()和 test_give_custom_raise()。使用方法 setUp(),以免在每个测试方法中都创 建新的雇员实例。运行这个测试用例,确认两个测试都通过了。
#employee.py
# _*_ coding:utf-8 _*_
class Employee():
def __init__(self,first_name,last_name,salary):
self.first_name = first_name
self.last_name = last_name
self.salary = salary
def give_raise(self,increment=5000):
self.salary += increment
#test_employee.py
# _*_ coding:utf-8 _*_
import unittest
class TestRaise(unittest.TestCase):
def setUp(self):
self.employee = Employee('Li','hua',5000)
"""默认情况"""
def test_default_raise(self):
self.employee.give_raise()
self.assertEqual(self.employee.salary,10000)
"""其他情况下"""
def test_give_custom_raise(self):
self.employee.give_raise(10000)
self.assertEqual(self.employee.salary,15000)
unittest.main()
结果:
Testing started at 17:28 ...
D:\python北风\venv\Scripts\python.exe "D:\PyCharm 2018.3.5\helpers\pycharm\_jb_unittest_runner.py" --path D:/python北风/chapter10测试代码/test_employee.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
Launching unittests with arguments python -m unittest D:/python北风/chapter10测试代码/test_employee.py in D:\python北风\chapter10测试代码
OK
Process finished with exit code 0
6、小结
在本章中,你学习了:如何使用模块unittest中的工具来为函数和类编写测试;如何编写继 承unittest.TestCase的类,以及如何编写测试方法,以核实函数和类的行为符合预期;如何使用 方法setUp()来根据类高效地创建实例并设置其属性,以便在类的所有测试方法中都可使用它们。
测试是很多初学者都不熟悉的主题。作为初学者,并非必须为你尝试的所有项目编写测试; 但参与工作量较大的项目时,你应对自己编写的函数和类的重要行为进行测试。这样你就能够更 加确定自己所做的工作不会破坏项目的其他部分,你就能够随心所欲地改进既有代码了。如果不 小心破坏了原来的功能,你马上就会知道,从而能够轻松地修复问题。相比于等到不满意的用户 报告bug后再采取措施,在测试未通过时采取措施要容易得多。