C#+NUnit:带有字节数组参数的单元测试方法

本文关键字:参数 单元 测试方法 数组 字节数 字节 C#+NUnit | 更新日期: 2023-09-27 18:28:58

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

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

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

C#+NUnit:带有字节数组参数的单元测试方法

我假设您希望字节实际上代表可反序列化的对象,而不仅仅是随机的。大约一百个字节将构成一个小的base64编码字符串。您可以将测试输入保存为基本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);
    }
}

为了确保它能工作,你是否也有一个反序列化程序。。。?先序列化再反序列化再比较原始文件是否相等?

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

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

整个T4系统非常值得一看:使用T4文本模板生成设计时代码

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


我建议几种方法,但不确定哪种方法适合您,甚至可能适合您,因为在您的案例中没有方法的例子
如果你能提供一个你的方法的例子并解释它的工作原理,这将是有用的。你的100多种方法是做什么的

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

OR

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

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

干杯

您可以使用生成器代码为每个测试获取byte[]。例如,您可以在Test类中使用一个方法来生成具有随机大小的byte[]。像这样的

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();
}

生成器代码也将与实际测试一起进行测试,因为它还应该处理无效输入情况(我认为)