学习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()
运行结果是一样的。这本书中的学习结束,作业不做了,这个书中的作业太简单了。
从另外一本书上看到,说写函数或者方法之前应该先写测试,这个感觉。。。。。。好苛刻啊。。。。。。