是否可以在整个 fixture 而不是逐个测试的基础上更改 NUnit 测试名称约定?

Is it possible to change the NUnit test name convention on the entire fixture instead of on the test by test basis?

我想使用模板“{m}({1})”。现在我可以在每个 TestCase 属性中提供 TestName = "{m}({1})"。但这重复太多了。 TestFixture也有这个参数,但是用了好像没有什么效果:

    [TestFixture(TestName = "{m}({1})")]
    public class Tests
    {
...
    }

我的问题 - 是否可以通过仅指定一次而不是在每个 TestCase 属性中指定来更改给定夹具中所有测试的测试名称约定?

编辑 1

我想继续使用 TestCase 属性,即使使用 TestCaseSource 只允许我指定模板一次。

不,那不可能。使用 TestName 属性 就像您所做的那样,只需设置由夹具 class 表示的测试套件的名称。在这种情况下,新名称是“{m}({1})”,按原样使用,不做任何替换。

原因是名称模板中使用的特殊序列仅适用于命名测试用例,不适用于固定装置。

如果您运行使用 NUnit3 控制台 运行ner,您可以通过--test-name-format 选项。

您可以使用 TestCaseSourceTestCaseData 避免在每个 TestCase 属性中设置名称,如下例所示:

[TestFixture]
public class UnitTest1 
{
    [TestCaseSource(typeof(MyDataClass), nameof(MyDataClass.TestCases))]
    public void DivideTest(int n, int d) 
    {
        Assert.AreEqual(3, n / d);
    }
}

public class MyDataClass 
{
    public static IEnumerable TestCases 
    {
        get 
        {
            yield return new MyTestCaseData(9, 3);
            yield return new MyTestCaseData(30, 10);
            yield return new MyTestCaseData(12, 4);
        }
    }
}

public class MyTestCaseData : TestCaseData 
{
    public MyTestCaseData(object arg1, object arg2) : base(arg1, arg2) 
    {
        SetName("{m}({1})");
    }
}

TestCaseDataSetName方法允许设置单个测试用例的名称。因此,创建一个新的 class 派生自 TestCaseData 并在构造函数中设置名称将避免为每个 TestCase 属性设置名称,并使代码更清晰。

解决方案 2:(不使用 TestCaseSource 和 TestCases) 不可能使用 TestFixture TestName 属性 并在本地使用 TestCase 属性。但是通过创建和使用自定义属性可以实现相同的结果,例如 MyTestCaseAttr - 从 TestCaseAttribute 继承的 class 并在其构造函数中设置名称(避免每次都设置名称)

[TestFixture]
public class UnitTest1
{
    [MyTestCaseAttr(12, 4)]
    public void DivideTest(int n, int d)
    {
        Assert.AreEqual(3, n / d);
    }

    [MyTestCaseAttr(4, 5, 6)]
    public void AddTest(int a, int b, int c)
    {
        Assert.AreEqual(15, a + b + c);
    }
}

public class MyTestCaseAttr : TestCaseAttribute
{
    public MyTestCaseAttr(object arg1, object arg2) : base(arg1, arg2)
    {
        TestName = "{m}({1})";
    }

    public MyTestCaseAttr(object arg1, object arg2, object arg3) : base(arg1, arg2, arg3)
    {
        TestName = "{m}({1})";
    }
}