Python 测试驱动开发:使用 Django、Selenium 和 JavaScript 进行 Web 编程 第2版 PDF 文档
本书从最基础的知识开始,讲解 Web 开发的整个流程,展示如何使用 Python 做测试驱动开发。本书由三个部分组成。第一部分介绍了测试驱动开发和 Django 的基础知识,并在每个阶段进行严格的单元测试。第二部分讨论了 Web 开发要素,探讨了 Web 开发过程中不可避免的问题,以及如何通过测试解决这些问题。第三部分探讨了一些高级话题,如模拟技术、集成第三方认证系统、Ajax、测试固件以及持续集成等。
第 2 版全部使用 Python 3,并针对新版 Django 全面升级,介绍了由外而内的测试驱动开发流程。
本书适合 Web 开发人员阅读。
我至今仍然处在编程事业的初期。人们说,不管从事什么工作,都要历经从新手到熟手的过程,最终有可能成为大师。我要说的是,我最多算是个熟练的程序员。但我很幸运,在事业的早期阶段就结识了一群测试驱动开发(Test-Driven Development,TDD)的狂热爱好者,这对我的编程事业产生了极大影响,让我迫不及待地想和所有人分享这段经历。可
以说,我很积极地做出了最近这次转变,而且这段学习经历现在还历历在目,我希望能让初学者感同身受。
我在开始学习 Python 时(看的是 Mark Pilgrim 写的 Dive Into Python),偶然知道了 TDD 的概念。我当时就认为:“是的,我绝对知道这个概念的意义所在。”或许你第一次听说 TDD 时也有类似的反应吧。它听起来像是一个非常合理的方案,一个需要养成的非常好的习惯——就像经常刷牙。
目录
前言
准备工作和应具备的知识
致谢
第一部分 TDD 和 Django 基础
第 1 章 使用功能测试协助安装 Django
1.1 遵从测试山羊的教诲,没有测试什么也别做
1.2 让 Django 运行起来
1.3 创建 Git 仓库
第 2 章 使用 unittest 模块扩展功能测试
2.1 使用功能测试驱动开发一个最简可用的应用
2.2 Python 标准库中的 unittest 模块
2.3 提交
第 3 章 使用单元测试测试简单的首页
3.1 第一个 Django 应用,第一个单元测试
3.2 单元测试及其与功能测试的区别
3.3 Django 中的单元测试
3.4 Django 中的 MVC、URL 和视图函数
3.5 终于可以编写一些应用代码了
3.6 urls.py
3.7 为视图编写单元测试
“单元测试/编写代码”循环
第 4 章 测试(及重构)的目的
4.1 编程就像从井里打水
4.2 使用 Selenium 测试用户交互
4.3 遵守“不测试常量”规则,使用模板解决这个问题
4.3.1 使用模板重构
4.3.2 Django 测试客户端
4.4 关于重构
4.5 接着修改首页
4.6 总结:TDD 流程
第 5 章 保存用户输入:测试数据库
5.1 编写表单,发送 POST 请求
5.2 在服务器中处理 POST 请求
5.3 把 Python 变量传入模板中渲染
5.4 事不过三,三则重构
5.5 Django ORM 和第一个模型
5.5.1 第一个数据库迁移
5.5.2 测试向前走得挺远
5.5.3 添加新字段就要创建新迁移
5.6 把 POST 请求中的数据存入数据库
5.7 处理完 POST 请求后重定向
更好的单元测试实践方法:一个测试只测试一件事
5.8 在模板中渲染待办事项
5.9 使用迁移创建生产数据库
5.10 回顾
第 6 章 改进功能测试:确保隔离,去掉含糊的休眠
6.1 确保功能测试之间相互隔离
只运行单元测试
6.2 升级 Selenium 和 Geckodriver
6.3 隐式等待、显式等待和含糊的 time.sleep
第 7 章 步步为营
7.1 必要时做少量的设计
7.1.1 不要预先做大量设计
7.1.2 YAGNI
7.1.3 REST(式)
7.2 使用 TDD 实现新设计
7.3 确保出现回归测试
7.4 逐步迭代,实现新设计
7.5 自成一体的第一步:新的 URL
7.5.1 一个新 URL
7.5.2 一个新视图函数
7.6 变绿了吗?该重构了
7.7 再迈一小步:一个新模板,用于查看清单
7.8 第三小步:用于添加待办事项的 URL
7.8.1 用来测试新建清单的测试类
7.8.2 用于新建清单的 URL 和视图
7.8.3 删除当前多余的代码和测试
7.8.4 出现回归!让表单指向刚添加的新 URL
7.9 下定决心,调整模型
7.9.1 外键关系
7.9.2 根据新模型定义调整其他代码
7.10 每个列表都应该有自己的 URL
7.10.1 捕获 URL 中的参数
7.10.2 按照新设计调整 new_list 视图
7.11 功能测试又检测到回归
7.12 还需要一个视图,把待办事项加入现有清单
7.12.1 小心霸道的正则表达式
7.12.2 最后一个新 URL
7.12.3 最后一个新视图
7.12.4 直接测试响应上下文对象
7.13 使用 URL 引入做最后一次重构
第二部分 Web 开发要素
第 8 章 美化网站:布局、样式及其测试方法
8.1 如何在功能测试中测试布局和样式
8.2 使用 CSS 框架美化网站
8.3 Django 模板继承
8.4 集成 Bootstrap
行和列
8.5 Django 中的静态文件
换用 StaticLiveServerTestCase
8.6 使用 Bootstrap 中的组件改进网站外观
8.6.1 超大文本块
8.6.2 大型输入框
8.6.3 样式化表格
8.7 使用自己编写的 CSS
8.8 补遗:collectstatic 命令和其他静态目录
8.9 没谈到的话题
第 9 章 使用过渡网站测试部署
9.1 TDD 以及部署的危险区域
9.2 一如既往,先写测试
9.3 注册域名
9.4 手动配置托管网站的服务器
9.4.1 选择在哪里托管网站
9.4.2 搭建服务器
9.4.3 用户账户、SSH 和权限
9.4.4 安装 Nginx
9.4.5 安装 Python 3.6
9.4.6 解析过渡环境和线上环境所用的域名
9.4.7 使用功能测试确认域名可用而且 Nginx 正在运行
9.5 手动部署代码
9.5.1 调整数据库的位置
9.5.2 手动创建虚拟环境,使用 requirements.txt
9.5.3 简单配置 Nginx
9.5.4 使用迁移创建数据库
9.6 手动部署大功告成
第 10 章 为部署到生产环境做好准备
10.1 换用 Gunicorn
10.2 让 Nginx 伺服静态文件
10.3 换用 Unix 套接字
10.4 把 DEBUG 设为 False,设置 ALLOWED_HOSTS
10.5 使用 Systemd 确保引导时启动 Gunicorn
保存改动:把 Gunicorn 添加到 requirements.txt
10.6 考虑自动化
保存配置文件的模板
10.7 保存进度
第 11 章 使用 Fabric 自动部署
11.1 分析一个 Fabric 部署脚本
11.1.1 分析一个 Fabric 部署脚本
11.1.2 使用 Git 拉取源码
11.1.3 更新 settings.py
11.1.4 更新虚拟环境
11.1.5 需要时迁移数据库
11.2 试用部署脚本
11.2.1 部署到线上服务器
11.2.2 使用 sed 配置 Nginx 和 Gunicorn
11.3 使用 Git 标签标注发布状态
11.4 延伸阅读
第 12 章 输入验证和测试的组织方式
12.1 针对验证的功能测试:避免提交空待办事项
12.1.1 跳过测试
12.1.2 把功能测试分拆到多个文件中
12.1.3 运行单个测试文件
12.2 功能测试新工具:通用显式等待辅助方法
12.3 补完功能测试
12.4 重构单元测试,分拆成多个文件
第 13 章 数据库层验证
13.1 模型层验证
13.1.1 self.assertRaises 上下文管理器
13.1.2 Django 怪异的表现:保存时不验证数据
13.2 在视图中显示模型验证错误
确保无效的输入值不会存入数据库
13.3 Django 模式:在渲染表单的视图中处理 POST 请求
13.3.1 重构:把 new_item 实现的功能移到 view_list 中
13.3.2 在 view_list 视图中执行模型验证
13.4 重构:去除硬编码的 URL
13.4.1 模板标签{% url %}
13.4.2 重定向时使用 get_absolute_url
第 14 章 简单的表单
14.1 把验证逻辑移到表单中
14.1.1 使用单元测试探索表单 API
14.1.2 换用 Django 中的 ModelForm 类
14.1.3 测试和定制表单验证
14.2 在视图中使用这个表单
14.2.1 在处理 GET 请求的视图中使用这个表单
14.2.2 大量查找和替换
14.3 在处理 POST 请求的视图中使用这个表单
14.3.1 修改 new_list 视图的单元测试
14.3.2 在视图中使用这个表单
14.3.3 使用这个表单在模板中显示错误消息
14.4 在其他视图中使用这个表单
14.4.1 定义辅助方法,简化测试
14.4.2 意想不到的好处:HTML5 自带的客户端验证
14.5 值得鼓励
14.6 这难道不是浪费时间吗
14.7 使用表单自带的 save 方法
第 15 章 高级表单
15.1 针对重复待办事项的功能测试
15.1.1 在模型层禁止重复
15.1.2 题外话:查询集合排序和字符串表示形式
15.1.3 重写旧模型测试
15.1.4 保存时确实会显示完整性错误
15.2 在视图层试验待办事项重复验证
15.3 处理唯一性验证的复杂表单
15.4 在清单视图中使用 ExistingListItemForm
15.5 小结:目前所学的 Django 测试知识
第 16 章 试探 JavaScript
16.1 从功能测试开始
16.2 安装一个基本的 JavaScript 测试运行程序
16.3 使用 jQuery 和<div>固件元素
16.4 为想要实现的功能编写 JavaScript 单元测试
16.5 固件、执行顺序和全局状态:JavaScript 测试的重大挑战
16.5.1 使用 console.log 打印调试信息
16.5.2 使用初始化函数精确控制执行时间
16.6 经验做法:onload 样板代码和命名空间
16.7 JavaScript 测试在 TDD 循环中的位置
16.8 一些缺憾
第 17 章 部署新代码
17.1 部署到过渡服务器
17.2 部署到线上服务器
17.3 如果看到数据库错误该怎么办
17.4 总结:为这次新发布打上 Git 标签
第三部分 高级话题
第 18 章 用户身份验证、探究及去掉探究代码
18.1 无密码验证
18.2 探索性编程(又名“探究”)
18.2.1 为此次探究新建一个分支
18.2.2 前端登录 UI
18.2.3 从 Django 中发出邮件
18.2.4 使用环境变量,避免源码中出现机密信息
18.2.5 在数据库中存储令牌
18.2.6 自定义身份验证模型
18.2.7 结束自定义 Django 身份验证功能
18.3 去掉探究代码
删除探究代码
18.4 一个极简的自定义用户模型
把测试当作文档
18.5 令牌模型:把电子邮件地址与唯一的 ID 关联起来
第 19 章 使用驭件测试外部依赖或减少重复
19.1 开始之前布好基本管道
19.2 自己动手模拟(打猴子补丁)
19.3 Python 的模拟库
19.3.1 使用 unittest.patch
19.3.2 让测试向前迈一小步
19.3.3 测试 Django 消息框架
19.3.4 在 HTML 中添加消息
19.3.5 构建登录 URL
19.3.6 确认给用户发送了带有令牌的链接
19.4 去除自定义的身份验证后端中的探究代码
19.4.1 一个 if 语句需要一个测试
19.4.2 get_user 方法
19.4.3 在登录视图中使用自定义的验证后端
19.5 使用驭件的另一个原因:减少重复
19.5.1 使用驭件的返回值
19.5.2 在类一级上打补丁
19.6 关键时刻:功能测试能通过吗
19.7 理论上正常,那么实际呢
19.8 完善功能测试,测试退出功能
第 20 章 测试固件和一个显式等待装饰器
20.1 事先创建好会话,跳过登录过程
检查是否可行
20.2 显式等待辅助方法最终版:wait 装饰器
第 21 章 服务器端调试技术
21.1 实践是检验真理的唯一标准:在过渡服务器中捕获最后的问题
设置日志
21.2 在服务器上通过环境变量设定机密信息
21.3 调整功能测试,以便通过 POP3 测试真实的电子邮件
21.4 在过渡服务器中管理测试数据库
21.4.1 创建会话的 Django 管理命令
21.4.2 让功能测试在服务器上运行管理命令
21.4.3 直接在 Python 代码中使用 Fabric
21.4.4 回顾:在本地服务器和过渡服务器中创建会话的方式
21.5 集成日志相关的代码
21.6 小结
第 22 章 完成“My Lists”页面:由外而内的 TDD
22.1 对立技术:“由内而外”
22.2 为什么选择使用“由外而内”
22.3 “My Lists”页面的功能测试
22.4 外层:表现层和模板
22.5 下移一层到视图函数(控制器)
22.6 使用由外而内技术,再让一个测试通过
22.6.1 快速重组模板的继承层级
22.6.2 使用模板设计 API
22.6.3 移到下一层:视图向模板中传入什么
22.7 视图层的下一个需求:新建清单时应该记录属主
抉择时刻:测试失败时是否要移入下一层
22.8 下移到模型层
最后一步:实现模板需要的.name 属性
第 23 章 测试隔离和“倾听测试的心声”
23.1 重温抉择时刻:视图层依赖于尚未编写的模型代码
23.2 首先尝试使用驭件实现隔离
使用驭件的 side_effect 属性检查事件发生的顺序
23.3 倾听测试的心声:丑陋的测试表明需要重构
23.4 以完全隔离的方式重写视图测试
23.4.1 为了新测试的健全性,保留之前的整合测试组件
23.4.2 完全隔离的新测试组件
23.4.3 站在协作者的角度思考问题
23.5 下移到表单层
始终倾听测试的心声:从应用中删除 ORM 代码
23.6 下移到模型层
回到视图层
23.7 关键时刻,以及使用模拟技术的风险
23.8 把层与层之间的交互当作“合约”
23.8.1 找出隐形合约
23.8.2 修正由于疏忽导致的问题
23.9 还缺一个测试
23.10 清理:保留哪些整合测试
23.10.1 删除表单层多余的代码
23.10.2 删除以前实现的视图
23.10.3 删除视图层多余的代码
23.11 总结:什么时候编写隔离测试,什么时候编写整合测试
23.11.1 以复杂度为准则
23.11.2 两种测试都要写吗
23.11.3 继续前行
第 24 章 持续集成
24.1 安装 Jenkins
24.2 配置 Jenkins
24.2.1 首次解锁
24.2.2 现在建议安装的插件
24.2.3 配置管理员用户
24.2.4 添加插件
24.2.5 告诉 Jenkins 到哪里寻找 Python 3 和 Xvfb
24.2.6 设置 HTTPS
24.3 设置项目
24.4 第一次构建
24.5 设置虚拟显示器,让功能测试能在无界面的环境中运行
24.6 截图
24.7 如有疑问,增加超时试试
24.8 使用 PhantomJS 运行 QUnit JavaScript 测试
24.8.1 安装 node
24.8.2 在 Jenkins 中添加构建步骤
24.9 CI 服务器能完成的其他操作
第 25 章 简单的社会化功能、页面模式以及练习
25.1 有多个用户以及使用 addCleanup 的功能测试
25.2 页面模式
25.3 扩展功能测试测试第二个用户和“My Lists”页面
25.4 留给读者的练习
第 26 章 测试运行速度的快慢和炽热的岩浆
26.1 正题:单元测试除了运行速度超快之外还有其他优势
26.1.1 测试运行得越快,开发速度越快
26.1.2 神赐的心流状态
26.1.3 经常不想运行速度慢的测试,导致代码变坏
26.1.4 现在还行,不过随着时间推移,整合测试会变得越来越慢
26.1.5 别只听我一个人说
26.1.6 单元测试能驱使我们实现好的设计
26.2 纯粹的单元测试有什么问题
26.2.1 隔离的测试难读也难写
26.2.2 隔离测试不会自动测试集成情况
26.2.3 单元测试几乎不能捕获意料之外的问题
26.2.4 使用驭件的测试可能和实现方式联系紧密
26.2.5 这些问题都可以解决
26.3 合题:我们到底想从测试中得到什么
26.3.1 正确性
26.3.2 简洁可维护的代码
26.3.3 高效的工作流程
26.3.4 根据所需的优势评估测试
26.4 架构方案
26.4.1 端口和适配器(或六边形、简洁)架构
26.4.2 函数式核心,命令式外壳
26.5 小结
扩展阅读
遵从测试山羊的教诲
测试很难
让 CI 构建始终能通过
像重视代码一样重视测试
别忘了给吧台服务员小费
别见外
附录 A PythonAnywhere
A.1 使用 Xvfb 在 Firefox 中运行 Selenium 会话
A.2 以 PythonAnywhere Web 应用的方式安装 Django
A.3 清理/tmp 目录
A.4 截图
A.5 关于部署
附录 B 基于类的 Django 视图
B.1 基于类的通用视图
B.2 使用 FormView 实现首页
B.3 使用 form_valid 定制 CreateView
B.4 一个更复杂的视图,既能查看清单,也能向清单中添加待办事项
B.4.1 测试有指引作用,但时间不长
B.4.2 现在不得不反复实验
B.4.3 测试再次发挥作用
B.4.4 这是最终结果吗
B.5 新旧版对比
B.6 为 CBGV 编写单元测试有最佳实践吗
B.7 记住:编写多个只有一个断言的隔离视图测试有所帮助
附录 C 使用 Ansible 配置服务器
C.1 安装系统包和 Nginx
C.2 配置 Gunicorn,使用处理程序重启服务
C.3 接下来做什么
C.3.1 把 Fabric 执行的部署操作交给 Ansible
C.3.2 使用 Vagrant 搭建本地虚拟主机
附录 D 测试数据库迁移
D.1 尝试部署到过渡服务器
D.2 在本地执行一个用于测试的迁移
D.2.1 输入有问题的数据
D.2.2 从线上网站中复制测试数据
D.2.3 确认的确有问题
D.3 插入一个数据迁移
重新创建以前的迁移
D.4 一起测试这两个迁移
D.5 小结
附录 E 行为驱动开发
E.1 BDD 是什么
E.2 基本的准备工作
E.3 使用 Gherkin 句法以“特性描述”的形式编写功能测试
E.3.1 As-a/I want to/So that
E.3.2 Given/When/Then
E.3.3 并不始终完美契合
E.4 编写步骤函数
生成占位步骤
E.5 定义第一步
E.6 environment.py 中与 setUp 和 tearDown 等价的函数
E.7 再次运行
E.8 在步骤中捕获参数
E.9 与行间式功能测试比较
E.10 BDD 得到的测试代码结构更好
E.11 与页面模式比较
E.12 BDD 可能没有行间注释的表达力强
E.13 非程序员会编写测试吗
E.14 目前的结论
附录 F 构建一个 REST API:JSON、Ajax 和 JavaScript 模拟技术
F.1 本附录采用的方案
F.2 选择测试方案
F.3 基本结构
F.4 返回实质内容
F.5 添加对 POST 请求的支持
F.6 使用 Sinon.js 测试客户端 Ajax
使用 Sinon 测试 Ajax 请求的异步行为
F.7 在模板中连接各部分,确认这样是否真的可行
F.8 实现 Ajax POST,包括 CSRF 令牌
F.9 JavaScript 中的模拟技术
结束重构:让测试与代码匹配
F.10 数据验证:留给读者的练习
附录 G Django-Rest-Framework
G.1 安装
G.2 串化器(具体而言是 ModelSerializer)
G.3 Viewset(具体而言是 ModelViewSet)和路由器
G.4 通过 POST 请求添加待办事项的 URL
G.5 调整客户端代码
G.6 Django-Rest-Framework 的优势
G.6.1 用配置代替代码
G.6.2 自带的功能
附录 H 速查表
H.1 项目开始阶段
H.2 TDD 基本流程
H.3 测试不止要在开发环境中运行
H.4 通用的测试最佳实践
H.5 Selenium/功能测试最佳实践
H.6 由外而内,测试隔离与整合测试,模拟技术
附录 I 接下来做什么
I.1 提醒——站内提醒以及邮件提醒
I.2 换用 Postgres
I.3 在不同的浏览器中运行测试
I.4 400 和 500 测试
I.5 Django 管理后台
I.6 编写一些安全测试
I.7 测试优雅降级
I.8 缓存和性能测试
I.9 JavaScript MVC 框架
I.10 异步和 websocket
I.11 换用 py.test
I.12 试试 coverage.py
I.13 客户端加密
I.14 你的建议
附录 J 示例源码
J.1 使用 Git 检查自己的进度
J.2 下载各章代码的 ZIP 文件
J.3 不要完全依赖我的代码
下载地址:https://www.wenjiangs.com/wp-content/uploads/2024/03/nvyrMfbF6LALqknW.zip
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 测试驱动开发 PDF 文档
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论