前言 xv
準備工作和應具備的知識 xxi
緻謝 xxvii
第一部分 TDD 和Django 基礎
第1章 使用功能測試協助安裝Django 3
1.1 遵從測試山羊的教誨,沒有測試什麼也彆做 3
1.2 讓Django運行起來 6
1.3 創建Git倉庫 7
第2章 使用unittest模塊擴展功能測試 11
2.1 使用功能測試驅動開發一個最簡可用的應用 11
2.2 Python標準庫中的unittest模塊 14
2.3 隱式等待 16
2.4 提交 16
第3章 使用單元測試測試簡單的首頁 18
3.1 第一個Django應用,第一個單元測試 19
3.2 單元測試及其與功能測試的區彆 19
3.3 Django中的單元測試 20
3.4 Django中的MVC、URL 和視圖函數 21
3.5 終於可以編寫一些應用代碼瞭 22
3.6 urls.py 24
3.7 為視圖編寫單元測試 27
第4章 編寫這些測試有什麼用 31
4.1 編程就像從井裏打水 31
4.2 使用Selenium測試用戶交互 33
4.3 遵守“不測試常量”規則,使用模闆解決這個問題 35
4.4 關於重構 39
4.5 接著修改首頁 40
4.6 總結:TDD流程 42
第5章 保存用戶輸入 45
5.1 編寫錶單,發送POST請求 45
5.2 在服務器中處理POST請求 48
5.3 把Python變量傳入模闆中渲染 49
5.4 事不過三,三則重構 53
5.5 Django ORM和第一個模型 54
5.5.1 第一個數據庫遷移 56
5.5.2 測試嚮前走得挺遠 57
5.5.3 添加新字段就要創建新遷移 57
5.6 把POST請求中的數據存入數據庫 58
5.7 處理完POST請求後重定嚮 61
5.8 在模闆中渲染待辦事項 63
5.9 使用遷移創建生産數據庫 65
第6章 完成最簡可用的網站 70
6.1 確保功能測試之間相互隔離 70
6.2 必要時做少量的設計 74
6.2.1 YAGNI 74
6.2.2 REST 75
6.3 使用TDD 實現新設計 76
6.4 逐步迭代,實現新設計 78
6.5 使用Django測試客戶端一起測試視圖、模闆和URL 80
6.5.1 一個新測試類 80
6.5.2 一個新URL 81
6.5.3 一個新視圖函數 81
6.5.4 一個新模闆,用於查看清單 82
6.6 用於添加待辦事項的URL和視圖 85
6.6.1 用來測試新建清單的測試類 85
6.6.2 用於新建清單的URL和視圖 86
6.6.3 刪除當前多餘的代碼和測試 88
6.6.4 讓錶單指嚮剛添加的新URL 88
6.7 調整模型 89
6.7.1 通過外鍵實現的關聯 91
6.7.2 根據新模型定義調整其他代碼 92
6.8 每個列錶都應該有自己的URL 94
6.8.1 捕獲URL中的參數 95
6.8.2 按照新設計調整new_list視圖 96
6.9 還需要一個視圖,把待辦事項加入現有清單 97
6.9.1 小心霸道的正則錶達式 98
6.9.2 最後一個新URL 98
6.9.3 最後一個新視圖 99
6.9.4 如何在錶單中使用那個URL 100
6.10 使用URL 引入做最後一次重構 102
第二部分 Web開發要素
第7章 美化網站:布局、樣式及其測試方法 106
7.1 如何在功能測試中測試布局和樣式 106
7.2 使用CSS框架美化網站 109
7.3 Django模闆繼承 111
7.4 集成Bootstrap 112
7.5 Django中的靜態文件 114
7.6 使用Bootstrap中的組件改進網站外觀 116
7.6.1 超大文本塊 116
7.6.2 大型輸入框 116
7.6.3 樣式化錶格 117
7.7 使用自己編寫的CSS 117
7.8 補遺:collectstatic命令和其他靜態目錄 118
7.9 沒談到的話題 121
第8章 使用過渡網站測試部署 122
8.1 TDD以及部署的危險區域 123
8.2 一如既往,先寫測試 124
8.3 注冊域名 126
8.4 手動配置托管網站的服務器 126
8.4.1 選擇在哪裏托管網站 127
8.4.2 搭建服務器 127
8.4.3 用戶賬戶、SSH和權限 128
8.4.4 安裝Nginx 128
8.4.5 解析過渡環境和綫上環境所用的域名 129
8.4.6 使用功能測試確認域名可用而且Nginx正在運行 130
8.5 手動部署代碼 130
8.5.1 調整數據庫的位置 131
8.5.2 創建虛擬環境 133
8.5.3 簡單配置Nginx 135
8.5.4 使用遷移創建數據庫 137
8.6 為部署到生産環境做好準備 138
8.6.1 換用Gunicorn 138
8.6.2 讓Nginx伺服靜態文件 139
8.6.3 換用Unix套接字 140
8.6.4 把DEBUG設為False,設置ALLOWED_HOSTS 141
8.6.5 使用Upstart確保引導時啓動Gunicorn 141
8.6.6 保存改動:把Gunicorn 添加到requirements.txt 142
8.7 自動化 143
第9章 使用Fabric自動部署 147
9.1 分析一個Fabric部署腳本 148
9.2 試用部署腳本 151
9.2.1 部署到綫上服務器 153
9.2.2 使用sed配置Nginx 和Gunicorn 155
9.3 使用Git標簽標注發布狀態 155
9.4 延伸閱讀 156
第10章 輸入驗證和測試的組織方式 158
10.1 針對驗證的功能測試:避免提交空待辦事項 158
10.1.1 跳過測試 159
10.1.2 把功能測試分拆到多個文件中 160
10.1.3 運行單個測試文件 162
10.1.4 填充功能測試 163
10.2 使用模型層驗證 164
10.2.1 重構單元測試,分拆成多個文件 164
10.2.2 模型驗證的單元測試和self.assertRaises上下文管理器 165
10.2.3 Django怪異的錶現:保存時不驗證數據 166
10.3 在視圖中顯示模型驗證錯誤 167
10.4 Django模式:在渲染錶單的視圖中處理POST 請求 171
10.4.1 重構:把new_item實現的功能移到view_list 中 172
10.4.2 在view_list 視圖中執行模型驗證 174
10.5 重構:去除硬編碼的URL 176
10.5.1 模闆標簽{% url %} 176
10.5.2 重定嚮時使用get_absolute_url 177
第11章 簡單的錶單 181
11.1 把驗證邏輯移到錶單中 181
11.1.1 使用單元測試探索錶單API 182
11.1.2 換用Django中的ModelForm類 183
11.1.3 測試和定製錶單驗證 184
11.2 在視圖中使用這個錶單 186
11.2.1 在處理GET請求的視圖中使用這個錶單 187
11.2.2 大量查找和替換 189
11.3 在處理POST請求的視圖中使用這個錶單 191
11.3.1 修改new_list視圖的單元測試 191
11.3.2 在視圖中使用這個錶單 192
11.3.3 使用這個錶單在模闆中顯示錯誤消息 193
11.4 在其他視圖中使用這個錶單 194
11.5 使用錶單自帶的save方法 196
第12章 高級錶單 199
12.1 針對重復待辦事項的功能測試 199
12.1.1 在模型層禁止重復 200
12.1.2 題外話:查詢集閤排序和字符串錶示形式 202
12.1.3 重寫舊模型測試 204
12.1.4 保存時確實會顯示完整性錯誤 205
12.2 在視圖層試驗待辦事項重復驗證 206
12.3 處理唯一性驗證的復雜錶單 207
12.4 在清單視圖中使用ExistingListItemForm 209
第13章 試探JavaScript 213
13.1 從功能測試開始 213
13.2 安裝一個基本的JavaScript 測試運行程序 214
13.3 使用jQuery 和<div>固件元素 217
13.4 為想要實現的功能編寫JavaScript單元測試 219
13.5 JavaScript測試在TDD循環中的位置 221
13.6 經驗做法:onload樣闆代碼和命名空間 222
13.7 一些缺憾 223
第14章 部署新代碼 224
14.1 部署到過渡服務器 224
14.2 部署到綫上服務器 225
14.3 如果看到數據庫錯誤該怎麼辦 225
14.4 總結:為這次新發布打上Git 標簽 225
第三部分 高級話題
第15章 用戶認證、集成第三方插件以及JavaScript模擬技術的使用 228
15.1 Mozilla Persona(BrowserID) 229
15.2 探索性編程(又名“探究”) 229
15.2.1 為此次探究新建一個分支 230
15.2.2 前端和JavaScript代碼 230
15.2.3 Browser-ID協議 231
15.2.4 服務器端:自定義認證機製 232
15.3 去掉探究代碼 237
15.3.1 常用Selenium技術:顯式等待 240
15.3.2 刪除探究代碼 241
15.4 涉及外部組件的JavaScript單元測試:首次使用模擬技術 242
15.4.1 整理:全站共用的靜態文件夾 242
15.4.2 什麼是模擬技術,為什麼要模擬,模擬什麼 244
15.4.3 命名空間 244
15.4.4 在initialize函數的單元測試中使用一個簡單的馭件 245
15.4.5 高級模擬技術 250
15.4.6 檢查參數的調用 253
15.4.7 QUnit 中的setup和teardown函數,以及Ajax請求測試 255
15.4.8 深層嵌套迴調函數和測試異步代碼 259
第16章 服務器端認證,在Python中使用模擬技術 262
16.1 探究登錄視圖 262
16.2 在Python代碼中使用模擬技術 263
16.2.1 通過模擬authenticate函數測試視圖 263
16.2.2 確認視圖確實登錄瞭用戶 266
16.3 模擬網絡請求,去除自定義認證後颱中的探究代碼 270
16.3.1 一個if 語句需要一個測試 270
16.3.2 在類上使用patch修飾器 272
16.3.3 進行布爾值比較時要留意馭件 275
16.3.4 需要時創建用戶 276
16.3.5 get_user方法 277
16.4 一個最簡單的自定義用戶模型 279
16.4.1 稍微有點兒失望 280
16.4.2 把測試當作文檔 281
16.4.3 用戶已經通過認證 282
16.5 關鍵時刻:功能測試能通過嗎 283
16.6 完善功能測試,測試退齣功能 284
第17章 測試固件、日誌和服務器端調試 287
17.1 事先創建好會話,跳過登錄過程 287
17.2 實踐是檢驗真理的唯一標準:在過渡服務器中捕獲最後的問題 290
17.2.1 設置日誌 291
17.2.2 修正Persona引起的這個問題 293
17.3 在過渡服務器中管理測試數據庫 295
17.3.1 創建會話的Django管理命令 295
17.3.2 讓功能測試在服務器上運行管理命令 296
17.3.3 使用subprocess模塊完成額外的工作 298
17.4 集成日誌相關的代碼 301
17.5 小結 304
第18章 完成“My Lists”頁麵:由外而內的TDD 305
18.1 對立技術:“由內而外” 305
18.2 為什麼選擇使用“由外而內” 306
18.3 “My Lists”頁麵的功能測試 306
18.4 外層:錶現層和模闆 307
18.5 下移一層到視圖函數(控製器) 308
18.6 使用由外而內技術,再讓一個測試通過 309
18.6.1 快速重組模闆的繼承層級 309
18.6.2 使用模闆設計API 310
18.6.3 移到下一層:視圖嚮模闆中傳入什麼 311
18.7 視圖層的下一個需求:新建清單時應該記錄屬主 312
18.8 下移到模型層 313
第19章 測試隔離和“傾聽測試的心聲” 318
19.1 重溫抉擇時刻:視圖層依賴於尚未編寫的模型代碼 318
19.2 首先嘗試使用馭件實現隔離 319
19.3 傾聽測試的心聲:醜陋的測試錶明需要重構 322
19.4 以完全隔離的方式重寫視圖測試 323
19.4.1 為瞭新測試的健全性,保留之前的整閤測試組件 323
19.4.2 完全隔離的新測試組件 324
19.4.3 站在協作者的角度思考問題 324
19.5 下移到錶單層 328
19.6 下移到模型層 332
19.7 關鍵時刻,以及使用模擬技術的風險 335
19.8 把層與層之間的交互當作“閤約” 336
19.8.1 找齣隱形閤約 337
19.8.2 修正由於疏忽導緻的問題 338
19.9 還缺一個測試 340
19.10 清理:保留哪些整閤測試 340
19.10.1 刪除錶單層多餘的代碼 340
19.10.2 刪除以前實現的視圖 341
19.10.3 刪除視圖層多餘的代碼 342
19.11 總結:什麼時候編寫隔離測試,什麼時候編寫整閤測試 343
19.11.1 以復雜度為準則 344
19.11.2 兩種測試都要寫嗎 344
19.11.3 繼續前行 345
第20章 持續集成 346
20.1 安裝Jenkins 346
20.1.1 Jenkins的安全配置 348
20.1.2 添加需要的插件 348
20.2 設置項目 350
20.3 第一次構建 351
20.4 設置虛擬顯示器,讓功能測試能在無界麵的環境中運行 353
20.5 截圖 355
20.6 一個常見的Selenium問題:條件競爭 358
20.7 使用PhantomJS運行QUnit JavaScript測試 361
20.7.1 安裝node 361
20.7.2 在Jenkins中添加構建步驟 362
20.8 CI 服務器能完成的其他操作 364
第21章 簡單的社會化功能、頁麵模式,以及練習 365
21.1 有多個用戶以及使用addCleanup 的功能測試 365
21.2 實現Selenium交互等待模式 367
21.3 頁麵模式 368
21.4 擴展功能測試測試第二個用戶和“My Lists”頁麵 371
21.5 留給讀者的練習 373
第22章 測試運行速度的快慢和熾熱的岩漿 375
22.1 正題:單元測試除瞭運行速度超快之外還有其他優勢 376
22.1.1 測試運行得越快,開發速度越快 376
22.1.2 神賜的心流狀態 377
22.1.3 速度慢的測試經常不想運行,導緻代碼變壞 377
22.1.4 現在還行,不過隨著時間推移,整閤測試會變得越來越慢 377
22.1.5 彆隻聽我一個人說 377
22.1.6 單元測試能驅使我們實現好的設計 377
22.2 純粹的單元測試有什麼問題 378
22.2.1 隔離的測試難讀也難寫 378
22.2.2 隔離測試不會自動測試集成情況 378
22.2.3 單元測試幾乎不能捕獲意料之外的問題 378
22.2.4 使用馭件的測試可能和實現方式聯係緊密 378
22.2.5 這些問題都可以解決 379
22.3 閤題:我們到底想從測試中得到什麼 379
22.3.1 正確性 379
22.3.2 簡潔可維護的代碼 379
22.3.3 高效的工作流程 379
22.3.4 根據所需的優勢評估測試 379
22.4 架構方案 380
22.4.1 端口和適配器(或六邊形、簡潔)架構 380
22.4.2 函數式核心,命令式外殼 381
22.5 小結 381
遵從測試山羊的教誨 383
附錄A PythonAnywhere 385
附錄B 基於類的Django 視圖 388
附錄C 使用Ansible配置服務器 398
附錄D 測試數據庫遷移 402
附錄E 接下來做什麼 407
附錄F 速查錶 411
附錄G 參考書目 415
作者簡介 416
封麵介紹 416
· · · · · · (
收起)