1.自己动手编写测试1.1.QA团队可以帮助你验证你的代码是否稳定,但千万不要把代码直接丢给他们,然后让他们做所有的测试1.2.避免硬编码的值,不要重复代码1.3.专注于测试基本功能而不是实现细节,这有助于代码库的重构1.3.1.测试代码在重构后仍然可以运行1.4.将测试的依赖项与常规代码的依赖项分开2.避免过度测试2.1.要编写那些在测试失败的时候有意义的测试,不要为了提高代码覆盖率而去提高代码覆盖率2.1.1.测试数据库包装器、第三方类库或基本的变量赋值,即使它们能提高覆盖率指标,也是毫无价值的2.1.2.要专注于那些对代码风险有最大影响的测试2.2.将代码覆盖率作为一个指南,而不是硬性的规则2.2.1.高的代码覆盖率并不能保证正确性2.3.不要为自动生成的代码手动编写测试2.3.1.Web框架2.3.2.脚手架2.3.3.OpenAPI客户端2.4.代码生成器是经过彻底测试的,所以测试自动生成的代码是在浪费时间2.4.1.除非你手动引入对生成文件的修改,在这种情况下,你应该测试它们2.5.把精力集中在最高价值的测试上2.5.1.测试需要时间来编写和维护2.5.2.专注于高价值的测试,可以产生最大的收益2.5.2.1.首先应该关注代码中的高风险的区域2.5.2.2.那些低风险或被废弃的代码并不值得测试3.测试中的确定性3.1.确定性的代码对于相同的输入总是给予相同的输出3.2.非确定性的代码对于相同的输入可以返回不同的结果3.2.1.一个需要在网络套接字上调用远程网络服务的单元测试具有不确定性3.2.1.1.如果网络出现问题,那么测试也会失败3.2.2.测试中的不确定性降低了测试的价值3.3.间歇性的测试失败(被称为拍打测试)是很难重现和调试的3.3.1.它们不会在每次运行时都复现3.3.2.你不知道问题是出在测试本身还是你的代码上3.3.3.拍打测试的结果不能提供有意义的信息,开发人员可能会忽略它们,并因此提交错误的代码3.3.4.间歇性失败的测试应该被禁用或立即修复3.4.非确定性通常是由对休眠、超时和生成随机数的不恰当处理引入的3.4.1.测试中遗留下来的副作用或与远程系统交互也会导致非确定性3.5.种子随机数生成器3.5.1.随机数生成器(random number generators,RNG)必须使用一个值作为种子,这个值决定了你从它那里获取的随机数3.5.2.可用一个常数作为随机数生成器的种子,迫使它每次运行时都能确定地生成相同的序列3.5.2.1.使用常数种子的随机数生成器的测试将总是通过或总是失败3.6.不要在单元测试中调用远程系统3.6.1.远程系统的调用需要网络跳转,这是不稳定的3.6.2.避免远程调用也能保持单元测试的快捷和可移植性3.6.3.通过使用模拟库或重构代码来剔除单元测试中的远程系统调用,从而使远程系统仅在集成测试中被需要3.7.采用注入式时间戳3.7.1.如果处理不当,依赖于特定时间间隔的代码会导致非确定性3.7.2.使用静态的系统时钟方法,如now或sleep,则表明你的代码依赖于时间3.7.3.可以使用注入式时间戳而不是静态时间方法,这样你就可以控制你的代码在测试中获取的时间3.7.3.1.注入式时间戳将让你使用模拟来精确控制测试中的时间流逝3.8.避免使用休眠和超时3.9.记得关闭网络套接字和文件句柄3.9.1.许多测试都会泄露操作系统的资源,因为开发人员认为测试是短暂的,当测试终止时,操作系统自己会清理一切3.9.2.泄露的资源会导致不确定性3.9.3.操作系统对打开的套接字和文件句柄的数量有一个上限,当有太多的资源被泄露时,操作系统就会开始拒绝新的请求3.10.绑定到0端口3.10.1.测试不应该绑定到某个特定的网络端口3.10.2.绑定静态端口会导致不确定性3.10.2.1.在一台计算机上运行良好的测试在另一台计算机上会失败,只是因为端口被占用了3.10.3.将所有测试都绑定到同一端口是一种常见的做法3.10.3.1.这些测试在串行时会运转良好,但是在并行时就会失败3.10.3.2.测试失败将是不确定的,因为测试并不总以相同的顺序执行3.10.4.将网络套接字都绑定到0端口,这将使操作系统需要自动去选择一个开放的端口3.10.4.1.测试可以检索被选中的端口,并在该项测试的剩余部分使用这个端口3.11.生成唯一的文件路径和数据库位置3.11.1.测试不应该写入某一个已经被静态定义好了的位置3.11.2.数据的持久性与网络端口绑定有同样的困境3.11.3.恒定的文件路径和数据库位置会导致测试之间相互干扰3.11.4.应该动态地生成唯一的文件名、目录路径以及数据库或表名3.11.4.1.动态ID可以让测试并行执行,因为它们都会读写到各自的位置3.12.隔离并清理剩余的测试状态3.12.1.不清理测试状态会导致不确定性3.12.2.无论你的测试是否通过,你都必须重置状态,不要让失败的测试“留下残渣”3.13.不要依赖测试顺序3.13.1.测试不应该依赖于特定的执行顺序3.13.2.在每次运行之间重置状态,将防止测试在状态发生突变时相互破坏