读程序员的制胜技笔记05_测试(上) 2023-11-06 06:49 由 躺柒 发表于 #其他 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. 主要目的是在代码被推送到存储库之前检查代码,并发现其中潜在的bug 3.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. 编写测试成为更有效率的开发者 热门相关:高人竟在我身边 高人竟在我身边 我家影后超甜的 大时代1994 神武觉醒