如何忽略基于NUnit中另一个测试的测试?

时间:2009-11-23 11:15:34

标签: unit-testing nunit

我正在为数据库操作编写一些NUnit测试。显然,如果Add()失败,那么Get()也会失败。但是,当Add()Get()都失败时,它看起来很有欺骗性,因为看起来有两个问题而不是一个问题。

有没有办法为测试运行指定“顺序”,因为如果第一次测试失败,将忽略以下测试?

在同一行中,有没有办法自行订购单元测试类?例如,我想在测试来自UI的往返数据之前,首先运行基本数据库操作的测试。

注意:这与测试相互依赖有点不同,它更像是在运行一堆测试之前确保某些东西先工作。例如,如果您无法首先连接到数据库,那么运行大量数据库操作是浪费时间。

编辑:似乎有些人忽略了这一点。我不这样做:

[Test]
public void AddTest()
{
    db.Add(someData);
}

[Test]
public void GetTest()
{
    db.Get(someData);
    Assert.That(data was retrieved successfully);
}

相反,我这样做:

[Test]
public void AddTest()
{
    db.Add(someData);
}

[Test]
public void GetTest()
{
    // need some way here to ensure that db.Add() can actually be performed successfully
    db.Add(someData);
    db.Get(somedata);
    Assert.That(data was retrieved successfully);
}

换句话说,我想确保在我可以测试是否可以检索数据之前首先添加数据。人们假设我使用第一次测试的数据来通过第二次测试,但事实并非如此。我试图确保一个操作可能,然后再尝试依赖它的另一个操作。

正如我已经说过的,您需要确保在运行数据库操作之前可以连接到数据库。或者您可以在执行文件操作之前打开文件。或者在测试API调用之前连接到服务器。或者......你明白了。

7 个答案:

答案 0 :(得分:14)

NUnit支持用于验证设置的“Assume.That”语法。这是Theory的一部分(感谢clairestreb)。在NUnit.Framework命名空间中是一个类Assume。引用文档:

/// Provides static methods to express the assumptions
/// that must be met for a test to give a meaningful
/// result. If an assumption is not met, the test
/// should produce an inconclusive result.

所以在上下文中:

public void TestGet() {
    MyList sut = new MyList()
    Object expecting = new Object();
    sut.Put(expecting);
    Assume.That(sut.size(), Is(1));
    Assert.That(sut.Get(), Is(expecting));
}

答案 1 :(得分:5)

测试永远不会相互依赖。你刚刚发现了原因。根据定义,依赖于彼此的测试是脆弱的。如果您需要数据库中的数据用于Get()的测试,请将其放在设置步骤中。

答案 2 :(得分:2)

我认为问题在于你正在使用NUnit来运行NUnit运行的单元测试以外的其他东西。

基本上,您希望AddTest在GetTest之前运行,并且您希望NUnit在AddTest失败时停止执行测试。

问题在于,这与单元测试是对立的 - 测试应该是完全独立的,并且可以按任何顺序运行。

单元测试的标准概念是,如果您对“添加”功能进行了测试,那么您可以在“获取”测试中使用“添加”功能,而不必担心“添加”是否适用于'得到'测试。你知道'添加'是有效的 - 你有一个测试。

'FIRST'原则(http://agileinaflash.blogspot.com/2009/02/first.html)描述了单元测试的行为方式。您要编写的测试违反了“I”(隔离)和“R”(可重复)。

如果你担心两个测试之间的数据库连接断开,我建议你不要在测试期间连接到真正的数据库,你的代码应该使用某种数据接口,而对于测试,你应该使用模拟界面。如果测试点来运行数据库连接,那么你可能只是使用错误的工具来完成工作 - 这不是一个单元测试。

答案 3 :(得分:1)

我认为这不可能是开箱即用的。

无论如何,您所描述的测试类设计会使测试代码非常脆弱。

答案 4 :(得分:0)

MbUnit似乎有一个DependsOnAttribute可以让你做你想做的事。

  

如果是其他测试夹具或测试   方法失败然后这个测试不会   跑。而且,依赖力   这个测试在它之后运行   取决于。

虽然对NUnit一无所知。

答案 5 :(得分:0)

您不能假设任何测试夹具执行顺序,因此必须在测试类中检查任何先决条件。

将您的添加测试分为一个测试类,例如AddTests,并将Get测试放入另一个测试类,例如GetTests类。

在GetTests类的[TestFixtureSetUp]方法中,检查您是否具有工作数据库访问权限(例如,Add的工作),如果没有,请检查Assert.Ignore或Inconclusive,如您所愿。

这将在不满足其先决条件时中止GetTests测试夹具,并跳过尝试运行它包含的任何单元测试。 (我想!我是一个nUnit新手。)

答案 6 :(得分:-2)

创建一个全局变量并在Get的测试中返回,除非Add将其设置为true(在Add的最后一行执行此操作):

public boolean addFailed = false;
public void testAdd () {
    try {
        ... old test code ...
    } catch (Throwable t) { // Catch all errors
        addFailed = true;
        throw t; // Don't forget to rethrow
    }
}
public void testGet () {
    if (addFailed) return;
    ... old test code ...
}