如何从非静态方法传递TestCaseData

本文关键字:TestCaseData 静态方法 | 更新日期: 2023-09-27 18:05:55

我的测试失败,因为消息:

The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method.

这是我的代码

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);
}

我只使用静态测试用例方法,但现在我需要访问非静态数据,如变量Qv_ges_Quer: Qv_ges_Quer.IL.Value, Qv_ges_Quer.FL.Value ....所以我去掉了static

问题:
如何使用非静态测试用例?
通过调试,我还注意到它一开始没有进入安装程序。

这是我的旧代码,我想重新组织,也许你知道另一个/更好的方法比上面的方法:

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);
}

如何从非静态方法传递TestCaseData

‍♀️僵尸响应,但迟做总比不做好。

完成此任务的另一种方法是让您的测试用例数据源返回一个函数对象,该对象接受您需要的非静态成员作为其参数。然后你的测试调用它来创建你希望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 );
}

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

new Func<Qv_ges, (double, double)>( qvGesQuer => (qvGesQuer.RL.Value, qvGesQuer.IL.Value) )

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

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

在您的例子中,您似乎已经发现可以使用静态方法。如果可能的话,那最好了。

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