Assert.Inconclusive的用法

时间:2009-08-02 17:01:39

标签: .net mocking tdd assert stub

我想知道某人应该如何使用Assert.Inconclusive()。

我正在使用它,如果我的单元测试即将失败的原因不是测试的目的。

例如,我在一个类上有一个方法来计算一个int数组的总和。在同一个类中,还有一种计算元素平均值的方法。它通过调用sum并将其除以数组的长度来实现。

为Sum()编写单元测试很简单。但是,当我为Average()编写测试时,Sum()失败,那么Average()也可能会失败。

平均值的失败并未明确失败的原因;它失败的原因不是它应该测试的原因。这就是为什么我会检查Sum()是否返回正确的结果,否则我是Assert.Inconclusive()。

这是否被视为良好做法?什么是Assert.Inconclusive用于?或者我应该通过隔离框架来解决前面的例子?

4 个答案:

答案 0 :(得分:24)

不确定性测试是一种无法确定结果的测试。例如,如果您的测试使用某种外部资源(例如,Internet连接),该怎么办?如果连接当前不可用,这并不意味着测试失败。另一方面,您不应该只是在没有实际运行的情况下将其标记为成功。因此,您将其标记为不确定,这可以在测试报告中看到。

注意:通常,您不应在测试中使用此类外部资源,因为这会使测试变得脆弱。

对于尚未完成的测试,我使用MbUnit的Explicit属性。

答案 1 :(得分:15)

当我使用VS生成单元测试时,我得到Assert.Inclusive用于生成的测试方法,并且通常我更改断言以便在我工作时使用其他东西。我在测试结果中使用Assert.Inconclusive的问号作为标记,快速告诉我哪些测试还没有完成。

嗯,这就是我使用它的方式。从它的名字“Inconclusive”,我想你可以用来表明你的不确定状态,只要你记录它的含义。

但是,根据您的Average()方法的描述,我认为您的单元测试可能不足以覆盖一个“单元”,一个特定情况。有时,我为单个方法编写2或3个单元测试方法。或者,您可以将Average()方法分解为涵盖单一职责的较小方法。这样,您可以在单元测试Average()之前对这些较小的方法进行单元测试。


约翰,

这是我实施Sum()Average()方法的方法。

public static class MyMath
{
    private static void ValidateInput(ICollection<int> numbers)
    {
        if (numbers == null)
            throw new ArgumentNullException("numbers", "Null input.  Nothing to compute!");
        if (numbers.Count == 0)
            throw new ArgumentException("Input is empty.  Nothing to compute!");
    }

    public static int Sum(int[] numbers)
    {
        ValidateInput(numbers);

        var total = 0;
        foreach (var number in numbers)
            total += number;

        return total;
    }

    public static double Average(int[] numbers)
    {
        ValidateInput(numbers);
        return Sum(numbers) / numbers.Length;
    }
}

为简单起见,我只是从ArgumentException方法中抛出ValidateInput(ICollection<int>)个例外。您还可以检查溢出的可能性,并在OverflowException方法中抛出ValidateInput(ICollection<int>)

话虽如此,这是我如何测试Average(int[])函数。

[TestMethod]
public void AverageTest_GoodInput()
{
    int[] numbers = {1, 2, 3};
    const double expected = 2.0;
    var actual = MyMath.Average(numbers);
    Assert.AreEqual(expected, actual);
}

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void AverageTest_NullInput()
{
    int[] numbers = null;
    MyMath.Average(numbers);
}

[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void AverageTest_EmptyInput()
{
    var numbers = new int[0];
    MyMath.Average(numbers);
}

通过这些测试设置,我可以确定当所有测试通过时,我的功能是正确的。好吧,除了溢出的情况。现在我可以回到ValidateInput(ICollection<int>)方法添加逻辑来检查溢出,然后再添加一个测试以期望OverflowException引发导致溢出的输入类型。如果您想使用TDD,请按相反的顺序执行此操作。

我希望这有助于澄清这个想法。

答案 2 :(得分:9)

我只是Assert.Inconclusive单元测试我尚未编写。有时在写东西的时候我会发现一些我不想错过的角落。所以我快速跳过,用描述性名称编写测试方法并添加一行Assert.Inconclusive。

这样做的原因是它提供了我需要测试的内容的文档,而不会过多地中断我的工作流程。它还可以在结果列表中快速过滤掉测试失败。有一个不确定的失败意味着我没有破坏任何我只是更多的测试编写。

答案 3 :(得分:7)

Assert.Inconclusive表示:

我还没有编写测试;我只创建了测试方法

-OR -

我的测试有一个依赖项,并且该依赖项不可用。例如

List<Customer> custs = o.GetAllCustomers();
if (custs.Count == 0)
{
  Assert.Inconclusive("No customers to test");
  return;
}