2009-12-02 48 views
2

如果这个标题没有意义(我期待=))这里是我问:断言与自己的单元测试功能输出?

我有一个函数称为ParseFile()。它将一个字符串作为参数,并将一个DataTable作为返回值。

我想单元测试这个功能。首先编写函数,运行它,获取输出,将其序列化为XML,将其保存为预期输出,然后编写单元测试以调用函数并针对反序列化的数据断言,这是错误的吗?

我意识到这有助于我走下坡路,如果我们得到新的输入,我们可能以前没有见过,并且必须更改解析函数来处理它 - 运行我的测试现在会断言我没有打破任何当前工作文件。真棒...

..但在这种情况下,格式将永远不会改变,并且是标准的。那么,我所说的完全没用?如果是,那么如何测试这个功能呢?

而且哎呀,如果我说的仍然是一个好主意 - 你怎么会连做真正的TDD风格和编写测试第一?没有沉闷地为文件中的每个预期字段编写Assert调用()?我并不完全处于TDD'模式' - 但是我试图到达那里......而且这种情况我有时会想知道如何在第一次测试时对它进行测试,当预期输出是一个数据集例如...

感谢

回答

4

这没有错,但它不是TDD。

话虽这么说,我想提醒你有关主张对XML字符串:当出现错误时,XML尺寸足够大,你最终手动比较两个XML字符串中,犯错不错,在视觉上。

在那里,做到了。我记得在这种情况下,将XML复制到两个文件中,将其修改为每行具有一个属性并将两个文件与diff进行比较。我说过我会尝试下次使用XPath和/或XQuery来声明XML。

另外,是不是你的函数做了太多事情:解析字符串生成XML?你可能想考虑把它分开。

你会怎么做到真正的TDD 风格并先写测试?

如果你真的想使用TDD并保留一个函数,那么你可以从一个测试开始:你的XML输出应该是什么样的空字符串?这是你的第一个考验。一旦它通过,用一个简单元素的字符串重新启动,编写测试,使其通过,并采取更复杂的字符串。泡沫,冲洗,重复。

2

这取决于你为什么要编写测试。

从测试驱动开发的角度来看,您描述的过程是错误的。从质量保证的角度来看,它具有很大的意义,因为它为您提供了一个回归测试套件,可以在您前进时充当安全网。

使用TDD开发此类方法的关键是将它们分成更小的块(单元)并单独测试每个块。如果你可以设法把它分成许多小块,那么它通常会产生一个更加灵活和可重用的API,而不是具有一些输入和输出的单一方法。

你如何分割这种方法?

开始思考如何将其组织到私人帮手方法中。然后考虑一下这些辅助方法中的一些(或全部)方法是否可以用一个对象来表示。设计模式如策略抽象工厂在这个意义上可以是非常有用的。

而不是粗粒度的API与很多内部逻辑,你会得到一个细粒度的API与许多公共,但可组合的逻辑。

1

您不应该将您的对象的序列化形式作为测试进行比较。这太具体实现了。你只应该测试界面。

您应该测试DataTable对象的特定属性,例如它有四行,五列,并且该单元[1,2]包含字符串“Fish”。

2

通常我会尽量远离那些“宽泛”的测试功能。我更喜欢测试更细粒度的功能。我假设你的ParseFile()方法使用了几个实用方法,它们本身使用其他实用程序方法。这些是我尝试测试的方法。通常,像这样的任何输入都是由几个不同的数据组成的。与其试图测试整个文件是否被正确解析,你能否浏览一下ParseFile()方法和正在解析的数据,并将它分解成几个较小的测试,这些测试在它们的聚合中给予你相同的信心?

我个人更喜欢这种方法的理由是,如果我需要修改任何解析代码并且测试失败,那么我有更快的路径来找到失败的原因,而不是“ParseFile()没有返回预期的结果“。 :)

3

这似乎更像是黑盒测试比单元测试。但是如果您确定生成的数据集是正确的,那么我不会看到您执行此操作的问题。你是确保数据集不改变未来,我认为这是一个很好的测试,但也许不一定是单元测试

3

我已经在过去使用的测试这样的 - 他们往往是非常有用的。

他们完全不是TDD。我发现我编写这样的测试时,我有更好的没有TDD的代码:Glue Code。你尤其可以看到数据提取(也就是“查询数据库中的这个(现有)数据,以这种方式格式化并发送给客户端。”)你可以使用TDD字段格式化器或其他实用程序对象,但最终所有的事情对于这种类型的代码,如果您为给定(大)输入产生给定(大)输出。将代码翻出来引入测试接缝是不值得的麻烦。

你得到一个单元测试套件中最重要的美德了这种测试的:如果你改变的基本功能共享的一块,它打破了功能,你的测试将变为红色。

有人会说,这不是一个单元测试,因为它不是孤立的。我不在乎。这种区别对我毫无帮助。这个测试为我提供了保证系统正常工作。这让我无需担心就可以对代码库进行更改。