如何对发生器/序列化方法进行单元测试?

时间:2014-11-02 07:17:39

标签: unit-testing

我想为序列化方法编写单元测试。通过序列化方法,我指的是将一组数据输出为特殊格式的方法。

例如,一种以XML格式输出数据的方法。 (我用C ++编写,但在每种语言中都是一样的。)

class Generator
{
public:
    std::string serialize();
};

// unit test (pseudo-code)
Generator gen;
// set some data in gen
std::string actual = gen.serialize();
std::string expected = "<xml>...</xml>";
ASSERT_EQUAL(expected, actual);

问题在于单元测试高度依赖于非重要的事情,例如XML格式(换行符)或XML属性的顺序。

使用XML时,前一种方法可行,但它不适用于输出二进制数据的生成器。

那么,测试序列化方法的有效方法是什么?


我的想法如下,但都有严重的缺点。

  • 使用外部库来解析数据(对于专有格式,可能不存在)。
  • 总是编写序列化/反序列化对并组合测试它们(两种方法中的错误可能仍然未被发现)。
  • 将序列化数据存储在外部文件中,并在测试中与它们进行比较(单元测试难以阅读和维护)。

2 个答案:

答案 0 :(得分:1)

这更像是我对该主题的第一次想法的长评论。

我认为你必须看两种不同的场景。您的数据&lt; - &gt;序列化数据关系可以是1:1或1:n。

XML将是一个1:n的关系,在这种关系中,XML代码将具有相当大的自由度,但仍然会再次对同一数据进行反序列化。在这种情况下,在我看来,开发和测试序列化/反序列化是一种可行的方法。如果还有外部库,那么当然可以使用它们。如果没有可用的外部库,那么 - 只要序列化/反序列化 - 产生相同的结果,你可能没有&#34;错误&#34;,但&#34;功能&#34; ...
使用存储的外部数据文件测试反序列化也很有意义,但这不适用于序列化,imho。

看一个1:1的关系,就像把数据放到某个二进制格式一样,你应该在外部文件中找到存储的数据。当然,也总是使用外部库(如果存在)。

我建议一起完成所有这三种方法 - 当然适用。你不应该依赖它们中的任何一个。

答案 1 :(得分:1)

在您询问单元测试时,我假设您已知道序列化器所有详细信息的预期行为。也就是说,您知道要在何处插入换行符和缩进等。

现在的问题是,在每个测试案例中,这些细节中只有一部分是相关的。换句话说,在某些测试中,您想测试正确的缩进,而在某些测试中,您只想确保以正确的方式插入数字。

除了您提供的选项外,我还建议另一种方法:使用正则表达式匹配而不是字符串比较。借助正则表达式,您可以将序列化的字符串减少为各个测试中感兴趣的基本部分。例如,要检查结果字符串是否包含某个数字(例如42),可以将其与^[^0-9]*42[^0-9]*$进行匹配。然后,在此特定测试中将忽略封闭的XML。这样,该测试就可以抵抗序列化中的大量更改。

通过这种方法,您避免了对外部解析库的依赖(嗯,您依赖于正则表达式库,但这在当今许多语言中甚至是标准库的一部分),还可以测试序列化的方面-deserialize无法测试(缩进),您的测试运行速度很快,并且不是特定于操作系统的(与文件系统无关)。