python基础课程系列(十三)

第11章 测试代码
使用 Python 模块 unittest 中的工具来测试代码。
11.1.测试函数
要学习测试,得有要测试的代码。下面是一个简单的函数,它接受名和姓并返回整洁的姓名
-------------------------------------------------------
def get_formatted_name(first, last):
    """Generate a neatly formatted full name."""
    full_name = first + ' ' + last
    return full_name.title()
-------------------------------------------------------
from name_function import get_formatted_name

print('Enter \'q\' at any time to 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('\nNeatly formatted name: ' + formatted_name + '.')
-------------------------------------------------------
Enter 'q' at any time to quit.

Please give me a first name:janis

Please give me a last name:joplin

Neatly formatted name: Janis Joplin.

Please give me a first name:bob

Please give me a last name:dylan

Neatly formatted name: Bob Dylan.

Please give me a first name:q


11.1.1.单元测试和测试用例
单元测试 用于核实函数的某个方面没有问题; 测试用例 是一组单元测试,这些单元测试一起核实函数在各种情形下的
行为都符合要求。良好的测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。 全覆盖式测试 用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖可能很难。通常,最初只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖

11.1.2.可通过的测试
创建测试用例的语法需要一段时间才能习惯,但测试用例创建后,再添加针对函数的单元测试就很简单了。要为函数编写测试用例,可先导入模块 unittest 以及要测试的函数,再创建一个继承 unittest.TestCase 的类,并编写一系列方法对函数行为的不同方面进行测试。
-------------------------------------------------------
import unittest
from name_function import get_formatted_name

class NamesTestCase(unittest.TestCase):
    """测试name_function.py"""
    def test_first_last_name(self):
        """能够正确地处理像Janis Joplin这样的姓名吗?"""
        formatted_name = get_formatted_name('janis', 'joplin')
        self.assertEqual(formatted_name, 'Janis Joplin')

unittest.main()
-------------------------------------------------------
.
-------------------------------------------------------Ran 1 test in 0.032s

OK
-------------------------------------------------------
第 1 行的句点表明有一个测试通过了。接下来的一行指出 Python 运行了一个测试,消耗的时间不到 0.001 秒。最后的 OK 表明该测试用例中的所有单元测试都通过了。

在这里我们使用了 unittest 类最有用的功能之一:一个 断言 方法。断言方法用来核实得到的结果是否与期望的结果一致。我们知道 get_formatted_name() 应返回这样的姓名,即名和姓的首字母为大写,且它们之间有一个空格,因此我们期望 formatted_name 的值为 Janis Joplin 。为检查是否确实如此,我们调用 unittest的方法 assertEqual() ,并向它传递 formatted_name 和 'Janis Joplin' 。代码行self.assertEqual(formatted_name, 'Janis Joplin') 的意思是说: “ 将 formatted_name 的值同字符串 'Janis Joplin' 进行比较,如果它们相等,就万事大吉,如果它们不相等,跟我说一声!”

11.1.3.不能通过的测试
测试未通过时结果是什么样的呢?我们来修改 get_formatted_name() ,使其能够处理中间名,但这样做时,故意让这个函数无法正确地处理像 Janis Joplin 这样只有名和姓的姓名。
-------------------------------------------------------
E
=======================================================
ERROR: test_first_last_name (__main__.NamesTestCase)
能够正确地处理像Janis Joplin这样的姓名吗?
-------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\zjhzyjzhaoc1z\Desktop\新建文件夹\test1.py", line 8, 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.014s

FAILED (errors=1)
-------------------------------------------------------

11.1.4.测试未通过时怎么办
测试未通过时怎么办呢?如果你检查的条件没错,测试通过了意味着函数的行为是对的,而测试未通过意味着你编写的新代码有错。因此,测试未通过时,不要修改测试,而应修复导致测试不能通过的代码:检查刚对函数所做的修改,找出导致函数行为不符合预期的修改。

修改 get_formatted_name() ,将中间名设置为可选的,然后再次运行这个测试用例。如果通过了,我们接着确认这个函数能够妥善地处理中间名。要将中间名设置为可选的,可在函数定义中将形参 middle 移到形参列表末尾,并将其默认值指定为一个空字符串。我们还要添加一个 if 测试,以便根据是否提供了中间名相应地创建姓名
-------------------------------------------------------
def get_formatted_name(first, last, middle=''):
""" 生成整洁的姓名 """
if middle:
full_name = first + ' ' + middle + ' ' + last
else:
full_name = first + ' ' + last
return full_name.title()
-------------------------------------------------------
.
-------------------------------------------------------
Ran 1 test in 0.021s

OK

11.1.5.添加新测试
确定 get_formatted_name() 又能正确地处理简单的姓名后,我们再编写一个测试,用于测试包含中间名的姓名。为此,我们在 NamesTestCase 类中再添加一个方法:
-------------------------------------------------------
import unittest
from name_function import get_formatted_name

class NamesTestCase(unittest.TestCase):
    """测试name_function.py"""
    def test_first_last_name(self):
        """能够正确地处理像Janis Joplin这样的姓名吗?"""
        formatted_name = get_formatted_name('janis', 'joplin')
        self.assertEqual(formatted_name, 'Janis Joplin')

    def test_first_last_middle_name(self):
        """能够准确地处理像Wolfgang Amadeus Mozart这样的姓名吗"""
        formatted_name = get_formatted_name('wolfgang', 'mozart', 'amadeus')
        self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')

unittest.main()
-------------------------------------------------------
..
-------------------------------------------------------
Ran 2 tests in 0.022s

OK

11.2.测试类
在本章前半部分,你编写了针对单个函数的测试,下面来编写针对类的测试。
11.2.1.各种断言方法
Python 在 unittest.TestCase 类中提供了很多断言方法。
方法            用途
assertEqual(a,b)    核实a==b
assertNotEqual(a,b)    核实a!=b
assertTrue(x)        核实x=True
assertFalse(x)        核实x=False
assertIn(item,list)    核实item在list内
assertNotIn(item,list)    核实item不在list内
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值