繁体   English   中英

在基于TDD的单元测试中处理I / O.

[英]Handle I/O in TDD based unit tests

我正在练习基于Java的TDD并编写一些代码来读取和写入文件。 现在,我对每个场景(读取和写入)进行了大约100次测试,以测试我的代码,每次我创建文件或读取给定文件。 要写入的文件将在临时目录中创建,并在每次测试运行后删除。 但是这种策略产生了大量的I / O,而且我担心在SSD寿命期间。 模拟不是一种选择。

一种可能性是重新编写/写入一次文件,然后针对(静态)数据结构(伪代码)运行我的测试:

private static Object resultData = null;

@BeforeClass
// Read/Write my stuff here
resultData = ....

@Test
// Check my requirements
assertTrue(resultData....);

问题是,我可以改变测试方法中的预期行为,因此我的测试不再是自治的。

你会怎么处理它?

但是这种策略产生了大量的I / O,而且我担心在SSD寿命期间。

你忽略了这一点:对于SSD磁盘 (现在足够标准),DWPD(每天驱动器写入数)为1适用于许多用例。
DWPD测量您可以在其生命的每一天覆盖驱动器的整个大小的次数。
对于500 GO磁盘,DWPD为1意味着理论上您可以在未达到产品保修期限的情况下每天写入500 GO。
而这通常是5到10年。
因此,每个构建(100或更多)创建的一些临时文件几乎没有,但如果你每天执行几百万的构建。

此外,由于这种考虑,你不应该使代码或测试更复杂。
SSD可以让开发人员更简单,而不是更复杂。

话虽如此,在单元测试中避免这么多文件写入仍然是有意义的,因为测试必须快速执行。
您可以更改测试类的API,使其也接受ByteArrayInputStreamByteArrayOutputStream 这样,读取和写入将在内存中工作,而不是在文件系统中。

你会怎么处理它?

我会重构代码,以便使用测试双打(也就是模拟) 一个选项。

具体来说,我希望创建这样的接缝

  1. 实现I / O的代码太简单而不能失败
  2. 所有复杂的代码都不关心I / O的实现方式。

在像java这样的语言中,接缝将是一个接口。 我的I / O代码将实现接口,但本身不会在测试中运行。

相反,测试将使用合适的测试双 - 实现相同接口但实际上不执行写入磁盘。

注意:如果我想要模拟各种写入错误的测试,可能会有几种类型的test double,以确保复杂的逻辑能够正确处理这些错误。

当然,生产代码的组合根将需要创建要使用的“真实”实现的实例。 但是测试的组合根可以选择测试双重或内存文件系统,或者其他任何东西,以确保测试结果是确定性的(顺便说一下,不要咀嚼你的SSD寿命)。

Hoare为我们提供了关于场景背后代码的启发式方法

[构建软件设计]的一种方法是使其变得如此简单以至于显然没有缺陷

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM