4

我想使用具有字节数组参数的方法为某些类编写单元测试。总共有大约 100 种方法,数组大小从 5-10 到几百个字节不等。我应该如何生成和存储测试数组?

  1. 我应该手动生成它们还是通过一些生成器代码(也应该进行单元测试)?
  2. 我应该在测试期间在内存中生成它们,还是应该提前生成它们并将它们存储在某个地方?
  3. 在后一种情况下,我应该将它们存储在文件中(即使单元测试不应该触及文件系统),还是应该将它们存储在测试代码本身中(例如,以十六进制格式的字符串,如下所示:“47 08 00 14 等”)?

我开始手动创建它们并将它们以十六进制字符串的形式存储在测试代码中。我用这样的二进制字符串做了很多工作,所以我可以相对容易地阅读它们(“我什至没有看到代码。我看到的只是金发、黑发、红发。”)问题是,这种方法很慢,而且我认为使用自动生成器会导致更易于维护的测试。但是我应该如何测试生成器的输出是否正确?听起来像第 22 条军规……

4

4 回答 4

5

我假设您希望字节实际代表可反序列化的对象,而不仅仅是随机的。一百个字节左右将构成一个小的 base64 编码字符串。您可以将测试输入保存为 base 64 编码字符串,然后测试可以获取正确的输入并将其转换为字节:

    const string someScenario = 
"R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==";

    byte[] bytes = Convert.FromBase64String(someScenario);

您可以通过您的序列化程序预先确定字符串是什么,例如

public string SerializeAsBase64()
{
    var session = new SessionCredentials { SessionKey = Guid.NewGuid() };

    using (var mem = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(mem, session);

        var bytes = mem.ToArray();

        return Convert.ToBase64String(bytes);
    }
}

为了确保它有效,您是否也有一个反序列化器......?序列化然后反序列化然后比较原件是否相等?

于 2013-09-19T02:43:04.353 回答
3

我建议使用 Microsoft的文本模板作为单元测试的生成器。只需将 .tt 文件添加到您的项目并实现生成器。生成在设计时完成(当您保存或更改模板时)并在您的项目中生成一个 .cs 文件。然后可以将您的测试代码作为普通的“手写”代码处理,每个字节数组和方法进行一次测试。

生成器也可以为您的字节数组和预期输出加载定义文件。但是由于它是在设计时完成的,因此您的单元测试没有使用文件系统。

整个 T4 系统真的值得一看:Design-Time Code generation by using T4 Text Templates

...默认情况下它是 VisualStudio 的一部分 - 无需安装任何东西或更改构建脚本。

于 2013-09-18T13:31:06.420 回答
1


我会建议一些方法,但不确定哪一种适合或什至可能适合您,因为在您的案例中没有您使用的方法的示例。
如果您可以提供您的方法的示例并解释其工作原理,那将会很有用。你的 100 多种方法是做什么的?

1)尝试将100多种方法中与字节数组一起使用的逻辑重构并提取为一些辅助方法。这样,辅助方法可以处理字节数组,然后将反序列化的对象传递给 100 个奇数方法,这些方法现在将开始使用对象进行处理。

或者

2)我个人更喜欢在测试方法旁边的代码中使用字节数组,这是您当前采用的方法。也许一些输入组合作为函数的属性(使用 NUnit RowTest 扩展)。这使得单元测试相对独立于其他测试。如果您更改参数,那么只有特定的单元测试会受到影响。
生成器的最大问题是它可能会变得非常复杂,因为它为 100 个奇怪的方法中的每一个返回字节数组的逻辑。对生成器的更改可能会影响您的所有单元测试。

单元测试应该易于维护和独立。通过引入生成器,您正在添加依赖项并增加复杂性。

干杯!

于 2013-09-17T06:13:41.553 回答
1

You can use the generator code to get the byte[] for each test. For example you can have a single method in the Test class that generates the byte[] with random size. Something like this

byte[] GetRandomBytes()
{ 
Random random = new Random();
int randomNumber = random.Next(0, 100);
List<byte> bytes = new List<byte>();
for(int b = 0; b < randomNumber; b++)
    bytes.Add(b);
return bytes.ToArray();
}

The generator code will also be tested with your actual tests as it should also handle the invalid input case(I would assume)

于 2013-09-18T19:05:33.140 回答