Python 测试驱动开发读书笔记(二)使用unittest框架扩展功能测试

使用功能测试驱动开发一个最简可用的应用

上一节,我们启用了Django,并且用Selenium驱动浏览器,测试了本地地址http://127.0.0.1,因为只是启动了首页,并没有做任何的页面内容,所以首页显示为空白

这节,我们要在Django框架里开发一个Web应用——“一个代办事项清单的网站”,它是一个很简单的由文本字符串组成的列表,可以使用各种方式扩展功能,如使用持久模型、添加最后期限、提醒和分享功能,还可以改进客户端UI

通过这个代办事项,我们学习如何应用TDD理念

在这里插入图片描述
使用功能测试驱动开发一个最简可用的应用

使用Selenium 实现了测试驱动浏览器,让我们能从用户的角度查看应用是如何运作的。因此,我们把这类测试叫作功能测试。这意味着,功能测试在某种程度上可以作为应用的说明书。功能测试的作用是跟踪用户故事(User Story),模拟用户使用某个功能的过程,以及应用应该如何响应用户的操作。

功能测试应该可读、容易理解的故事。为了叙事清楚,可以把测试代码和代码 注释结合起来使用。编写新功能测试时,可以先写注释,勾勒出用户故事的重点。这样写出的测试用例可读,甚至可以作为一种讨论应用需求和功能的方式分享给非程序员看。

TDD 常与敏捷软件开发方法结合在一起使用,我们经常提到的一个概念是“最简可用的应用”,即我们能开发出来的最简单的而且可以使用的应用。下面我们就来开发一个最简可用的应用,尽早试水。

最简可用的待办事项清单其实只要能让用户输入一些待办事项,并且用户下次访问应用时 这些事项还在即可
打开functional_tests.py,开始编写下面的故事

from selenium import webdriver
browser = webdriver.Firefox()

# 小明听说有一个很酷的在线待办事项应用
# 她去看了这个应用的首页
browser.get('http://localhost:8000')

# 她注意到网页的标题和头部都包含“To-Do”这个词
assert 'To-Do' in browser.title

# 应用邀请她输入一个待办事项
# 她在一个文本框中输入了“Buy peacock feathers”(购买孔雀羽毛)
# 伊迪丝的爱好是使用假蝇做饵钓鱼
# 她按回车键后,页面更新了
# 待办事项表格中显示了“1: Buy peacock feathers”
# 页面中又显示了一个文本框,可以输入其他的待办事项
# 她输入了“Use peacock feathers to make a fly”(使用孔雀羽毛做假蝇)
# 伊迪丝做事很有条理
# 页面再次更新,她的清单中显示了这两个待办事项
# 伊迪丝想知道这个网站是否会记住她的清单
# 她看到网站为她生成了一个唯一的URL
# 而且页面中有一些文字解说这个功能
# 她访问那个URL,发现她的待办事项列表还在
# 她很满意,去睡觉了
browser.quit()

除了在测试中加入注释之外,还修改了assert 这行代码,让其查找单词“To-Do”,而不是“Django”。这意味着现在我们期望title返回的是“To-Do”。
启动服务器:

$ python manage.py runserver

然后在另一个shell 中运行测试代码,运行结果报错,

python functional_tests.py 

在这里插入图片描述

Python标准库中的unittest模块

注意: Unittest框架使用方法大家可以参考官方文档或者去介绍Unittest,有简单的框架方法和实例
(Python语言Unitest框架的使用(一)准备工作:https://blog.csdn.net/sevensolo/article/details/98202271)

通过刚才运行,我们发现断言错误
我们需要修改测试代码,使用assert 关键字的第二个参数

assert ‘To-Do’ in browser.title, "Browser title was " + browser.title

这里使用了unittest 框架,代码后面有具体解释

from selenium import webdriver
import unittest


class NewVisitorTest(unittest.TestCase): 
	# 执行之前执行
    def setUp(self):
        self.brower = webdriver.Firefox() # 这里注意Firefox首字母大小写
        
	# 执行完之后执行
    def tearDown(self):
        self.brower.quit()

	# 测试用例
    def test_can_start_a_list_and_retrieve_it_later(self):
        # 伊迪丝听说有一个很酷的在线待办事项应用
        # 她去看了这个应用的首页
        self.brower.get('http://localhost:8000')
        
        # 她注意到网页的标题和头部都包含“To-Do”这个词
        self.assertIn('To-Do', self.brower.title)
        self.fail('Finish the test!')
        
        # 应用邀请她输入一个待办事项
        


if __name__ == '__main__':
        unittest.main(warnings='ignore')

你可能注意到以下几个地方了。
➊ 测试组织成类的形式,继承自unittest.TestCase。
➋ 测试的主要代码写在名为test_can_start_a_list_and_retrieve_it_later 的方法中。名字以test_ 开头的方法都是测试方法,由测试运行程序运行。类中可以定义多个测试方法。为测试方法起个有意义的名字是个好主意。
➌ setUp 和tearDown 是特殊的方法,分别在各个测试方法之前和之后运行。我使用这两个方法打开和关闭浏览器。注意,这两个方法有点类似try/except 语句,就算测试中出错了,也会运行tearDown 方法。1 测试结束后,Firefox 窗口不会一直停留在桌面上了。
➍ 使用self.assertIn 代替assert 编写测试断言。unittest 提供了很多这种用于编写测试断言的辅助函数,如assertEqual、assertTrue 和assertFalse 等。更多断言辅助函数参见unittest 的文档。
➎ 不管怎样,self.fail 都会失败,生成指定的错误消息。我使用这个方法提醒测试结束了。
➏ 最后是if name == ‘main’ 分句(如果你之前没见过这种用法,我告诉你,Python 脚本使用这个语句检查自己是否在命令行中运行,而不是在其他脚本中导入)。我们调用unittest.main() 启动unittest 的测试运行程序,这个程序会在文件中自动查找测试类和方法,然后运行。
➐ warnings=‘ignore’ 的作用是禁止抛出ResourceWarning 异常。写作本书时这个异常会抛出,但你阅读时我可能已经把这个参数去掉了。你可以把这个参数删掉,看一下效果。

继续运行,报错如下图,断言提示未找到”To-Do“,错误先放下
在这里插入图片描述

这样是不是更好了?这个测试清理了Firefox 窗口,显示了一个排版精美的报告,指出运行了几个测试,其中有几个测试失败了,而且assertIn 还显示了一个有利于调试的错误消息。

提交代码

现在是提交代码的好时机,因为已经做了一次完整的修改。我们扩展了功能测试,加入注释说明我们要在最简可用的待办事项清单应用中执行哪些操作。我们还使用Python 中的
unittest 模块及其提供的各种测试辅助函数重写了测试。

执行git status 命令,你会发现只有functional_tests.py 文件的内容变化了

$git status

在这里插入图片描述
执行git diff命令,查看上一次提交和当前硬盘中保存内容之间的差异,你会发现functional_tests.py 文 件的变动很大
$ git diff
在这里插入图片描述
git commit提代码,-a 的意思是:自动添加已跟踪文件(即已经提交的各文件)中的改动

 $ git commit -a

第一行输入本次提交的备注后:wq!保存退出

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sevensolo/article/details/93405546