我最近读了很多关于TDD的内容,但我只看到了一些小例子。
现在我必须从一个(不是大的,但不仅仅是一个单独的类)文件导入器开始,它必须是健壮的,所以它必须检查文件是否存在(在FTP服务器上),如果它不是重新安排自己,不要在文件损坏时崩溃,重新运行等等:一个可以启动的导入器,不需要每天检查日志文件。
所以当开始构建这样的程序时,我从哪里开始使用TDD?
是否处于最低级别,例如实现GetFile()或Reschedule()然后继续工作,或者我首先创建'Controller'并让它首先失败因为我没有设置任何测试文件和所有功能的深入研究?
答案 0 :(得分:2)
由于文件导入器的主要焦点是导入一个应该是您的第一个调用端口的文件(是吗?)。编写测试以确保您能够检索文件。
就个人而言,在开始编码之前,我会使用UML勾画出你想要实现的内容。它将帮助您确定需要写的内容。
答案 1 :(得分:2)
嗯 - 从一开始就开始。第一个可以测试的功能是“它必须检查文件是否存在于FTP服务器上”。我可以考虑至少两个测试用例:文件存在,文件不存在。这是两个测试。那么服务器不存在呢?那应该发生什么呢?好吧,也测试一下。当您描述您的单位应该做什么时,就像您在问题中所做的那样,将描述翻译成测试。
你不想做任何功能,是吗?然后测试所有。编写测试的顺序并不重要(最终)你会想要测试每一位(如果你真的关注TDD,那么在写入该位之前,每一位都会经过测试)。 / p>
答案 2 :(得分:1)
我想我会从我想要完成的事情开始。因此,例如,如果我正在编写某种个人财务软件,我会从以下内容开始:
@Test public void importsTransactionsFromQuicken() { List transactions = new QuickenImporter().importFrom("filename.qfx"); assertSomeStuffAbout(transactions); }
现在,一旦你有了这个工作,你可以重构和模拟文件处理,以避免一些I / O.这可能会导致读取文件的抽象。
接下来,开始寻找其他一些场景。例如,您提供了损坏的文件作为示例。那么,如果文件损坏会发生什么?
@Test public void logsAndRemovesCorruptFiles() { File cf = new CorruptFile(); Logger ls = new LogSpy(); // Note, this might be the refactored interface for after mocking out I/O QuickenImporter qi = new QuickenImporter(cf, ls); List transactions = qi.import(); assertEmptyList(transactions); assertFileWasDeleted(cf); assertCorruptLogEntryWasWritten(ls); }
你可以看到我做了一些重构,包括一些构造函数注入等等,但测试确实推动了下一步。对于“重新安排”功能,它似乎违反了单一责任原则,因此它可能属于另一个类,例如在ImportScheduler
类中。如果是这种情况我知道我想要的导入器行为是什么时候找不到文件,所以我会再做一次测试:
@Test public void doesntReturnAnyTransactionsWhenFileNotPresent() { QuickenImporter qi = new QuickenImporter(new NonExistentFile(), NULL_LOGGER); List transactions = qi.import(); assertEmptyList(transactions); }
现在,为了测试调度组件,我可以为ImportSchedulerTest
编写两个条件的测试用例(当我有文件时,当我没有时)。
希望有所帮助!