【问题标题】:XUnit custom data attribute executes for every test为每个测试执行 XUnit 自定义数据属性
【发布时间】:2020-03-15 11:34:41
【问题描述】:

我在 xUnit 中有一个自定义数据属性。

public class MyTest : DataAttribute
{
    private readonly int _x;
    private readonly int _y;

    public MyTest(int x, int y)
    {
        _x = x;
        _y = y;
    }

    public override IEnumerable<object[]> GetData(MethodInfo testMethod)
    {
        return new[] { new object[] { _x, _y } };
    }
}

然后我有两个测试

    [Theory]
    [MyTest(100, 200)]
    public void Test1(int x, int y)
    {
        var r = x * y;
        Assert.Equal(20000, r);
    }


    [Theory]
    [MyTest(300, 400)]
    public void Test2(int x, int y)
    {
        var r = x * y;
        Assert.Equal(120000, r);
    }

然后我在MyTest 属性的GetData() 方法中放置断点。然后在测试资源管理器中我右键单击Test1 并单击调试选定的测试。

当我这样做时,我注意到MyTest 属性被执行了两次,分别是Test1Test2。我不确定为什么它也会为Test2 执行?

如果我有更多带有MyTest 属性的测试,那么它会为每个测试执行。 有什么办法可以禁用这种行为?

【问题讨论】:

  • 我怀疑“运行此测试”首先要收集所有可用测试的信息,然后将“我所要求的”与“可用的”进行匹配。
  • MyTest 属性是一个元数据,在运行测试之前会被收集并申请运行测试。
  • 随着测试套件的增长,这种开销变得相当沉重,因为每个测试总是会支付所有使用这种属性修饰的测试的总成本。我不记得 NUnit 测试运行器有这种行为。

标签: c# visual-studio xunit xunit.net


【解决方案1】:

默认情况下,xUnit 在发现任何直接继承自 Xunit.Sdk.DataAttribute 的自定义数据属性期间启用枚举。您可以通过将以下内容添加到您的实现中,为您的自定义数据属性配置此枚举。

[DataDiscoverer("MyNamespace.MyTestDataAttribute+Discoverer", "MyAssemblyFullyQualifiedName")]
public class MyTestDataAttribute : DataAttribute
{
    protected class Discoverer : DataDiscoverer
    {
        public override bool SupportsDiscoveryEnumeration(IAttributeInfo dataAttribute, IMethodInfo testMethod)
        {
            return dataAttribute.GetNamedArgument<bool>(nameof(MyTestDataAttribute.SupportsDiscoveryEnumeration));
        }
    }

    private readonly int _x;
    private readonly int _y;

    /// <summary>
    ///     Returns <c>false</c> if the data attribute wants to skip enumerating data during discovery. This will cause the
    ///     theory to yield a single test case for all data, and the data discovery will be during test execution instead of
    ///     discovery.
    /// </summary>
    public bool SupportsDiscoveryEnumeration { get; set; }

    public MyTest(int x, int y)
    {
        _x = x;
        _y = y;
    }

    public override IEnumerable<object[]> GetData(MethodInfo testMethod)
    {
        return new[] { new object[] { _x, _y } };
    }
}

这会将 xUnit 配置为在发现阶段默认跳过自定义数据属性的数据枚举,而是将发现延迟到执行阶段。

因此,您只需照常实施测试,并在测试执行之前仅选择加入您希望(无论出于何种原因)发现的测试。

[Theory]
[MyTest(100, 200)]
public void Test1(int x, int y)
{
    int r = x * y;
    Assert.Equal(20000, r);
}

[Theory]
[MyTest(300, 400, SupportsDiscoveryEnumeration = true)]
public void Test2(int x, int y)
{
    int r = x * y;
    Assert.Equal(120000, r);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 2018-05-05
    相关资源
    最近更新 更多