【问题标题】:NUnit Theory with an exceptionNUnit 理论例外
【发布时间】:2013-08-08 08:59:56
【问题描述】:

这是我正在寻找的设计/模式。

我有一个 nunit 测试,我计划在其中使用现有的枚举作为理论。现有的枚举有近 30 个成员。

说是这样的:

enum ABigEnum
{
    A,
    B,
    C,
    D
}


[Theory]
public void Test(ABigEnum enumValue)
{
//generate someValue based upon enumValue    
Assert.That(someValue, Is.True, "an amazing assertion message");
}

但是,测试应该断言,枚举中的值 D 为 False,所有其他值为 True。 我们可以不使用 if-else 条件来做到这一点(作为一个神圣的教义,我在测试中避免使用条件)? 或者你们有什么有趣的模式吗?

【问题讨论】:

    标签: c# unit-testing testing nunit theory


    【解决方案1】:

    在编写此类测试时,我喜欢使用 NUnit 提供的 TestCaseSource 属性。我相信这些测试被称为数据驱动测试。

    我的测试版本如下所示:

    public class TestClass
    {
        public enum ABigEnum
        {
            A,
            B,
            C,
            D
        }
    
        public IEnumerable TestValues
        {
            get
            {
                yield return new TestCaseData(ABigEnum.A, false).SetName("Assert A");
                yield return new TestCaseData(ABigEnum.B, false).SetName("Assert B");
                yield return new TestCaseData(ABigEnum.C, false).SetName("Assert C");
                yield return new TestCaseData(ABigEnum.D, true).SetName("Assert D");
            }
        }
    
        [Theory]
        [TestCaseSource(typeof(TestClass), "TestValues")]
        public void Test(ABigEnum enumValue, bool assertValue)
        {
            //generate someValue based upon enumValue    
            Assert.That(enumValue, Is.EqualTo(assertValue), "an amazing assertion message");
        }
    
    }
    

    编辑 1

    实际上,您可以将Datapoint 属性与Theory 一起使用。像这样的:

        public enum ABigEnum
        {
            A,
            B,
            C,
            D
        }
    
        [Datapoint]
        public Tuple<ABigEnum, bool>[] TestValues = new[]
                           {
                               new Tuple<ABigEnum, bool>(ABigEnum.A, false), new Tuple<ABigEnum, bool>(ABigEnum.B, false),
                               new Tuple<ABigEnum, bool>(ABigEnum.C, false), new Tuple<ABigEnum, bool>(ABigEnum.D, true)
                           };
    
        [Theory]
        public void Test(Tuple<ABigEnum,bool> data)
        {
            //generate someValue based upon enumValue    
            Assert.That(data.Item1, Is.EqualTo(data.Item2), "an amazing assertion message");
        }
    

    【讨论】:

    • 这是一个有趣的问题,唯一的问题是要使用的枚举又大又长!!所以会有大约 25 倍的收益!
    • 一个查询,为什么你同时拥有 Theory 和 TestCaseSource 属性?他们是这样一起工作的吗?
    • @dushyantp - 您可以拥有任何可以返回 IEnumerable 并将其用作您的 TestCaseSource 的实现。你需要TheoryTest 告诉NUnit 这是一个测试/理论,只有这样的修饰方法会被扫描。 TestCaseSource 告诉 NUnit 多次运行相同的方法。你可以有多个属性。
    • 感谢 Shrikanth,这些都是真正的好方法。唯一的问题是,如上所述,使用 Theory 的目的是我们不想再次重写整个枚举(因为它在测试用例源和数据点中都是必需的)。不过,您的观点非常有帮助。赞赏。
    • 需要更多上下文来改进这一点。 Enum 似乎是一个糟糕的选择,因为您有要传递的数据和断言值。改用字典试试?
    【解决方案2】:

    您应该能够通过以下方式实现您的要求:

    enum ABigEnum
    {
        A,
        B,
        C,
        D
    }
    
    [Theory]
    public void Test(ABigEnum enumValue)
    {
        bool someValue = enumValue != ABigEnum.D;
        Assert.That(someValue, Is.True, "an amazing assertion message");
    }
    

    当为所有其他值传入Dtrue 时,这将为您提供false

    因为这个逻辑不是系统“知道”的东西,你必须做出某种决定,它是 if / else 还是 switch。

    然而,这个“测试”看起来更像是一种方法,而不是纯粹的测试,您可能需要重新考虑您正在测试和尝试实现的目标是什么,因为您强调您没有真的不希望在测试中有很多逻辑。

    【讨论】:

      【解决方案3】:

      好的,我找到了这种编写测试的方法。如果有人发布更好的方法,应接受它。否则,这就是答案。

      [Theory]
      public void Test(ABigEnum enumValue)
      {
      //generate someValue based upon enumValue    
      bool truthValue = IsD(enumValue);
      Assert.That(someValue, Is.EqualTo(truthValue), "an amazing assertion message");
      }
      
      IsD(ABigEnum enumValue)
      {
          return (enumValue==ABigEnum.D)
      }
      

      可能不是最理想的解决方案,并且确实在外部引入了测试的条件代码路径。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-14
        • 2022-01-14
        • 1970-01-01
        相关资源
        最近更新 更多