AutoFixture:如何使用通用测试数据集生成不同的对象?

时间:2019-01-03 09:38:03

标签: c# tdd autofixture

我想测试一个自写的XML解析器,该解析器需要一个XML字符串并返回其模型表示。

T Parse(string content);

我遇到的问题与测试的断言部分有关。因为每次我调用Create<T>()时,它都会生成新的随机数据,在这种情况下,这不是我想要的。我有点需要可以按以下顺序使用的通用测试数据集:

a)生成可以传递给我的解析器的XML字符串

b)使用相同的测试数据集生成模型表示形式

c)比较XML解析器结果与生成的模型表示形式和Assert.AreEqual()

我遇到了Freeze<T>()方法,它听起来“听起来”很适合我的目的。但是我不知道如何使用它。

所以问题是:如何使用通用的测试数据集来生成不同的对象?

这是我当前的方法和静态测试数据生成器类。

public static class TestDataGenerator
{
    public static string GenerateSyntheticXmlTestData<T>(int minOid, int maxOid, int amount = 5)
    {
        var fixture = new Fixture()
        {
            RepeatCount = amount
        };

        fixture.Customizations.Add(new OidGenerator(minOid, maxOid));
        fixture.Customizations.Add(new EnableAllProperties());

        var testData = fixture.Create<T>();

        var serializedXmlTestData = XmlSerializerHelper.Current.SerializeToXmlDocument(testData, Encoding.UTF8);

        return serializedXmlTestData;
    }

    public static ICollection<T> GenerateSyntheticModelTestData<T>(int minOid, int maxOid, int amount = 1)
    {
        var fixture = new Fixture()
        {
            RepeatCount = 1
        };

        fixture.Customizations.Add(new OidGenerator(minOid, maxOid));

        var testData = fixture.CreateMany<T>(amount).ToList();

        return testData;
    }
}

这就是我想测试解析器的方式。我希望清楚我正在努力实现的目标。

[Fact]
public void ShouldParse()
{
    // [...]
    var xmlContent = TestDataGenerator.GenerateSyntheticXmlTestData<MyType>(minOid: 1, maxOid: 100, amount: 5);

    // Here I would like to generate a model object using the same data
    //
    // var modelContent = new Fixture().Create<ModelType>(); 

    var parsedContent = parser.Parse(xmlContent);

    //parsedContent.Should().BeEquivalentTo(modelContet); 
}

2 个答案:

答案 0 :(得分:0)

我不确定100%是否是您要找的东西,但是也许可以为您的XML数据创建具有自定义类型的自定义固定装置?

public class CustomFixture : Fixture
{
    Customize<YourXmlType>(c => c.Without(f => f.XmlStringThatShouldNotBeGenerated));
    Customize<YourXmlType>(c => c.Do(f => f.XmlStringThatShouldNotBeGenerated = "Your shared xml string"));
}

这也可以用c.With代替“不做而做”,但是一段时间前我在一个项目中遇到了问题,上述解决方案对我来说更可靠。

答案 1 :(得分:0)

在测试解析器时,我经常发现从基于属性的测试手册中提取页面最简单。 AutoFixture也可以使用许多对基于属性的测试有用的技术。

进行基于属性的解析逻辑测试时,定义与解析器一起使用的序列化程序通常很有用。也就是说,该函数可以将给定模型转换为解析器解析的格式。在这种情况下,它将是XML序列化程序。

指示AutoFixture(或基于属性的测试库)创建“模型”对象的有效实例通常要比指示其生成有效的XML字符串容易得多。

一旦设置了AutoFixture,就可以让它创建模型的实例,然后序列化模型,然后让解析器解析序​​列化的模型。断言是解析后的模型应该等于输入模型。

Scott Wlaschin将此测试模式称为There and back again。您还可以使用FsCheck查看example of it on my blog

使用AutoFixture,可能看起来像这样:

[Fact]
public void RoundTrippingWorks()
{
    var fixture = new Fixture().Customize(/*...*/);
    var model = fixture.Create<MyModel>();

    string xml = MyXmlSerializer.Serialize(model);
    MyModel actual = MyXmlParser.Parse(xml);

    Assert.Equal(model, actual);
}

(我没有尝试编译它,所以可能会有错别字...)