第一部分 测试驱动开发 1
第1章 自动化测试 1
1.1单元测试 1
1.1.1单元测试框架 2
1.1.2 JavaScript期函数strftime 2
1.2断言 5
1.3测试函数、用例和套件 7
1.4集成测试 10
1.5单元测试的好处 12
1.5.1回归测试 12
1.5.2重构 12
1.5.3跨浏览器的测试 13
1.5.4其他的一些好处 13
1.6单元测试中的陷阱 13
1.7小结 13
第2章 测试驱动开发的过程 15
2.1测试驱动开发的目的与目标 15
2.1.1开发顺序的颠倒 15
2.1.2测试驱动开发中的设计 15
2.2过程 16
2.2.1步骤1:编写一个测试 17
2.2.2步骤2:观看测试失败 17
2.2.3步骤3:使测试通过 18
2.2.4步骤4:重构以消除冗余 20
2.2.5打肥皂、冲洗、重复 20
2.3让测试驱动开发简便易行 21
2.4测试驱动开发的好处 21
2.4.1有效的代码 21
2.4.2遵循单一职责原则 22
2.4.3强制有意识的开发 22
2.4.4提高生产效率 22
2.5小结 22
第3章 行业工具 23
3.1 xUnit测试框架 23
3.1.1行为驱动开发 23
3.1.2持续集成 23
3.1.3异步测试 24
3.1.4 xUnit测试框架的特点 24
3.1.5断言 25
3.1.6依赖关系 25
3.2浏览器内的测试框架 26
3.2.1 YUI Test 26
3.2.2其他浏览器内的测试框架 28
3.3无头测试框架 29
3.3.1交叉检查 29
3.3.2 Rhino与env.js 29
3.3.3无头测试框架的缺点 30
3.4一个掌管一切的测试运行器 30
3.4.1 JsTestDriver是怎样工作的 30
3.4.2 JsTestDriver的缺点 31
3.4.3安装 31
3.4.4在IDE里使用JsTestDriver 35
3.4.5提高命令行效率 36
3.4.6断言 37
3.5小结 38
第4章 从测试中学习 39
4.1用单元测试探索JavaScript 39
4.1.1观察法编程的缺陷 41
4.1.2学习测试的最佳点 41
4.2性能测试 42
4.2.1基准和相对性能 43
4.2.2性能评测和定位瓶颈 50
4.3小结 51
第二部分 开发人员的JavaScript 53
第5章 函数 53
5.1定义函数 53
5.1.1函数声明 53
5.1.2函数表达式 54
5.1.3 Function构造器 55
5.2调用函数 56
5.2.1 arguments对象 56
5.2.2形参和arguments 57
5.3作用域和执行上下文 58
5.3.1执行上下文 59
5.3.2变量对象 59
5.3.3活动对象 60
5.3.4全局对象 60
5.3.5作用域链 61
5.3.6再访函数表达式 62
5.4this关键字 64
5.4.1隐式地设置this 65
5.4.2显式地设置this 65
5.4.3使用原初类型当做this 66
5.5小结 67
第6章 函数和闭包的应用 68
6.1绑定函数 68
6.1.1this被丢弃:一个Lightbox的例子 68
6.1.2通过一个匿名函数解决this问题 69
6.1.3 Function.prototype.bind 70
6.1.4绑定参数 71
6.1.5局部套用 73
6.2被立即调用的匿名函数 74
6.2.1 Ad Hoc作用域 74
6.2.2命名空间 76
6.3状态函数 79
6.3.1生成唯一的标识符 79
6.3.2迭代器 81
6.4记忆 84
6.5小结 86
第7章 对象和原型继承 87
7.1对象和属性 87
7.1.1属性访问 88
7.1.2原型链 89
7.1.3通过原型链实现对象扩展 90
7.1.4可枚举属性 91
7.1.5属性的特性 94
7.2使用构造器创建对象 98
7.2.1 prototype和[[Prototype]] 98
7.2.2使用new创建对象 98
7.2.3构造器原型 99
7.2.4构造器的问题 102
7.3伪经典结构的继承 103
7.3.1继承函数 104
7.3.2访问[[Prototype]] 105
7.3.3实现super 105
7.4封装和信息隐藏 110
7.4.1私有方法 110
7.4.2私有成员和特权方法 112
7.4.3函数式继承 113
7.5对象组合和混搭体 115
7.5.1 Object.create方法 115
7.5.2 tddjs.extend方法 117
7.5.3混搭体 120
7.6小结 121
第8章 ECMAScript 5 122
8.1 JavaScript不远的未来 122
8.2对象模型的更新 123
8.2.1属性的特性 123
8.2.2原型继承 125
8.2.3 Getter和Setter 127
8.2.4使用属性的特性 128
8.2.5作为属性标识符的保留关键字 131
8.3严格模式 131
8.3.1启用严格模式 131
8.3.2严格模式带来的改变 132
8.4各种新内容及改进 134
8.4.1原生的JSON 134
8.4.2 Function.prototype.bind 135
8.4.3关于数组 135
8.5小结 135
第9章 不唐突的JavaScript 137
9.1不唐突的JavaScript的目标 137
9.2不唐突的JavaScript的规则 138
9.2.1唐突的标签式面板 138
9.2.2简洁的标签式面板标记 140
9.2.3 TDD和渐进增强 141
9.3不要做任何假设 141
9.3.1不要假设只有你一个人 141
9.3.2不要假设标记是正确的 142
9.3.3不要假设所有用户的需求都一样 142
9.3.4不要假设支持 142
9.4规则何时适用 143
9.5不唐突的标签式面板的例子 143
9.5.1建立测试 143
9.5.2tabController对象 145
9.5.3 activateTab方法 147
9.5.4使用标签控制器 149
9.6小结 152
第10章 特性检测 154
10.1浏览器嗅探 154
10.1.1用户代理嗅探 154
10.1.2对象检测 155
10.1.3浏览器嗅探的状态 156
10.2正确使用对象检测 156
10.2.1检查对象是否存在 156
10.2.2类型检查 157
10.2.3原生和宿主对象 157
10.2.4使用测试样例 160
10.2.5何时测试 161
10.3特性检测DOM事件 161
10.4特性检测CSS属性 163
10.5跨浏览器事件处理例程 164
10.6使用特性检测 167
10.6.1向前进 167
10.6.2无法检测到的特性 167
10.7小结 168
第三部分 JavaScript测试驱动开发实践 169
第11章 观察者模式 169
11.1 JavaScript中的观察者 169
11.1.1观察物库 170
11.1.2设置环境 170
11.2添加观察者 171
11.2.1第一个测试 171
11.2.2重构 173
11.3检查观察者 174
11.3.1测试 175
11.3.2重构 177
11.4通知观察者 177
11.4.1确保观察者被调用 177
11.4.2传递参数 178
11.5错误处理 179
11.5.1添加假的观察者 179
11.5.2有问题的观察者 180
11.5.3记录调用顺序 181
11.6观察任意对象 182
11.6.1让构造器成为过去式 183
11.6.2用对象来替换构造器 185
11.6.3重命名方法 186
11.7观察任意事件 187
11.7.1支持observe中的事件 187
11.7.2支持notify中的事件 188
11.8小结 191
第12章 抽象化浏览器区别:Ajax 192
12.1以测试驱动来开发一个请求API 192
12.1.1发现浏览器的不一致 192
12.1.2开发策略 192
12.1.3目标 193
12.2实现请求接口 193
12.2.1项目布局 193
12.2.2选择接口风格 194
12.3创建一个XMLHttpRequest对象 194
12.3.1第一个测试 194
12.3.2 XMLHttpRequest背景知识 195
12.3.3实现tddjs.ajax.create 196
12.3.4更强的特性检测 197
12.4编写Get请求 198
12.4.1需要一个URL 198
12.4.2为XMLHttpRequest对象创建桩 199
12.4.3处理状态的变化 205
12.4.4处理状态变化 206
12.5使用Ajax API 209
12.5.1集成测试 210
12.5.2测试结果 211
12.5.3微妙的麻烦 212
12.5.4本地请求 213
12.5.5测试状态 214
12.6发出POST请求 217
12.6.1为POST做准备 217
12.6.2发送数据 220
12.6.3设置请求头信息 225
12.7重审请求API 225
12.8小结 229
第13章 使用Ajax和Comet将数据流式化 230
13.1数据轮询 230
13.1.1项目结构 230
13.1.2轮询器:tddjs.ajax.poller 231
13.1.3定时器测试 238
13.1.4可配置的头和回调 242
13.1.5单行接口 245
13.2 Comet 247
13.2.1永不消失的框架 247
13.2.2流式化XMLHttpRequest 248
13.2.3 HTML5 248
13.3长轮询的XMLHttpRequest 248
13.3.1实现长轮询支持 248
13.3.2避免缓存问题 251
13.3.3特性检测 252
13.4 Comet客户端 252
13.4.1消息格式 253
13.4.2介绍ajax.cometClient 254
13.4.3分发数据 255
13.4.4添加观察者 258
13.4.5服务器连接 259
13.4.6跟踪请求和接收到的数据 264
13.4.7发布数据 267
13.4.8特性检测 267
13.5小结 267
第14章 基于Node.js的服务器端JavaS cript 269
14.1 Node js运行时环境 269
14.1.1环境设置 269
14.1.2起点 271
14.2控制器 272
14.2.1 CommonJS规则模块 272
14.2.2定义模块:首测 272
14.2.3建立控制器 273
14.2.4基于POST方式添加消息 274
14.2.5对请求做出响应 280
14.2.6将应用程序用于实践 281
14.3域模型和存储器 283
14.3.1创建聊天室 283
14.3.2 Node中的输入输出 283
14.3.3添加聊天信息 283
14.3.4获取聊天信息 287
14.4 Promises 290
14.4.1用promise重构addMessage方法 291
14.4.2使用promise对象 294
14.5事件产生器 295
14.5.1让chatRoom对象成为一个事件产生器 295
14.5.2等待聊天信息 297
14.6回到控制器 300
14.6.1完成Post方法 300
14.6.2通过GET方法输出数据流 302
14.6.3响应头和响应体 307
14.7小结 308
第15章 TDD与DOM操作:聊天室客户端程序 309
15.1客户端的蓝图 309
15.1.1目录结构 309
15.1.2选择方法 310
15.2用户表单 311
15.2.1视图的设置 311
15.2.2处理提交事件 316
15.2.3特征测试 324
15.3用Node js后端使用客户端 325
15.4聊天信息列表 327
15.4.1设置模型 327
15.4.2设置视图 330
15.4.3添加聊天信息 331
15.4.4来自同一用户的重复内容 334
15.4.5特征测试 335
15.4.6动手实验 335
15.5聊天信息表单 336
15.5.1建立测试用例 337
15.5.2设置视图 337
15.5.3发布聊天信息 339
15.5.4特征测试 342
15.6聊天室客户端的最终版本 343
15.6.1收尾工作 344
15.6.2部署时的注意事项 346
15.7小结 347
第四部分 测试模式 349
第16章 模拟对象和创建桩 349
16.1测试替身概述 349
16.1.1特技替身 349
16.1.2假对象 350
16.1.3哑对象 350
16.2测试验证 351
16.2.1状态验证 351
16.2.2行为验证 351
16.2.3验证策略的作用 352
16.3桩 352
16.3.1使用桩来避免不方便的接口 352
16.3.2使用桩让系统通过特定代码路径 353
16.3.3使用桩来制造麻烦 353
16.4测试间谍 354
16.4.1测试间接输入 354
16.4.2检测调用细节 355
16.5使用桩库 355
16.5.1创建桩函数 355
16.5.2给方法创建桩 356
16.5.3内建行为验证 358
16.5.4创建桩和Node.js 359
16.6模拟对象 360
16.6.1恢复被模拟的函数 360
16.6.2匿名的模拟对象 361
16.6.3多重期望 361
16.6.4对this值的期望 362
16.7模拟对象还是桩 363
16.8小结 364
第17章 编写良好的单元测试 365
17.1提高可读性 365
17.1.1清楚地命名测试以表明意图 365
17.1.2用设置、应用和验证块对测试进行结构化 367
17.1.3使用更高级的抽象保持测试的简单性 367
17.1.4减少重复,而不是减少明确性 369
17.2将测试作为行为规范 370
17.2.1一次只测试一种行为 370
17.2.2每个行为只测试一次 371
17.2.3在测试中隔离行为 371
17.3与测试中的缺陷做斗争 373
17.3.1在测试通过之前运行它们 373
17.3.2首先编写测试 374
17.3.3搅乱和破坏代码 374
17.3.4使用JsLint 374
17.4小结 375
参考文献 376