使用 EUnit 似乎有两种常见的方法:
- 在模块末尾包含测试本身
- 将测试添加到单独的“测试”路径
假设我只对测试特定模块的导出功能感兴趣,那么选择一种方法是否有任何优势或约定?
tl; dr:您通常可以将它们放在源代码的底部而不会弄乱。交错总是很糟糕。编写如此多的测试,以至于您需要一个专门的地方来存放大量特定于测试的代码,这意味着您错误地投入了时间。
打破它会缩短您的源文件,并在某些情况下使事情更容易导航。OTOH,难以导航的源通常是其他更深层次问题的标志。
我发现 Dialyzer 和用户是我真正的错误发现者,除了纯粹的功能性、零副作用代码之外,我还测试了相对较少的实用程序。在纯功能代码的情况下,测试是微不足道的——一旦检查了那种代码,这是一个很好的选择,没有人会再过很长时间重新访问它,如果有的话。在这些情况下,我通常会在最后包含测试,这样如果我们想回去再次找到它们,我就不会丢失它们。我有意识地努力重构,直到我的代码尽可能多地属于这种类型——不是每个人都同意这是值得的。
代码的毛茸茸的部分是副作用位,特别是如果您没有使用 typer 和 Dialyzer 对其进行一些工作以找出您对自己犯下的最重大罪行。所有现实世界中的错误的唯一共同点是它们已经通过了所有测试。我从未发现编写测试所花费的精力与副作用代码中的错误之间存在任何关联。实际上,目前还没有办法正式测试参与者模型协议,而交互通常是剩余的错误所在,而不是隐藏在您已经仔细考虑过的进程中。
具体来说,考虑一下:你宁愿在一个有人花了 X 小时正确打字的系统上工作,还是 X 小时编写和运行测试?我的投票是打字。我并不是说测试不好,我是说它在开发人员时间上很昂贵,并且在纯功能代码之外的实用性有限。纯函数式代码的测试具有明显可识别的限制,往往是微不足道的和小的,因此可以不显眼地驻留在它们所应用的模块的底部。