测试代码
学习如何使用python模块unittest中的工具来测试代码。
学习编写测试用例,核实一系列输入都将得到预期的输入。
学习如何测试函数和类,并将知道该为项目编写多少个测试。
测试函数
def get_formatted_name(first,last):
"""Generate a neatly formatted full name."""
full_name = first + ' ' + last
return full_name.title()
- 为了核实get_formatted_name()可以想想象的那样工作,编写一个使用该函数的程序。
from name_function import get_formatted_name
print("Enter 'q' at any time 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
formatted_name = get_formatted_name(first,last)
print("Neatly formatted name: " + formatted_name + '.')
Enter 'q' at any time quit.
Please give me a first name: 小黑
Please give me a last name: 蛋
Neatly formatted name: 小黑 蛋.
Please give me a first name: q
***Repl Closed***
单元测试和测试用例
- 模块unittest提供例如代码测试工具。
- 单元测试用来核实函数的某个方面有没有问题。
- 测试用例是一组单元测试,这些单元测试一起核实函数在各种情况下都符合要求。
- 全覆盖测试用例包含一整套单元测试,覆盖了各种可能的函数使用方式。
可通过的测试
- 为函数编写测试用例,首先导入模块unittest以及测试的函数,在创建继承unittest.TestCase的类,
- 并编写一系列方式对函数行为的不同方面进行测试。
import unittest
from name_function import get_formatted_name
class NameTestCase(unittest.TestCase):
"""测试name_function.py"""
def test_first_last_name(self):
"""能够正确处理像Jains Joplin"""
formatted_name = get_formatted_name('janis','Joplin')
self.assertEqual(formatted_name,'Janis Joplin')
unittest.main()
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
[Finished in 0.2s]
- 给测试类命名时,最好包含Test字样,让他 看起来与测试的函数有关。
- 这个类必须继承unittest.TestCase类,让python知道你如何运行你编写的测试。
- unittest类最有用的功能之一
- 断言方法:用来核实运行得到的结果是否与预期的结果一致。
- self.assertEqual就是将的formatted_name值与字符串Janis Joplin进行比较,如果相等万事大吉,不相等说一声。
不能通过的测试。
- 修改get_formatted_name(),使其能够处理中间名。
def get_formatted_name(first,middle,last):
"""Generate a neatly formatted full name."""
full_name = first + ' ' + middle + ' ' + last
return full_name.title()
- 在进行测试就会报错
import unittest
from name_function import get_formatted_name
class NameTestCase(unittest.TestCase):
"""测试name_function.py"""
def test_first_last_name(self):
"""能够正确处理像Jains Joplin"""
formatted_name = get_formatted_name('janis','Joplin')
self.assertEqual(formatted_name,'Janis Joplin')
unittest.main()
E
======================================================================
ERROR: test_first_last_name (__main__.NameTestCase)
能够正确处理像Jains Joplin
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\学习笔记\python学习笔记\第十一章\test_name_function.py", line 10, in test_first_last_name
formatted_name = get_formatted_name('janis','Joplin')
TypeError: get_formatted_name() missing 1 required positional argument: 'last'
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (errors=1)
[Finished in 0.1s with exit code 1]
- 测试未通过时,第一行输出有个字母E,说明测试用例有个单元测试导致了错误。
测试为通过时怎么办
- 检查对函数所做的修改,找出函数不符合预期的修改。
- name_function.py
def get_formatted_name(first,last,middle=''):
"""Generate a neatly formatted full name."""
if middle:
full_name = first + ' ' + middle + ' ' + last
else:
full_name = first + ' ' + last
return full_name.title()
- test_name_function.py
import unittest
from name_function import get_formatted_name
class NameTestCase(unittest.TestCase):
"""测试name_function.py"""
def test_first_last_name(self):
"""能够正确处理像Jains Joplin"""
formatted_name = get_formatted_name('janis','Joplin')
self.assertEqual(formatted_name,'Janis Joplin')
unittest.main()
添加新测试。
import unittest
from name_function import get_formatted_name
class NameTestCase(unittest.TestCase):
"""测试name_function.py"""
def test_first_last_name(self):
"""能够正确处理像Jains Joplin"""
formatted_name = get_formatted_name('janis','Joplin')
self.assertEqual(formatted_name,'Janis Joplin')
def test_first_last_middle_name(self):
formatted_name = get_formatted_name('J','Q','K')
self.assertEqual(formatted_name,'J K Q')
unittest.main()
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
[Finished in 0.1s]
- 将这个方法命名为test_first_last_middle_name,方法命名必须以test_ 开头,这样它才能自动运行。
测试类
- 前面讲的是针对单个函数的测试,下面是针对类的测试。
- 如果针对的类通过测试,你就能确信对类所做的改进没有意外的破坏原来的行为。
各种断言方法
- python中的unittest.TestCase提供了很多断言方法。
- unittest Module中的断言方法
方法 | 用途 |
---|---|
self.assertEqual(a,b) | 核实a == b |
self.assertNotEqual(a,b) | 核实 a != b |
self.assertTrue(x) | 核实x 为Ture |
self.assertFalse(x) | 核实x为False |
self.assertIn(item,list) | 核实item在list中 |
self.assertNotIn(item,list) | 核实item不在list中 |
一个要测试的类
编写一个帮助管理匿名测试的类
surver.py
class anonymousSurvey():
"""收集匿名调查的答案"""
def __init__(self,question):
self.question = question
self.responses = []
def show_question(self):
"""显示调查问卷"""
print(self.question)
def store_responses(self,new_responses):
"""存储单份调查答卷"""
self.responses.append(new_responses)
def show_results(self):
"""显示收集到的所有答案"""
print("Survey results: ")
for response in self.responses:
print('-' + response)
- 编写一个使用它的程序
- language_survey.py
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_responses(response)
print("\nThank you to everyone who participated in the survey!")
my_survey.show_results()
What language did you first learn to speak?
Enter 'q' at any time to quit.
language: English
language: chinses
language: chinese
language: English
language: q
Thank you to everyone who participated in the survey!
Survey results:
-English
-chinses
-chinese
-English
***Repl Closed***
测试AnonymousSurvey类
- 使用方法asserIn()核实是否答案列表中。
import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
"""针对AnonymousSurvey类的测试"""
def test_store_single_response(self):
"""测试单个答案是否会被存储"""
question = "What language fif you first learn to speak?"
my_survey = AnonymousSurvey(question)
my_survey.store_responses("chinese")
self.assertIn('chinese',my_survey.responses)
unittest.main()
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
[Finished in 0.2s]
- 测试提供三个答案时
import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
"""针对AnonymousSurvey类的测试"""
def test_store_single_response(self):
"""测试单个答案是否会被存储"""
question = "What language fif you first learn to speak?"
my_survey = AnonymousSurvey(question)
my_survey.store_response("chinese")
self.assertIn('chinese',my_survey.responses)
def test_store_three_responses(self):
question = "What language fif you first learn to speak?"
my_survey = AnonymousSurvey(question)
responses = ["English","chinese","Japanese"]
for response in responses:
my_survey.store_response(response)
for response in responses:
self.assertIn(response,my_survey.responses)
unittest.main()
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
[Finished in 0.5s]
方法setUP()
- 使用setUp()来创建一个调查对象和一组答案。提供test_store_single_response()和test_store_three_responses()使用。
import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
"""针对AnonymousSurvey类的测试"""
def setUp(self):
question = "What language fif you first learn to speak?"
self.my_survey = AnonymousSurvey(question)
self.responses = ["English","chinese","Japanese"]
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)
unittest.main()
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
[Finished in 0.4s]
- 方法setUp()做了两件事:
- 1.创建了一个调查对象。2.创建一个答案列表
小结
- 如何使用模块unittest()中工具中函数和类编写测试。
- 如何编写继承unitest.TestCase()的类,以及如何编写测试方法。
- 如何使用setUP()来根据类创建实例并设置属性。