通过使用yield的IEnumerable进行迭代

问题描述

我已经开始对系统进行单元测试,并且使用以下TestData()进行了一系列测试(使用Xunit),一次是一个矢量:

public static IEnumerable<object[]> TestData()
{
   yield return new object[] { true,false };
   yield return new object[] { false,false };
   yield return new object[] { true,true };
   yield return new object[] { false,true };
}

现在我想知道是否有一种方法可以在相同/单个测试中重新使用整个集合。
例如,这是我要设置的测试:

[Theory]
public void CanCheckAllInOneGo()
{
    bool error = false;

    // The foreach does not work
    foreach (var a in TestData())
    {
        error |= doSomething(a[0],a[1]);
    }
            
    Assert.True(error != true,"doSomething() Failed");
} 

注意,为了一次运行一个向量,我以前使用了以下属性

[Theory]
[MemberData(nameof(TestData))]

也许由于“产量”是不可能的。如果没有,您将如何做?谢谢。

解决方法

如果要进行参数化测试,则应使用InlineData属性,如下所示:

null

请参见https://andrewlock.net/creating-parameterised-tests-in-xunit-with-inlinedata-classdata-and-memberdata/

该文章还介绍了如何使用MemberData属性重用测试数据。

undefined

如果您真的想在[事实]测试中使用TestData生成器,那么您就走在正确的轨道上,只是忘了将对象转换回布尔值:

[Theory]
[InlineData(true,false)]
[InlineData(false,false)]
[InlineData(true,true)]
[InlineData(false,true)]
public void CanCheckAllInOneGo(bool value1,bool value2)
{      
    Assert.True(doSomething(value1,value2),"doSomething() failed");
}
,

如果您想使用IEnumerable<_>,则最好使用适当的类型:

public static IEnumerable<Tuple<bool,bool>> TestData()
{
   yield return new Tuple<bool,bool>(true,false);
   yield return new Tuple<bool,bool>(false,true);
   yield return new Tuple<bool,true);
}

[Theory]
public void CanCheckAllInOneGo()
{
    foreach (var a in TestData())
    {
        var error = doSomething(a.Item1,a.Item2);

        Assert.False(error,"doSomething() failed");
    }
} 

如果需要object[],则需要进行一些投射。

public static IEnumerable<object[]> TestData()
{
   yield return new object[] { true,false };
   yield return new object[] { false,false };
   yield return new object[] { true,true };
   yield return new object[] { false,true };
}

[Theory]
public void CanCheckAllInOneGo()
{
    foreach (var a in TestData())
    {
        var x = (bool) a[0];
        var y = (bool) a[1];

        var error = doSomething(x,y);

        Assert.False(error,"doSomething() failed");
    }
}