目录
译者序
前言
致谢
关于作者
#### 第一部分 测试驱动开发
##### 第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
##### 第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.4 this关键字 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.1 this被丢弃:一个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.2 tabController对象 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测试驱动开发实践
##### 第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的服务器端
JavaScript 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
#### 第四部分 测试模式
##### 第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