先说个题外话,第一个例子我用了差不多一个小时,才运出我想要的结果。对于一个菜鸟最烦的就是明明按照书上敲得一模一样,也不报错,就是运不出我想要的结果。菜鸟的学习果然是艰辛的,但我会坚持下去。这边我想说,我最终的解决方法是重启了我的编译器,然后然后然后,它就对了!所以我觉得我有时候真的太轴了,把代码敲了两遍,又不停地自己测试,最终还不如我朋友随嘴说的重开一下。。。不要轴,另辟蹊径,也许是康庄大道。
笔者后面在做试一试的时候又碰到一样的问题:
这次不像上次一样幸运,重启编译器两次,不行!复制了参考答案的代码,重新运行,不行!运行之前能运出来的程序,也不行了!重启电脑,还是不行!上网百度了一下,好多人好多说法,其中有一种让我成功运行了。如下图:
上面一行不能省略,虽然我也不知道,我之前没有上面一行,只是重启了编译器怎么就能运行了。但是但是但是,后面想要继续运行就得这么干!
11.1 测试函数
11.1.1 单元测试四和测试用例
Python标准库中的模块unittest提供了代码测试的工具。单元测试用于核实函数的某个方面没有问题;测试用例是一组单元测试,这些单元测试一起核实函数在各种情况下的行为都符合要求。全覆盖测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。
11.1.2 可通过的测试
要为函数编写测试用例,可先导入模块unittest 以及要测试的函数,再创建一个集成unittest.TestCase 类,并编写一系列方法对函数行为的不同方面进行测试。
下面是只包含一个方法的测试用例,它检查name_combine()在给定名和姓时能否正确地工作:
import unittest from name import name_combine class NamesTestCase(unittest.TestCase): def test_names(self): """测试""" combined_name = name_combine(‘xiao‘,‘ming‘) self.assertEqual(combined_name,‘Xiao Ming‘) unittest.main()
测试结果:
. ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
测试结果中的句点表明有一个测试通过。接下来的一行指出了Python运行了一个测试,消耗的时间不到0.001秒。最后的OK表明该测试用例中的所有单元测试都通过了。
11.1.3 不能通过的测试
如果将name.py 改成下面这样,这次运行程序test_name时,就会发现测试不能通过。
E ====================================================================== ERROR: test_names (__main__.NamesTestCase) 测试 ---------------------------------------------------------------------- Traceback (most recent call last): File "D:/PycharmProject/Study/test_name.py", line 8, in test_names combined_name = name_combine(‘xiao‘,‘ming‘) TypeError: name_combine() missing 1 required positional argument: ‘last‘ ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (errors=1)
第一行的E表示有一个单元测试导致了错误。接下来指出是NamesTestCase中的 test_names导致了错误。然后,一个标准的traceback指出函数调用name_combine(‘xiao‘,‘ming‘)有问题,少了一个参数。
我们还看到运行了1个单元测试,最后还有一个消息,指出整个测试用例都未通过,因为该运行测试用例时发生了一个错误。
11.1.4 测试未通过时怎么办
如果你检查的条件没有错,测试通过了意味着函数的行为是对的,而测试未通过意味着你编写的新代码有错。因此,测试未通过时,不要修改测试,而应修复导致测试不能通过的代码:检查刚对函数所做的修改,找出导致函数行为不符合预期的修改。
最佳的选择就是让中间名变成可选的:
再次运行test_name.py:
. ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
11.1.5 添加新的测试
确定name_combine()又能正确地处理简单的姓名之后,我们再编写一个测试,用于测试包含中间名的姓名。为此,我们需要添加一个方法:
import unittest from name import name_combine class NamesTestCase(unittest.TestCase): def test_names(self): """测试""" combined_name = name_combine(‘xiao‘,‘ming‘) self.assertEqual(combined_name,‘Xiao Ming‘) def test_middle_name(self): """测试有中间名的名字""" combined_name = name_combine(‘xiao‘, ‘ming‘,‘xiao‘) self.assertEqual(combined_name, ‘Xiao Xiao Ming‘) unittest.main()
测试结果:
.. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
P192-193 动手试一试11-1、11-2 城市国家和人口数量
city_funcition.py def city(cityname, countryname,population = ‘‘): if population: city_country = cityname.title() + "," + countryname.title() + ‘ - population ‘ + str(population) else: city_country = cityname.title() + "," + countryname.title() return city_country
test_cities.py import unittest from city_functions import city class CityTestCase(unittest.TestCase): """测试city_function""" def test_city_country(self): cityinfo = city(‘santiago‘, ‘chile‘) self.assertEqual(cityinfo, ‘Santiago,Chile‘) def test_city_country_pop(self): cityinfo = city(‘santiago‘, ‘chile‘,5000000) self.assertEqual(cityinfo, ‘Santiago,Chile - population 5000000‘) if __name__ ==‘__main__‘: unittest.main()
测试结果:
Ran 2 tests in 0.000s OK
11.2 测试类
11.2.1 各种断言方法
表11-1描述了6个常用的断言方法。使用这些方法可核实返回的值等于或不等于预期的值、返回的值为True或Flase、返回的值在列表中或不在列表中。只能在继承unittest.TestCase 的类中使用这些方法。
self.assertEqual(a,b) |
11.2.2 一个要测试的类
类的测试和函数的测试相似。
创建一个匿名调查的类:
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)
测试 AnonymousSurvey()类:
import unittest from survey import AnonymousSurvey class SurveyTestCase(unittest.TestCase): """测试匿名调查类""" def test_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.responses) def test_three_response(self): """测试三个答案会被妥善处理""" question = "What language did you first learn to speak" my_survey = AnonymousSurvey(question) responses = [‘English‘,‘Spanish‘,‘Chinese‘] for response in responses: my_survey.store_response(response) for response in responses: self.assertIn(response,my_survey.responses) if __name__ ==‘__main__‘: unittest.main()
测试结果:
Ran 2 tests in 0.000s Launching unittests with arguments python -m unittest D:/PycharmProject/Study/test_aurvey.py in D:\PycharmProject\Study OK
11.2.3 方法setUp()
在上面的实例中,我们在每个测试方法中都创建了一个AnonymousSurvey()实例,并在每个方法中都创建了答案。unittest.TestCase类包含setUp()方法,Python将先运行它,再运行各个以test_打头的方法。这样,在你编写的每个测试方法中都可以使用在方法setUp()中创建的对象了。
下面用setUp()来创建一个调查对象和一组答案,供test_three_response()、test_single_response()使用:
import unittest from survey import AnonymousSurvey class SurveyTestCase(unittest.TestCase): """测试匿名调查类""" def setUp(self): """ 创建一个调查对象和一组答案,供使用的测试方法使用 """ question = "What language did you first learn to speak?" self.my_survey = AnonymousSurvey(question) self.responses = [‘English‘, ‘Spanish‘, ‘Chinese‘] def test_single_response(self): """测试单个答案会被妥善地存储""" self.my_survey.store_response(self.responses[0]) self.assertIn(self.responses[0],self.my_survey.responses) def test_three_response(self): """测试三个答案会被妥善处理""" 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()
setUp()方法做了两件事:创建一个调查对象;创建一个答案列表。存储这两样东西的变量名包含前缀self(即存储在属性中),因此可在这个类的任何地方使用。这让两个测试方法都更简单,因为它们都不用创建调查对象和答案。再次运行时,这两个测试都通过了。
p198动手试一试11-3雇员
创建Employee类
class Employee(): def __init__(self,firstname,lastname,wage): self.firstname = firstname self.lastname = lastname self.wage = wage def give_raise(self,increase = 5000): self.wage += increase
测试Employee类:
import unittest from employee import Employee class EmployeeTestCase(unittest.TestCase): """测试Employee类""" def setUp(self): """创建一个employee对象""" self.employee = Employee(firstname=‘xiao‘,lastname=‘ming‘,wage=1000) def test_give_default_raise(self): """薪资默认上升值为5000""" self.employee.give_raise() self.assertEqual(self.employee.wage,6000) def test_give_custom_raise(self): """薪资上升值设置为9000""" self.employee.give_raise(9000) self.assertEqual(self.employee.wage,10000)
测试结果:
Ran 2 tests in 0.001s OK
《Python编程从入门到实践》学习笔记10(第11章:测试函数)
原文:https://www.cnblogs.com/cathycheng/p/11212541.html