第11章 测试代码
编写函数或类时,还可为其编写测试。通过测试,可确定代码面对各种输入都能够按要求的那样工作。
1.测试函数
python提供了一种自动测试函数输出的高效方式。
单元测试和测试用例
python 标准库中的模块unittest提供了代码测试工具
单元测试用于核实函数的某个方面没有问题
测试用例是一组单元测试,它们一道核实函数在各种情形下的行为都符合要求
全覆盖的测试用例包含一整套单元测试,,涵盖了各种可能的函数使用方式
对于大型项目,要进行全覆盖测试可能很难。通常只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖
可通过的测试
import unittest
from name_function import get_formatted_name
class NameTestCase(unittest.TestCase):
def test_first_last_name(self):
formatted_name = get_formatted_name('janis','joplin')
self.assertEqual(formatted_name,'Janis Joplin')
if __name__ == '__main__':
unittest.main()
"""
Ran 1 test in 0.002s
OK
"""
未通过的测试
Ran 1 test in 0.006s
Launching unittests with arguments python -m unittest D:/Users/86180/Desktop/python编程学习笔记/源代码文件/chapter_11/myself.py in D:\Users\86180\Desktop\python编程学习笔记\源代码文件\chapter_11
FAILED (failures=1)
测试未通过时怎么办
修改被测试函数,而非测试函数
添加新测试
添加一个测试方法
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""Tests for 'name_function.py'."""
def test_first_last_name(self):
"""Do names like 'Janis Joplin' work?"""
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin')
def test_first_last_middle_name(self):
"""Do names like 'Wolfgang Amadeus Mozart' work?"""
formatted_name = get_formatted_name(
'wolfgang', 'mozart', 'amadeus')
self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')
if __name__ == '__main__':
unittest.main()
方法名必须以test_打头,这样才会在运行测试程序时自动运行。
2.测试类
针对类的测试
各种断言方法
方法 | 用途 |
---|
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) | 核实item不在list中 |
一个要测试的类
class AnonymousSurvey:
"""Collect anonymous answers to a survey question."""
def __init__(self, question):
"""Store a question, and prepare to store responses."""
self.question = question
self.responses = []
def show_question(self):
"""Show the survey question."""
print(self.question)
def store_response(self, new_response):
"""Store a single response to the survey."""
self.responses.append(new_response)
def show_results(self):
"""Show all the responses that have been given."""
print("Survey results:")
for response in self.responses:
print(f"- {response}")
from survey import 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类
import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
def test_store_single_response(self):
quesion = "what language did you first learn to speak?"
my_survey = AnonymousSurvey(quesion)
my_survey.store_response('English')
self.assertIn('English',my_survey.responses)
def test_store_three_response(self):
quesion = "what language did you first learn to speak?"
my_survey = AnonymousSurvey(quesion)
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()
测试有重复的地方
方法setUp()
import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
"""Tests for the class AnonymousSurvey"""
def setUp(self):
"""
Create a survey and a set of responses for use in all test methods.
"""
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):
"""Test that a single response is stored properly."""
self.my_survey.store_response(self.responses[0])
self.assertIn(self.responses[0], self.my_survey.responses)
def test_store_three_responses(self):
"""Test that three individual responses are stored properly."""
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()
unittest.TestCase类包含的方法setUp()让我们只需创建这些对象一次,就能在每个测试方法中使用。
可在setUpz方法中创建一系列实例并设置其属性,再在测试方法中直接使用这些实例
tips:运行测试用例时,每完成一个单元测试,python都打印一个字符:测试通过时打印一个句点,测试引发错误时打印一个E,而测试导致断言失败时则打印一个F。
如果测试用例包含很多单元测试,需要运行很长时间,就可通过观察这些结果来获悉有多少个测试通过了
|