您的位置:首页 > 编程语言 > Python开发

《Python编程从入门到实践》学习笔记10(第11章:测试函数)

2019-07-19 15:45 316 查看
原文链接:http://www.cnblogs.com/cathycheng/p/11212541.html

  先说个题外话,第一个例子我用了差不多一个小时,才运出我想要的结果。对于一个菜鸟最烦的就是明明按照书上敲得一模一样,也不报错,就是运不出我想要的结果。菜鸟的学习果然是艰辛的,但我会坚持下去。这边我想说,我最终的解决方法是重启了我的编译器,然后然后然后,它就对了!所以我觉得我有时候真的太轴了,把代码敲了两遍,又不停地自己测试,最终还不如我朋友随嘴说的重开一下。。。不要轴,另辟蹊径,也许是康庄大道。

  笔者后面在做试一试的时候又碰到一样的问题:

  这次不像上次一样幸运,重启编译器两次,不行!复制了参考答案的代码,重新运行,不行!运行之前能运出来的程序,也不行了!重启电脑,还是不行!上网百度了一下,好多人好多说法,其中有一种让我成功运行了。如下图:

上面一行不能省略,虽然我也不知道,我之前没有上面一行,只是重启了编译器怎么就能运行了。但是但是但是,后面想要继续运行就得这么干!

  

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 NamesT
3ff7
estCase(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 的类中使用这些方法。

表11-1 unittest Module中的断言方法
self.assertEqual(a,b)
self.assertNotEqual(a,b)
self.assertTrue(x)
self.assertFalse(x)
self.assertIn(item,list)
self.assertNotIn()

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

转载于:https://www.cnblogs.com/cathycheng/p/11212541.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐