NUnit:如何从非静态方法传递TestCaseData?

Per*_*zim 8 c# junit nunit unit-testing nunit-3.0

我的测试因以下原因而失败:消息:TestCaseSourceAttribute上指定的sourceName必须引用静态字段,属性或方法.

这是我的代码:

const double MAX_DELTA = 0.01;
Qv_ges qv_ges_NE;
double Sum_Qv_ges_R_FL;
Qv_ges Qv_ges_Quer;

[SetUp]
public void init()
{
    qv_ges_NE = Din1946.Calc_Qv_ges_NE(205.7d);
    Sum_Qv_ges_R_FL = 15d + 15d + 15d + 15d + 15d + 10d + 10d + 10d + 10d + 10d + 10d + 10d;
    Qv_ges_Quer = Din1946.Calc_Qv_ges_Quer(qv_ges_NE, Sum_Qv_ges_R_FL);
}

public IEnumerable<TestCaseData> TestCases_A()
{
        yield return new TestCaseData(72.5, Qv_ges_Quer.FL.Value, MAX_DELTA);
        yield return new TestCaseData(169.17, Qv_ges_Quer.RL.Value, MAX_DELTA);
        yield return new TestCaseData(241.67, Qv_ges_Quer.NL.Value, MAX_DELTA);
        yield return new TestCaseData(314.17, Qv_ges_Quer.IL.Value, MAX_DELTA);
    }


    [TestCaseSource("TestCases_A")]
public void MethodA(double expected, double value, double latitude)
      { Assert.AreEqual(expected, value, latitude);}
Run Code Online (Sandbox Code Playgroud)

我只使用静态测试用例方法,但现在我需要数据: Qv_ges_Quer.IL.Value,Qv_ges_Quer.FL.Value....所以我删除了静态

我如何使用非静态测试用例?我还通过调试注意到它最初没有进入SetUp

这是我想要重新设置的旧代码,mybe你知道另一个/更好的方式然后上面的方式:

public void MethodA(){
  Qv_ges qv_ges_NE = Din1946.Calc_Qv_ges_NE(205.7d);

  double Sum_Qv_ges_R_FL = 15d + 15d + 15d + 15d + 15d + 10d + 10d + 10d + 10d + 10d + 10d + 10d;
  Qv_ges Qv_ges_Quer = Din1946.Calc_Qv_ges_Quer(qv_ges_NE, Sum_Qv_ges_R_FL);

  Assert.AreEqual(72.5, Qv_ges_Quer.FL.Value, MAX_DELTA);
  Assert.AreEqual(169.17, Qv_ges_Quer.RL.Value, MAX_DELTA);
  Assert.AreEqual(241.67, Qv_ges_Quer.NL.Value, MAX_DELTA);
  Assert.AreEqual(314.17, Qv_ges_Quer.IL.Value, MAX_DELTA);
}
Run Code Online (Sandbox Code Playgroud)

met*_*tal 11

???僵尸反应,但迟到总比不到好。

实现此目的的另一种方法是让您的测试用例数据源返回一个函数对象,该对象接受您需要的非静态成员作为其参数。然后您的测试调用它来创建您希望 NUnit 可以传递给您的数据。

在你的情况下,这看起来像:

private static IEnumerable<TestCaseData> GetTestDataA()
{
    yield return new TestCaseData(72.5,   new Func<Qv_ges, double>( qvGesQuer => qvGesQuer.FL.Value ), MAX_DELTA);
    yield return new TestCaseData(169.17, new Func<Qv_ges, double>( qvGesQuer => qvGesQuer.RL.Value ), MAX_DELTA);
    yield return new TestCaseData(241.67, new Func<Qv_ges, double>( qvGesQuer => qvGesQuer.NL.Value ), MAX_DELTA);
    yield return new TestCaseData(314.17, new Func<Qv_ges, double>( qvGesQuer => qvGesQuer.IL.Value ), MAX_DELTA);
}

[TestCaseSource( nameof(GetTestDataA) )]
public void MethodA( double expected, Func<Qv_ges, double> getValue, double latitude)
{ 
    Assert.AreEqual( expected, getValue( Qv_ges_Quer ), latitude );
}
Run Code Online (Sandbox Code Playgroud)

如果您需要多个参数,请将它们添加到函子和 lambda 的参数中,或者考虑传入this。如果需要多个返回值,让函数对象返回一个元组:

new Func<Qv_ges, (double, double)>( qvGesQuer => (qvGesQuer.RL.Value, qvGesQuer.IL.Value) )
Run Code Online (Sandbox Code Playgroud)

另一种方法是传入nameof()字符串作为测试参数并使用反射来获取这些参数的值。


Cha*_*lie 7

按照设计,TestCaseSourceAttribute使用的方法,属性或字段必须是静态的.这是为了避免在加载测试时实例化fixture类.你的夹具只在我们开始运行时被实例化 - 在GUI的情况下,每次我们开始运行 - 它的寿命只有运行夹具所需的时间.

在您的情况下,您似乎已经发现可以使用静态方法.如果可能的话,这是最好的.

这里使用实例方法的唯一方法是使用构造函数TestCaseSourceAttribute(Type sourceType),其中sourceType实现IEnumerable并直接返回测试用例数据.如果您使用此功能,我建议您使用TestFixture中的其他类.这不是绝对必要的.如果使用相同的类,则将在加载时和运行时创建不同的实例,这些实例彼此之间没有任何连接.许多开发人员最终都对此感到困惑,并试图在加载时将状态置于测试之后.那不行.

  • 我们曾经有很多 TestCaseSources,它们使用测试装置的 TestData 属性来定位测试用例文件集。把这个逻辑带出来并不容易。这过去在 NUnit2 中几乎可以正常工作(除了不需要的测试用例源被调用以用于甚至不打算在此会话中运行的测试),这是迁移到 NUnit3 的重大变化。 (2认同)
  • 最糟糕的是,当TestCaseSource调用一个在派生类中重写的虚方法时.为此,我不会立即知道该怎么做. (2认同)