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

Test case design for Max() function

这里是 C# 新手。

我理解测试用例应该是:

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

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

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

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

在您的情况下,不同的执行分支是 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.

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

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

我不太了解 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、X-Y = 0,以确保 A 在重新评估时不会改变,可能会添加时间延迟,以防其依赖于时间并且程序执行得太快以至于无法执行反映(你需要纳秒分辨率来反映不间断地执行如此小而简单的代码)