内容简介
本书从最基础的知识入手,讲解了Web开发的全过程,并展示了如何使用Python做测试驱动开发。这本书由三部分组成。第一部分介绍了测试驱动开发和Django的基础知识,并在每个阶段进行严格的单元测试。第二部分讨论了Web开发的要素,讨论了Web开发过程中不可避免的问题,以及如何通过测试来解决这些问题。第三部分讨论了一些前沿课题,如仿真技术、集成第三方认证系统、Ajax、测试固件和持续集成等。
版本2使用了Python3,从外到内引入了测试驱动的开发流程,对新版本Django进行全面升级。
目录
- 前言xv
- 准备工作和应具备的知识xxi
- 配套视频xxviii
- 致谢xxix
- 第一部分TDD和Django基础
- 第1章使用功能测试协助安装Django2
- 1.1遵从测试山羊的教诲,没有测试什么也别做2
- 1.2让Django运行起来4
- 1.3创建Git仓库6
- 第2章使用unittest模块扩展功能测试10
- 2.1使用功能测试驱动开发一个最简可用的应用10
- 2.2Python标准库中的unittest模块12
- 2.3提交14
- 第3章使用单元测试测试简单的首页16
- 3.1第一个Django应用,第一个单元测试16
- 3.2单元测试及其与功能测试的区别17
- 3.3Django中的单元测试18
- 3.4Django中的MVC、URL和视图函数19
- 3.5终于可以编写一些应用代码了20
- 3.6urls.py22
- 3.7为视图编写单元测试23
- 第4章测试(及重构)的目的28
- 4.1编程就像从井里打水28
- 4.2使用Selenium测试用户交互30
- 4.3遵守“不测试常量”规则,使用模板解决这个问题32
- 4.3.1使用模板重构33
- 4.3.2Django测试客户端35
- 4.4关于重构37
- 4.5接着修改首页38
- 4.6总结:TDD流程39
- 第5章保存用户输入:测试数据库42
- 5.1编写表单,发送POST请求42
- 5.2在服务器中处理POST请求45
- 5.3把Python变量传入模板中渲染46
- 5.4事不过三,三则重构50
- 5.5Django ORM和第一个模型51
- 5.5.1第一个数据库迁移53
- 5.5.2测试向前走得挺远53
- 5.5.3添加新字段就要创建新迁移54
- 5.6把POST请求中的数据存入数据库55
- 5.7处理完POST请求后重定向57
- 5.8在模板中渲染待办事项59
- 5.9使用迁移创建生产数据库61
- 5.10回顾64
- 第6章改进功能测试:确保隔离,去掉含糊的休眠66
- 6.1确保功能测试之间相互隔离66
- 6.2升级Selenium和Geckodriver70
- 6.3隐式等待、显式等待和含糊的time.sleep70
- 第7章步步为营75
- 7.1必要时做少量的设计75
- 7.1.1不要预先做大量设计75
- 7.1.2YAGNI76
- 7.1.3REST(式)76
- 7.2使用TDD实现新设计77
- 7.3确保出现回归测试78
- 7.4逐步迭代,实现新设计80
- 7.5自成一体的第一步:新的URL81
- 7.5.1一个新URL82
- 7.5.2一个新视图函数82
- 7.6变绿了吗?该重构了84
- 7.7再迈一小步:一个新模板,用于查看清单84
- 7.8第三小步:用于添加待办事项的URL86
- 7.8.1用来测试新建清单的测试类87
- 7.8.2用于新建清单的URL和视图88
- 7.8.3删除当前多余的代码和测试89
- 7.8.4出现回归!让表单指向刚添加的新URL89
- 7.9下定决心,调整模型90
- 7.9.1外键关系92
- 7.9.2根据新模型定义调整其他代码93
- 7.10每个列表都应该有自己的URL95
- 7.10.1捕获URL中的参数96
- 7.10.2按照新设计调整new_list视图97
- 7.11功能测试又检测到回归98
- 7.12还需要一个视图,把待办事项加入现有清单99
- 7.12.1小心霸道的正则表达式99
- 7.12.2最后一个新URL100
- 7.12.3最后一个新视图101
- 7.12.4直接测试响应上下文对象102
- 7.13使用URL引入做最后一次重构103
- 第二部分Web 开发要素
- 第8章美化网站:布局、样式及其测试方法108
- 8.1如何在功能测试中测试布局和样式108
- 8.2使用CSS框架美化网站111
- 8.3Django模板继承112
- 8.4集成Bootstrap114
- 8.5Django中的静态文件115
- 8.6使用Bootstrap中的组件改进网站外观117
- 8.6.1超大文本块118
- 8.6.2大型输入框118
- 8.6.3样式化表格118
- 8.7使用自己编写的CSS118
- 8.8补遗:collectstatic命令和其他静态目录120
- 8.9没谈到的话题122
- 第9章使用过渡网站测试部署123
- 9.1TDD以及部署的危险区域124
- 9.2一如既往,先写测试125
- 9.3注册域名127
- 9.4手动配置托管网站的服务器127
- 9.4.1选择在哪里托管网站127
- 9.4.2搭建服务器128
- 9.4.3用户账户、SSH和权限128
- 9.4.4安装Nginx128
- 9.4.5安装Python3.6129
- 9.4.6解析过渡环境和线上环境所用的域名130
- 9.4.7使用功能测试确认域名可用而且Nginx正在运行130
- 9.5手动部署代码130
- 9.5.1调整数据库的位置131
- 9.5.2手动创建虚拟环境,使用requirements.txt133
- 9.5.3简单配置Nginx134
- 9.5.4使用迁移创建数据库136
- 9.6手动部署大功告成137
- 第10章为部署到生产环境做好准备139
- 10.1换用Gunicorn139
- 10.2让Nginx伺服静态文件140
- 10.3换用Unix套接字141
- 10.4把DEBUG设为False,设置ALLOWED_HOSTS142
- 10.5使用Systemd确保引导时启动Gunicorn143
- 10.6考虑自动化144
- 10.7保存进度147
- 第11章使用Fabric自动部署148
- 11.1分析一个Fabric部署脚本149
- 11.1.1分析一个Fabric部署脚本149
- 11.1.2使用Git拉取源码150
- 11.1.3更新settings.py151
- 11.1.4更新虚拟环境151
- 11.1.5需要时迁移数据库152
- 11.2试用部署脚本152
- 11.2.1部署到线上服务器154
- 11.2.2使用sed配置Nginx和Gunicorn155
- 11.3使用Git标签标注发布状态157
- 11.4延伸阅读157
- 第12章输入验证和测试的组织方式159
- 12.1针对验证的功能测试:避免提交空待办事项159
- 12.1.1跳过测试160
- 12.1.2把功能测试分拆到多个文件中161
- 12.1.3运行单个测试文件163
- 12.2功能测试新工具:通用显式等待辅助方法164
- 12.3补完功能测试167
- 12.4重构单元测试,分拆成多个文件168
- 第13章数据库层验证171
- 13.1模型层验证172
- 13.1.1self.assertRaises上下文管理器172
- 13.1.2Django怪异的表现:保存时不验证数据173
- 13.2在视图中显示模型验证错误173
- 13.3Django模式:在渲染表单的视图中处理POST请求177
- 13.3.1重构:把new_item实现的功能移到view_list中178
- 13.3.2在view_list视图中执行模型验证180
- 13.4重构:去除硬编码的URL182
- 13.4.1模板标签{% url %}182
- 13.4.2重定向时使用get_absolute_url183
- 第14章简单的表单186
- 14.1把验证逻辑移到表单中186
- 14.1.1使用单元测试探索表单API187
- 14.1.2换用Django中的ModelForm类188
- 14.1.3测试和定制表单验证189
- 14.2在视图中使用这个表单191
- 14.2.1在处理GET请求的视图中使用这个表单191
- 14.2.2大量查找和替换192
- 14.3在处理POST请求的视图中使用这个表单194
- 14.3.1修改new_list视图的单元测试195
- 14.3.2在视图中使用这个表单196
- 14.3.3使用这个表单在模板中显示错误消息196
- 14.4在其他视图中使用这个表单197
- 14.4.1定义辅助方法,简化测试197
- 14.4.2意想不到的好处:HTML5自带的客户端验证199
- 14.5值得鼓励201
- 14.6这难道不是浪费时间吗201
- 14.7使用表单自带的save方法202
- 第15章高级表单205
- 15.1针对重复待办事项的功能测试205
- 15.1.1在模型层禁止重复206
- 15.1.2题外话:查询集合排序和字符串表示形式208
- 15.1.3重写旧模型测试210
- 15.1.4保存时确实会显示完整性错误211
- 15.2在视图层试验待办事项重复验证212
- 15.3处理唯一性验证的复杂表单213
- 15.4在清单视图中使用ExistingListItemForm215
- 15.5小结:目前所学的Django测试知识217
- 第16章试探JavaScript219
- 16.1从功能测试开始219
- 16.2安装一个基本的JavaScript测试运行程序221
- 16.3使用jQuery和固件元素223
- 16.4为想要实现的功能编写JavaScript单元测试225
- 16.5固件、执行顺序和全局状态:JavaScript测试的重大挑战227
- 16.5.1使用console.log打印调试信息227
- 16.5.2使用初始化函数精确控制执行时229
- 16.6经验做法:onload样板代码和命名空间230
- 16.7JavaScript测试在TDD循环中的位置232
- 16.8一些缺憾232
- 第17章部署新代码234
- 17.1部署到过渡服务器234
- 17.2部署到线上服务器235
- 17.3如果看到数据库错误该怎么办235
- 17.4总结:为这次新发布打上Git标签235
- 第三部分高级话题
- 第18章用户身份验证、探究及去掉探究代码238
- 18.1无密码验证238
- 18.2探索性编程(又名“探究”)239
- 18.2.1为此次探究新建一个分支239
- 18.2.2前端登录UI240
- 18.2.3从Django中发出邮件240
- 18.2.4使用环境变量,避免源码中出现机密信息242
- 18.2.5在数据库中存储令牌243
- 18.2.6自定义身份验证模型243
- 18.2.7结束自定义Django身份验证功能224
- 18.3去掉探究代码248
- 18.4一个极简的自定义用户模型251
- 18.5令牌模型:把电子邮件地址与唯一的ID关联起来254
- 第19章使用驭件测试外部依赖或减少重复257
- 19.1开始之前布好基本管道257
- 19.2自己动手模拟(打猴子补丁)258
- 19.3Python的模拟库261
- 19.3.1使用unittest.patch261
- 19.3.2让测试向前迈一小步263
- 19.3.3测试Django消息框架263
- 19.3.4在HTML中添加消息265
- 19.3.5构建登录URL266
- 19.3.6确认给用户发送了带有令牌的链接267
- 19.4去除自定义的身份验证后端中的探究代码269
- 19.4.1一个if语句需要一个测试269
- 19.4.2get_user方法272
- 19.4.3在登录视图中使用自定义的验证后端273
- 19.5使用驭件的另一个原因:减少重复274
- 19.5.1使用驭件的返回值277
- 19.5.2在类一级上打补丁278
- 19.6关键时刻:功能测试能通过吗279
- 19.7理论上正常,那么实际呢281
- 19.8完善功能测试,测试退出功能283
- 第20章测试固件和一个显式等待装饰器285
- 20.1事先创建好会话,跳过登录过程285
- 20.2显式等待辅助方法最终版:wait装饰器290
- 第21章服务器端调试技术293
- 21.1实践是检验真理的唯一标准:在过渡服务器中捕获最后的问题293
- 21.2在服务器上通过环境变量设定机密信息295
- 21.3调整功能测试,以便通过POP3测试真实的电子邮件296
- 21.4在过渡服务器中管理测试数据库299
- 21.4.1创建会话的Django管理命令300
- 21.4.2让功能测试在服务器上运行管理命令301
- 21.4.3直接在Python代码中使用Fabric302
- 21.4.4回顾:在本地服务器和过渡服务器中创建会话的方式303
- 21.5集成日志相关的代码304
- 21.6小结305
- 第22章完成“My Lists”页面:由外而内的TDD306
- 22.1对立技术:“由内而外”306
- 22.2为什么选择使用“由外而内”307
- 22.3“My Lists”页面的功能测试307
- 22.4外层:表现层和模板309
- 22.5下移一层到视图函数(控制器)309
- 22.6使用由外而内技术,再让一个测试通过310
- 22.6.1快速重组模板的继承层级311
- 22.6.2使用模板设计API311
- 22.6.3移到下一层:视图向模板中传入什么313
- 22.7视图层的下一个需求:新建清单时应该记录属主313
- 22.8下移到模型层315
- 第23章测试隔离和“倾听测试的心声”319
- 23.1重温抉择时刻:视图层依赖于尚未编写的模型代码319
- 23.2首先尝试使用驭件实现隔离320
- 23.3倾听测试的心声:丑陋的测试表明需要重构323
- 23.4以完全隔离的方式重写视图测试323
- 23.4.1为了新测试的健全性,保留之前的整合测试组件324
- 23.4.2完全隔离的新测试组件324
- 23.4.3站在协作者的角度思考问题324
- 23.5下移到表单层329
- 23.6下移到模型层332
- 23.7关键时刻,以及使用模拟技术的风险335
- 23.8把层与层之间的交互当作“合约”336
- 23.8.1找出隐形合约337
- 23.8.2修正由于疏忽导致的问题338
- 23.9还缺一个测试339
- 23.10清理:保留哪些整合测试340
- 23.10.1删除表单层多余的代码340
- 23.10.2删除以前实现的视图341
- 23.10.3删除视图层多余的代码342
- 23.11总结:什么时候编写隔离测试,什么时候编写整合测试343
- 23.11.1以复杂度为准则344
- 23.11.2两种测试都要写吗344
- 23.11.3继续前行344
- 第24章持续集成346
- 24.1安装Jenkins346
- 24.2配置Jenkins347
- 24.2.1首次解锁348
- 24.2.2现在建议安装的插件348
- 24.2.3配置管理员用户348
- 24.2.4添加插件350
- 24.2.5告诉Jenkins到哪里寻找Python3和Xvfb350
- 24.2.6设置HTTPS351
- 24.3设置项目351
- 24.4第一次构建352
- 24.5设置虚拟显示器,让功能测试能在无界面的环境中运行354
- 24.6截图356
- 24.7如有疑问,增加超时试试359
- 24.8使用PhantomJS运行QUnit JavaScript测试359
- 24.8.1安装node359
- 24.8.2在Jenkins中添加构建步骤361
- 24.9CI服务器能完成的其他操作362
- 第25章简单的社会化功能、页面模式以及练习363
- 25.1有多个用户以及使用addCleanup的功能测试363
- 25.2页面模式365
- 25.3扩展功能测试测试第二个用户和“My Lists”页面367
- 25.4留给读者的练习368
- 第26章测试运行速度的快慢和炽热的岩浆371
- 26.1正题:单元测试除了运行速度超快之外还有其他优势372
- 26.1.1测试运行得越快,开发速度越快372
- 26.1.2神赐的心流状态372
- 26.1.3经常不想运行速度慢的测试,导致代码变坏373
- 26.1.4现在还行,不过随着时间推移,整合测试会变得越来越慢373
- 26.1.5别只听我一个人说373
- 26.1.6单元测试能驱使我们实现好的设计373
- 26.2纯粹的单元测试有什么问题373
- 26.2.1隔离的测试难读也难写373
- 26.2.2隔离测试不会自动测试集成情况374
- 26.2.3单元测试几乎不能捕获意料之外的问题374
- 26.2.4使用驭件的测试可能和实现方式联系紧密374
- 26.2.5这些问题都可以解决374
- 26.3合题:我们到底想从测试中得到什么374
- 26.3.1正确性374
- 26.3.2简洁可维护的代码375
- 26.3.3高效的工作流程375
- 26.3.4根据所需的优势评估测试375
- 26.4架构方案375
- 26.4.1端口和适配器(或六边形、简洁)架构376
- 26.4.2函数式核心,命令式外壳377
- 26.5小结377
- 遵从测试山羊的教诲379
- 附录A PythonAnywhere381
- 附录B 基于类的Django 视图385
- 附录C 使用Ansible 配置服务器394
- 附录D 测试数据库迁移398
- 附录E 行为驱动开发403
- 附录F 构建一个REST API:JSON、Ajax 和JavaScript 模拟技术416
- 附录G Django-Rest-Framework433
- 附录H 速查表443
- 附录I 接下来做什么447
- 附录J 示例源码451
- 参考书目453
- 作者简介454
- 封面介绍454
虽然名字叫测试驱动开发,主要关注web项目的测试驱动开发,但是从如何构建一些平时很难构建的测试用例到fabric和anisble,整个CI/裁谈会进程已经涵盖,这真的很好。看完之后,你可以对一个正式的web项目开发过程有一个基本的了解,这比一些xxxinaction的书要好得多。
通过这熟悉了一下web开发和远程部署,对这有了个概念。之前听说19年nginx作者因为和公司的版权纠纷被抓进去了,那会还不知道nginx这么牛批..