【问题标题】:Building combinatorial data with AutoFixture使用 AutoFixture 构建组合数据
【发布时间】:2021-09-01 05:39:41
【问题描述】:

我是 AutoFixture 的新手,特别是在寻找一种创建组合数据的方法。

public class Person
{
    public string Firstname { get; set; }
    public string Lastname { get; set; }
}

var firstnames = new[] { "John", "Jane", ... };
var lastnames = new[] { "Doe", "Smith", ... };

var persons = Fixture.CreateMany<Person>().ToList();

现在我想创建一个包含所有名字和姓氏组合的Person 类列表。有没有办法用 AutoFixture 做到这一点?我找不到这个案例的任何例子。

【问题讨论】:

  • 也许 FsCheck 可以做得更好? fscheck.github.io/FsCheck
  • 您希望Person 的每个请求都是唯一的吗?如果您请求的 Person 实例多于可用的名称组合,您预计会发生什么?
  • @AndreiIvascu 我正在寻找一种工具,它可以一次生成组合数据集,而不是按请求生成。
  • @SerhiiShushliapin 我认为这不是正确的工具,但我会深入研究一下。谢谢!

标签: c# unit-testing autofixture


【解决方案1】:

AutoFixture 没有任何允许创建组合数据的功能。但是,理论上您可以集成一个生成器类,该生成器类创建全名并通过类Person 的扩展实例。

很可能其他工具可以更有效地生成组合数据,但出于演示目的,我们假设您可以使用以下 LINQ 查询生成所有全名组合。

from firstName in firstNames
from lastName in lastNames
select new FullName(firstName, lastName);

您可以将此序列封装到ISpecimenBuilder 中,以保留最后生成的名称对的状态。例如使用IEnumerator

这将允许您在生成 Person 实例时使用此构建器来注入 FirstNameLastName 的值。

您可以查看Gist 了解更多详情。

最后你应该有看起来像这样的测试。

[Fact]
public void GeneratesCombinatorialNames()
{
    var firstNames = new[] {"Jake", "Lana"};
    var lastNames = new[] {"Gates", "Morris"};
    var fixture = new Fixture().Customize(new PersonCustomization(firstNames, lastNames));
    var expected1 = new[]
    {
        new Person("Jake", "Gates"),
        new Person("Jake", "Morris"),
        new Person("Lana", "Gates")
    };
    var expected2 = new[]
    {
        new Person("Lana", "Morris"),
        new Person("Jake", "Gates"),
        new Person("Jake", "Morris")
    };

    var people1 = fixture.CreateMany<Person>();
    var people2 = fixture.CreateMany<Person>();

    Assert.Equal(expected1, people1.ToArray());
    Assert.Equal(expected2, people2.ToArray());
}

【讨论】:

  • 谢谢你的例子!但实际上,我正在寻找一种可以自动生成组合数据集的工具,因此我不必重新编写逻辑。你知道有什么工具可以做到这一点吗?
  • @arkord 我以前不需要这样的工具,但是在 Internet 上快速搜索会发现 several .NET 库可以满足您的要求。我认为最有可能的是combinatorics 库。
  • 谢谢指点,我去看看!