我正在为数据库操作编写一些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调用之前连接到服务器。或者......你明白了。
答案 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 ...
}