Max()函数的测试用例设计

时间:2016-11-18 21:54:44

标签: c# unit-testing testing tdd

C#新手在这里。

我理解测试用例应该是:

  • 简单透明
  • 重复次数最少
  • 确保100%代码覆盖率

我也理解边界值分析和等价分区的基础知识,但是使用下面的函数,什么是基本测试用例?

    static public int Max(int a, int b, int c)
    { // Lines of code: 8, Maintainability Index: 70, Cyclomatic Complexity: 4, Class Coupling: 0
        if (a > b)
            if (a > c)
                return a;
            else
                return c;
        else
            if (b > c)
                return b;
            else
                return c; 
    }

这是我到目前为止所拥有的......

  using Microsoft.VisualStudio.TestTools.UnitTesting;
    using ConsoleApplication10;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace ConsoleApplication10.Tests
    {
        [TestClass()]
        public class ProgramTests
        {
            [TestMethod()]
            public void MaxTestNulls(int a, int b, int c)
            {
                Assert.IsNotNull(a, "The first parameter must be present.");
                Assert.IsNotNull(b, "The second parameter must be present.");
                Assert.IsNotNull(c, "The third parameter must be present.");
            }
            [TestMethod()]
            public void MaxTestTypes(int a, int b, int c)
            {
                Assert.IsInstanceOfType(a, typeof(int));
                Assert.IsInstanceOfType(b, typeof(int));
                Assert.IsInstanceOfType(c, typeof(int)); 
            }
            [TestMethod()]
            public void MaxTestBasics(int a, int b, int c)
            {
                if (a > int.MaxValue || b > int.MaxValue || c > int.MaxValue)
                {
                    Assert.Fail();
                }

                if (a < int.MinValue || b < int.MinValue || c < int.MinValue)
                {
                    Assert.Fail();
                }
            }
        }
  }

我完全不在这里吗?我的老师不会膨胀并给我任何提示..我可以使用哪些其他测试用例会有用?

2 个答案:

答案 0 :(得分:2)

一种可行的测试策略称为分支覆盖。在那里,您尝试编写覆盖被测系统中每个执行分支的单元测试。

在您的情况下,不同的执行分支是return指令:return areturn creturn b以及底部的return c

您可以使用这些用例(分别为a,b和c的值)覆盖整个函数:

4, 2, 3
4, 2, 5
4, 2, 4 <-- boundary condition
2, 4, 3
2, 2, 3 <-- boundary condition
2, 4, 5
2, 4, 4 <-- boundary condition

正好有四个测试用例确保覆盖所有分支。还有三个案例涉及仍然在特定分支中结束的边界条件。

以下是xUnit中这些测试用例的实现。我选择了xUnit,因为它通过使用InlineData属性支持一种测试方法的多个测试用例:

[Theory]
[InlineData(4, 2, 3, 4)]
[InlineData(4, 2, 5, 5)]
[InlineData(4, 2, 4, 4)]
[InlineData(2, 4, 3, 4)]
[InlineData(2, 2, 3, 3)]
[InlineData(2, 4, 5, 5)]
[InlineData(2, 4, 4, 4)]
public void Max_ReturnsExpectedValue(int a, int b, int c, int expectedMax)
{
    int actualMax = Program.Max(a, b, c);
    Assert.Equal(expectedMax, actualMax);
}

只是为了记录,所有七个测试用例都在上面执行。

在相关的说明中,这种测试称为白盒测试。您可以访问具体实现,然后您正在为该实现编写测试。如果您想实施黑盒测试,那么您的测试用例只会受到您对该功能的期望的驱动。例如,这些可能是黑盒测试的合法测试用例:

1, 1, 1 -> 1
1, 1, 2 -> 2
1, 2, 1 -> 2
1, 2, 2 -> 2
1, 2, 3 -> 3
1, 3, 1 -> 3
1, 3, 2 -> 3
1, 3, 3 -> 3
2, 1, 1 -> 2
...

这里的问题是我们不知道哪些边界条件是相关的,因此我们必须添加相当多的边界条件以涵盖所有选项。如果继续朝同一方向前进,测试总数将为3 ^ 3 = 27。

答案 1 :(得分:0)

第一个明显的添加就像它的me86说你应该测试3个输入中的任何一个是否相等。

其次,您应该测试依赖性,这意味着输入的值可能是每次评估时更改的函数的输出,因此请确保在测试类中获取单个输入实例(即,评估一次)并继续对本地实例进行测试,不要重新评估输入

我对C#不太了解,但让我向您展示一个通用示例

public static TestFunction (int A, int B, int C)
{
// Your test methods
}

如果像这样被调用

boolean Result = TestFunction((int)Math.sin(System.currentTimeMillis()),(int)Math.sin(System.currentTimeMillis()),(int)Math.sin(System.currentTimeMillis()));

每次在您的函数中访问A,B或C时,它们的值都将被重新评估,并且可能会否定先前测试的结果

我会添加额外的测试,如X = A,Y = A,XY = 0,以确保A在重新评估时不会改变,可能会增加时间延迟,因为它依赖于时间,程序执行速度太快,无法反映(你需要纳秒级的分辨率才能反映出小而简单的代码的不间断执行)