Fuel/如何测试你的代码
< Fuel
为什么要编写测试?
- 测试可以帮助你发现代码中的错误。
- 测试可以帮助你编写更好的代码。
- 编写测试用例可以节省你之后的时间。
- 单元测试可以提供关于你代码的即时反馈。
- 测试用例可以记录意图。
以下是一些编写单元测试的指导原则。
- 一个测试单元应该专注于一个微小的功能点,并证明它是正确的。
- 每个测试单元必须完全独立。它们中的每一个都应该能够单独运行,并且在测试套件中运行,无论它们被调用的顺序如何。这条规则的含义是,每个测试都必须加载一个全新的数据集,并且可能需要在之后进行一些清理。这通常由 setUp() 和 tearDown() 方法处理。
- 编写有效测试和无效测试
- 尽量避免使用模拟(mocking)和桩(stubbing),而是优先使用测试参数或属性。如果必须使用模拟和桩,则仅针对小型、稳定、显而易见(或文档化的)API 进行模拟,这样桩更有可能代表未来的现实情况,即使经过重构。
- 在测试结束后彻底检查系统的状态。例如:当部署完成后,应该创建一个通知。正确的测试会检查是否只创建了一个通知,并且它的所有字段都与我们期望的一致。错误的测试会过滤数据库以查找任何成功的通知,并且只要找到任何一个就会通过。
- 测试代码如何处理异常。考虑用户将如何被告知错误。仅仅显示“服务器错误已发生”是不好的做法。
- 例如:测试发送带有破坏系统内部数据(例如,某个地方引发 ValueError)的 PUT 请求。响应状态码不应该是 500。
- 另一个例子:由于临时的网络连接问题,代理无法访问 Nailgun API。
- 明智地进行测试。测试是否可以使用默认参数创建新的通知可能没有意义,但测试在节点发现时是否创建了包含所有属性设置的有效通知对象非常有意义。如果在向 /api/nodes 发送 POST 请求时内存为 None?或者 0?或者某个小于 1 Gb 的数字,它是否会被正确地四舍五入?
- 单元测试也是代码。它必须清晰、结构化,遵循 DRY 和其他代码标准。
- 如果你更改了某个代码单元,拿出一张纸,写下所有使用该单元的其他代码单元。然后找到这些单元的测试,并检查是否有测试用于测试它们之间的交互。如果你发现缺少某个代码单元的测试,无论之前是谁遗漏的,你都必须编写它。
- 花点时间思考你的代码可能以何种方式失败。或者你没有足够关注的地方。把自己想象成一个黑客,提供什么数据来破坏你的代码?为所有这些编写测试。
- 在修复错误时,首先编写失败的单元测试。当错误修复后,测试应该通过。
- 不要在一个单元测试中混合多个检查:使用分离的测试。不要编写迭代器来生成测试。
- 努力使测试运行速度快。如果单个测试需要超过几毫秒才能运行,开发速度会变慢,或者测试不会像期望的那样频繁地运行。在某些情况下,测试无法运行得很快,因为它们需要在一个复杂的数据结构上工作,并且该数据结构必须在每次测试运行时加载。将这些较重的测试放在一个单独的测试套件中,该套件由某个计划任务运行,并根据需要尽可能频繁地运行所有其他测试。
参考文献