1.对测试普遍看法1.1.很乏味,没有人喜欢这样做,而且回报寥寥1.2.对测试人员有一种主观的看法,认为他们的工作太容易了1.3.测试看成项目的外部活动,希望尽量减少1.4.对于测试人员来说,他需要考虑的就是产品的质量2.测试是软件开发工作中不可或缺的一部分2.1.可为开发者的开发保驾护航2.2.能提供其他对你代码的操作所不能提供的保障2.3.能为你节省时间3.测试的类型3.1.测试虽然没法完全保证软件不出错,但是至少能让它在相当大的程度上达到稳定3.2.手动测试3.2.1.由人工手动完成的,但这通常由开发者完成,他们通过运行代码并检查其行为来测试代码3.3.代码审查(code review)3.3.1.主要目的是在代码被推送到存储库之前检查代码,并发现其中潜在的bug3.3.2.最重要的意义是这是你不动手改代码就能审视它的最后机会3.3.3.主要针对代码中可能给其他开发人员带来的bug和技术债3.3.4.其实是一种异步结对编程3.3.5.一段代码通过评审后,就变成了每个人的代码,因为这段代码大家都看过并通过了3.3.6.一种低成本、高效率的方法,可以让所有人达成共识,集中全体注意力去识别那些隐藏的问题3.4.代码分析工具(code analysis tool)3.5.自动化测试3.5.1.你是程序员,你有写代码的天赋,这意味着你可以让计算机为你做事情,其中也包括测试3.5.2.程序员通常只专注于为他们正在开发的软件创建工具,而不是开发过程本身,但过程同样重要3.5.3.最小的是单元测试(unit testing)3.5.3.1.也是最容易编写的3.5.3.2.只测试单个代码单元:公共函数(public function)3.5.3.3.需要是公开的,因为测试应该检查外部可见的接口,而不是类的内部细节3.5.3.4.问题是即便它让你能够知晓单个单元是否正常工作,但是并不能保证所有单元能够正常协同工作3.5.4.集成测试(integration testing)3.5.4.1.测试它们是否同样能很好地协同工作3.5.4.2.如果自动化UI测试是指运行生产代码来构建正确的用户界面,那么这种测试也属于集成测试3.6.生产环境3.6.1.实际用户访问的活动环境,其中任何更改都会影响实际数据3.6.2.生产环境的测试,被认为是一种大忌3.6.2.1.现行代码(live code)3.6.2.2.当你发现故障时,一顿修复,问题消失了,可你的客户或用户也消失了3.6.2.3.生产环境中的测试也有可取的时候。如果你引入的场景并不经常使用,也不是关键的代码路径的一部分,那你可能会在生产环境中进行测试3.6.2.4.如果你觉得放弃这个场景也无所谓,你的客户不会因为这个而放弃整个项目,那你甚至可以不进行代码测试3.7.开发环境3.7.1.作为运行时环境的名称,意味着代码在本地运行,并且不影响任何有损于生产的数据3.8.临时环境(staging)3.8.1.一个生产环境的近似环境3.8.2.它不会影响站点用户可见的实际数据4.选择正确的测试方法4.1.找到一个甜蜜点(sweet spot),让你的成本最低、风险最小4.2.每一个风险都意味着额外付出纠错成本4.3.你可以通过手动测试实现类似于自动化测试的快速迭代周期,只是它需要更多的时间4.4.编写测试能够使你思考你所写的代码,你甚至可以认为这是总结性的练习4.5.自动化测试使你保持状态,并花费你最少的时间4.5.1.编写和运行测试代码是不相干的活动,可能会使你离开这个状态5.要点5.1.采用测试框架5.1.1.使用测试框架的目的是让编写测试代码尽可能容易,但它并不是必需的5.1.2.它们是NASA的飞行前检查灯,是“系统状态名义”公告,是你的小纳米机器人,它们为你工作5.1.3.在测试框架出现之前,另写程序来测试功能代码就是测试程序的唯一方法5.1.4.不依靠测试框架,想要有选择性地运行某些测试,这不太可能5.1.5.利用测试框架可以得到一个代码覆盖率(code-coverage)报告,帮助你发现代码上缺少的内容5.2.避免用扩展方法“污染”代码补全5.2.1.开发者都非常喜欢扩展方法,并倾向于把所有东西都变成扩展方法,而不是静态方法5.2.2.每次你为一个众所周知的类(比如string或者int)写一个扩展方法的时候,你就会把它加入代码自动补全,也就是你在Visual Studio中在标识符后输入一个点时看到的下拉列表5.2.3.不要在常用的.NET类中引入你期望实现功能的方法,只有对那些将被普遍使用的通用方法才推荐你这样做5.2.4.你完全可以使用一个静态类和类似CDN.MakeFilename的语法5.2.5.当你本可以使方法成为类的一部分的时候,不要再去创建扩展方法5.2.6.例如5.2.6.1.你手头上可能有一个Web项目,这个项目使用一个不依赖网络组件库的类5.2.6.2.最好的方法就是只为Web项目中的扩展方法引入一个新的依赖,而不是让库依赖你的Web组件5.3.不要使用TDD或其他缩写5.3.1.测试驱动开发(testing-driven development,TDD)5.3.1.1.TDD的思想是,在编写实际代码之前写测试可以指导你编写更好的代码5.3.1.2.TDD的问题不在于心态,而在于实践,在于仪式化的方法5.3.2.行为驱动开发(behavior-driven development,BDD)5.3.2.1.BDD也是一种测试优先的方法,和TDD在测试的命名和布局上有所不同5.3.3.不可否认,我们喜欢能拿来就用的方法套路,因为那样的话,我们所需要做的就是遵循它们,而不用想太多,但这会花费我们很多时间,让我们讨厌测试5.3.4.先写测试会限制你改变代码的设计5.3.4.1.降低了你在进行原型代码(prototyping code)设计时的灵活性5.3.5.你的思维空间被分配到了写测试的任务、测试框架的行为要素,以及测试的组织,而不是生产代码本身5.3.6.测试的目的应该是帮助你把一段代码写得尽可能简单5.3.6.1.如果不是这样,你就做错了5.4.为你自己的目的写测试5.4.1.最后写测试则可以使代码更加灵活,因为即便后续有重大更改你也可以很从容地进行,而不用提心吊胆,这可算让你解脱了5.4.2.它起到了保险的作用,避免了沉没成本谬论5.4.3.在快速迭代阶段(如原型代码设计阶段)它不会挡你的路5.4.4.测试如果写得足够清晰易懂,你就可以把它当成一种规范或者文档5.4.4.1.通过它的写作逻辑和命名格式来描述一个函数的输入和预期输出5.4.5.测试可以反过来倒逼软件质量和开发者本身技术水平的提高5.4.5.1.编写测试成为更有效率的开发者