Scribe4net - 面向测试的序列化器






4.67/5 (5投票s)
如何仅用 2 行代码断言对象状态
Scribe4net 也在 codeplex 上,欢迎提出修改意见和报告缺陷……
简介
Scrive4net 是一个用于测试场景的简单序列化器。与用于将对象持久化到硬盘或通过网络连接的传统序列化器不同,它没有考虑反序列化回原始对象(因为这不是目的)。主要关注点是人类可读性和对序列化的完全控制。
它填补的需求是,将对象转换为文本形式,以便与标准/预先批准的对象进行比较,或将其批准为标准对象。
- 输出字符串尽可能人类可读,并带有内置格式化。
- 输出是确定性的 = 同一个对象每次都会产生相同的输出字符串。(用于字符串差异比较)
- 为原始类型(包括字符串和日期)生成简单的 ToString 值
- 为包括所有属性的对象生成 xml/json 表示
- 支持选择加入和选择退出
- 支持深度限制
- 处理 List/Array 和 Dictionary 属性(IEnumerable & IDictionary)
- 符合标准的 xml 和 json 格式,因此可以轻松反序列化为工作对象模型。
- 支持序列化任何对象的属性和字段
- 完全控制要序列化的成员类型(public/nonPublic/static/instance)
背景
随着软件项目规模和复杂性的增长,许多项目开始依赖多层自动化测试来及早发现 bug 和回归。单元测试和集成测试是其中的重要组成部分,但它们耗时且编写它们绝不是最受欢迎的编码任务……
我一直在寻找缩短编写测试时间的方法,并遇到了将接收到的对象与预先批准为正确答案的标准对象进行比较(均以文本形式)的概念。这种方法可以用来代替通过代码检查对象的属性并验证其内容。它易于理解和比较,有很多不错的 diff 工具 可以完成这项工作,而且您无需手动编写断言。
这种方法已经可以使用一个名为Approval Tests 的优秀框架,该框架可以加速比较和批准情况的文本表示,但我仍然认为还有些东西缺失:将对象转换为文本形式仍然是手动完成的,需要选择正确的字段集,并创建 getString 和 ToString 函数。对于像树这样的复杂对象怎么办?将它们转换为文本形式需要一些工作,而且您必须为每个类都重新做一遍。
于是我开始编写这个小程序,它是一个用 c# 编写的简单序列化器,以 json 的概念为出发点:所有东西都可以只用字典和列表来表示,而一个对象就是一个字典……
关键在于,您可以完全控制输出的序列化,并且输出是可读的,这样差异就会在 diff 时真正地显现出来。
使用代码
我尽可能地简化了这个类的使用,只需简单地静态调用该函数即可:
string result = TestObjectSerializer.SerializeToString(yourObject, SerializationType.Xml);
当需要更多控制时,可以传递一个附加的设置对象。
SerializationSettings settings = new SerializationSettings()
{
MaxDept = -1,
IncludeFields = true,
FieldInclusion = BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic
};
string result = TestObjectSerializer.SerializeToString(yourObject, SerializationType.Xml, settings);
SerializationSettings 对象包含以下属性:
- MaxDept 让您可以控制序列化器将在对象图中达到的深度,然后再停止。
- Include fields 允许您包含字段(除了属性)。
- FieldInclusion 是一个 BindingFlags 枚举,允许完全控制要包含的字段类型。
- PropertyInclusion 是一个 BindingFlags 枚举,允许完全控制要序列化的属性类型。
- OptIn 是一个布尔值,用于在选择加入和选择退出模式之间切换(默认为 OptOut,其中包含所有属性,除非设置了属性来排除它们)。
要排除属性,可以使用 [TestSerializerOptOut
] 属性:
[TestSerializerOptOut] string YourProperty {get;set;}
要仅包含明确包含的属性,可以使用 [TestSerializerOptIn
] 属性,同时在设置对象中传递 OptIn=true 设置(此项默认为 false):
[TestSerializerOptIn] string YourProperty {get;set;}
可以通过更改 MaxDept 设置来控制序列化深度(-1 表示无限制,也是默认值)。
SerializationSettings settings = new SerializationSettings() { MaxDept = 3, };
现在,对象可以像比较整数和字符串一样简单轻松地进行比较,断言一个复杂情况的正确性现在只需要两行代码:
string result = TestObjectSerializer.SerializeToString(primitive1, SerializationType.Xml); Approvals.Verify(result);
第二行使用了 Approval tests,但也可以轻松地使用 Assert.Equals(strExpected,strReceived)。
结论
我希望这能为大家节省一些测试编写时间…… 告诉我你的想法!