学习Python有段时间了,关于测试的部分基本没咋学过,初学的时候看不懂,现在都2018年了,回头再来学习下,要不然一点不了解说不过去。
首先参考的是入门初级《Python编程从入门到实践》第11章,测试代码。
Python标准库中的模块unittest提供了代码测试工具。单元测试用于何时函数的某个方法没有问题;
测试用例是一组单元测试,这些单元测试一起核实函数在各种情况下的行为都符合要求。
良好的测试用例考虑到了函数可能收到的各种输入,包含针对目标情形的测试。
全覆盖测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖很难。
通常,最初只要针对代码的重要行为编写测试既可,等项目被广泛使用时再考虑全覆盖。
首先编写一个测试函数
def get_formatted_name(first, last):
full_name = first + ' ' + last
return full_name.title()
然后编写一个测试该函数的类
import unittest
from name_function import get_formatted_name
# 编写一个测时类继承unittest.TestCase
class NamesTestCase(unittest.TestCase):
# 定义一个测试的方法,方法名字要以test开头,这样在unittest.main()执行的时候会自动执行
def test_first_last_name(self):
# 调用被测试的函数,输入参数,并通过变量接收
formatted_name = get_formatted_name('janis', 'joplin')
# 通过assertEqual判断测试函数返回的,与实际正确的结果是否一致。
self.assertEqual(formatted_name, 'Janis Joplin')
if __name__ == '__main__':
unittest.main()
执行该脚本
shijianzhongdeMacBook-Pro:Python从入门到实践 shijianzhong$ python3 test_name_function.py . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
一个点表示一个测试方法通过了,第二个是花费的时间,第三个参数为所有的测试方法都通过了。
故意搞错了试试。
def get_formatted_name(first, middle, last):
full_name = first + ' ' + middle + ' ' + last
return full_name.title()
把函数改成三个参数输入的。
运行测试的输出
shijianzhongdeMacBook-Pro:Python从入门到实践 shijianzhong$ python3 test_name_function.py
E
======================================================================
ERROR: test_first_last_name (__main__.NamesTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "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)
测试没通过,就要新办法去修改你的函数,让其通过
def get_formatted_name(first, last, middle=''):
if middle:
full_name = first + ' ' + middle + ' ' + last
else:
full_name = first + ' ' +last
return full_name.title()
改成这样就又可以通过了。
因为这个函数可以接收三个参数,所以原来的测试类上面添加一个测试的方法。
import unittest
from name_function import get_formatted_name
# 编写一个测时类继承unittest.TestCase
class NamesTestCase(unittest.TestCase):
# 定义一个测试的方法,方法名字要以test开头,这样在unittest.main()执行的时候会自动执行
def test_first_last_name(self):
# 调用被测试的函数,输入参数,并通过变量接收
formatted_name = get_formatted_name('janis', 'joplin')
# 通过assertEqual判断测试函数返回的,与实际正确的结果是否一致。
self.assertEqual(formatted_name, 'Janis Joplin')
def test_first_last_middle_name(self):
formatted_name = get_formatted_name(
'wolfgang', 'mozart', 'amadeus'
)
self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')
if __name__ == '__main__':
unittest.main()
返回的结果
shijianzhongdeMacBook-Pro:Python从入门到实践 shijianzhong$ python3 test_name_function.py .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
作业不写了,基本跟书上的一模一样,只不过把名字改成了城市。
测试类。
各种断言方法
self.assertEqual(a,b) 核实 a == b
self.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:
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
question = "What language did you first learn to spaek?"
my_survey = AnonymousSurvey(question)
my_survey.show_question()
print('Enter "q" at any time to quit.
')
while True:
response = input("Language: ")
if response == 'q':
break
my_survey.store_response(response)
print('
Thank you to everyone who participated in the survey!')
my_survey.show_results()
运行脚本显示的情况
/usr/local/bin/python3.7 /Users/shijianzhong/study/测试/Python从入门到实践/language_survey.py What language did you first learn to spaek? Enter "q" at any time to quit. Language: python Language: java Language: js Language: q Thank you to everyone who participated in the survey! Survey result: - python - java - js
编写测试 AnonymousSurvey的类,因为每添加一门语言,在实例的responses属性里面都会多一门,所以测试的时候用了AssertIn()
import unittest
from survey import AnonymousSurvey
# 创建测试类
class TestAnonymousSurvey(unittest.TestCase):
# 首先针对只输入了一门语言的情况
def test_store_single_response(self):
question = "What language did you first learn to spaek?"
my_survey = AnonymousSurvey(question)
# 保存一门语言
my_survey.store_response('English')
# 准备测试,这么语言是否在对象的responses属性里面
self.assertIn('English', my_survey.responses)
if __name__ == '__main__':
unittest.main()
shijianzhongdeMacBook-Pro:Python从入门到实践 shijianzhong$ python3 test_survey.py . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
后面写测试三个答案时候,是否也能妥善保管
import unittest
from survey import AnonymousSurvey
# 创建测试类
class TestAnonymousSurvey(unittest.TestCase):
# 首先针对只输入了一门语言的情况
def test_store_single_response(self):
question = "What language did you first learn to spaek?"
my_survey = AnonymousSurvey(question)
# 保存一门语言
my_survey.store_response('English')
# 准备测试,这么语言是否在对象的responses属性里面
self.assertIn('English', my_survey.responses)
def test_store_three_responses(self):
question = "What language did you first learn to spaek?"
my_survey = AnonymousSurvey(question)
# 答案列表
responses = ['English', 'Spanish', 'Mandarin']
for response in responses:
# 把答案先存起来
my_survey.store_response(response)
for response in responses:
# 测试所有的答案到底在不在实例的responses里面
self.assertIn(response, my_survey.responses)
if __name__ == '__main__':
unittest.main()
shijianzhongdeMacBook-Pro:Python从入门到实践 shijianzhong$ python3 test_survey.py .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
方法setUp()
前面的测试,每次测试都要在测试方法中实例化对象,很蛮烦,所以有了setUp方法,就好比普通类里面的__init__,在每次执行的时候,该方法内的逻辑会先执行。
import unittest
from survey import AnonymousSurvey
# 创建测试类
class TestAnonymousSurvey(unittest.TestCase):
def setUp(self) -> None:
question = "What language did you first learn to spaek?"
# 对象变成实例属性,后面大家可以用
self.survey = AnonymousSurvey(question)
# 答案列表
self.responses = ['English', 'Spanish', 'Mandarin']
# 首先针对只输入了一门语言的情况
def test_store_single_response(self):
# 从答案列表拿一个元素出来,进行存储操作
self.survey.store_response(self.responses[0])
# 准备测试,这么语言是否在对象的responses属性里面
self.assertIn(self.responses[0], self.survey.responses)
def test_store_three_responses(self):
for response in self.responses:
# 把答案先存起来
self.survey.store_response(response)
for response in self.responses:
# 测试所有的答案到底在不在实例的responses里面
self.assertIn(response, self.survey.responses)
if __name__ == '__main__':
unittest.main()
运行结果是一样的。这本书中的学习结束,作业不做了,这个书中的作业太简单了。
从另外一本书上看到,说写函数或者方法之前应该先写测试,这个感觉。。。。。。好苛刻啊。。。。。。