6

这里我将通过一个例子来解释这个问题。原始问题更抽象地提出了问题。不过没必要读。

更新:以问题为例

假设我们已经实现了这个有问题的函数来查找 int[] 的最小值:

public int MyMin(int[] data)
{
    int min = 1000;

    for (int i = 1; i < data.Length; i++)
    {
        if (data[i] < min)
        {
            min = data[i];
        }
    }

    return min;
}

在这个函数上运行 Intellitet 会给我们: 在此处输入图像描述

请注意测试#4 和#6,由于实现错误,该函数无法正确计算最小值。但是,这些测试正在通过,这是不希望的。

Intellitet 无法神奇地确定我们的预期行为MyMin并制作测试以在这些输入上失败。但是,如果我们可以手动指定这些测试所需的结果,那就太好了。

@michał-komorowski 的解决方案是可行的,但是对于每个测试用例,我必须以PexAssumes 重复其输入。是否有更优雅/干净的方式来指定测试输入的所需输出?

原始问题

Intelitest 生成一个可修改的参数化测试,并且可以在其中添加通用/全局断言。它还生成使代码覆盖率最大化的最小输入数。Intellitest 将输入存储为单独的单元测试,每个测试都使用精心设计的输入调用参数化测试。

我正在寻找一种方法来为每个输入添加断言。

由于每个输入都作为单元测试函数存储在.g.cs文件中,因此可以在其中添加断言。问题是这些函数不应该由用户自定义,因为它们将在后续运行中被 Intellitet 覆盖。

为每个单元测试添加断言的推荐方法是什么?

4

2 回答 2

2

您不应该将断言添加到测试方法(具有[TestMethod]属性的方法)。它们仅用于提供参数值。放置断言的地方是带有[PexMethod]属性的方法。

乍一看,它可能看起来像一个限制。但是,如果我们考虑 IntelliTest 是如何工作的,那就不是了。为每个输入添加断言是没有意义的,因为可以随时删除、更新或创建输入。例如,当:

  • 更改了正在测试的方法。
  • PexAssume类被使用。
  • PexMethod属性的配置已更改。

但是,您可以执行其他操作,即为正在测试和使用的方法添加多个“Pex 方法” PexAssume。例如,假设我们有BubbleSort方法,并且我们想根据输入数组的长度定义不同的断言。

[PexMethod]
public void BubbleSort(int[] a)
{
    PexAssume.IsTrue(a.Length == 5);
    int[] result = Program.BubbleSort(a);
    // Assertions specific for an array with 5 elements
}

[PexMethod]
public void BubbleSort(int[] a)
{
    PexAssume.IsTrue(a.Length == 10);
    int[] result = Program.BubbleSort(a);
    // Assertions specific for an array with 10 elements
}
于 2016-02-09T07:49:24.217 回答
0

这个答案建立在上一个答案的基础上。对于所提出的问题,它更具体。

Pex 为所有代码路径生成测试,但对您的代码一无所知。您仍然需要在 PUT(参数化单元测试)中进行安排/执行/断言,以告诉 Pex 您认为您的代码应该如何工作。此外,您可以在排列之前添加假设,因此模式是假设/排列/行为/断言。

对于您的示例,我从这个 PUT 开始。

    [PexMethod(MaxRunsWithoutNewTests = 200)]
    [PexAllowedException(typeof(NullReferenceException))]
    public int  MyMin([PexAssumeUnderTest]Class1 target, int[] data)
    {
        //assume
        PexAssume.IsTrue(data.Length == 1);
        //arrange
        data[0] = 0;

        //act
        int result = target.MyMin(data);

        //assert
        PexAssert.AreEqual(0, result);
        return result;
    }

结果表明只覆盖了 3/8 块,测试 2 失败,预期为“0”,得到“1000”

这告诉我我需要查看代码以找出我得到 1000 的原因。

我看到我用 1 而不是 0 开始 for 循环。所以我修复了代码并再次运行 IntelliTest。

这次我得到了两个通过测试,这很好。但只测试了 6/8 块。我错过了一些东西。

我创建了一个新的 PUT,它允许 Pex 生成看起来像这样的数据。

    [PexMethod(MaxRunsWithoutNewTests = 200)]
    [PexAllowedException(typeof(NullReferenceException))]
    public int MyMin2([PexAssumeUnderTest]Class1 target, int[] data)
    {
        //assume

        //act
        int result = target.MyMin(data);

        //assert
        return result;
    }

现在我有 7 个单元测试,它们运行所有代码路径并且所有测试都通过。

您会注意到每个 PUT 都会生成自己的一组测试。

于 2016-04-12T17:05:05.957 回答