Предположим, у меня есть несколько небольших тестовых случаев. Достаточно прост в настройке и достаточно прост в исполнении.
Предположим, что каждый маленький тестовый набор может выполнить несколько проверок.
Поскольку я согласен с тем фактом, что один тестовый случай должен в идеале проверить одно условие , я полагаю, что у меня есть несколько вариантов реализации такого требования.
- Создание базового класса со всеми настройками и выполнением частей тестовых примеров. Каждый класс-потомок выполняет проверку одного требования. (решение 1)
- Храните все в одном классе, напишите методы проверки для каждого требования и позвольте каждому методу проверки вызывать общую процедуру настройки / упражнения. (решение 2)
- (ab) Используйте атрибут NUnit Sequential, чтобы выполнить один тест для одного условия. (решение 3)
Поскольку мне не очень нравится решение 1 или 2, потому что оно требует от вас lookup того, что делает часть теста по настройке и упражнениям, вы бы классифицировали использование атрибута Sequential NUnit в таком сценарии, чтобы запах или раствор.
Оригинал: несколько проверок / метод испытаний
[Test]
public void MyTest1()
{
// Setup
IMyObject object1 = new MyObject(/* Parameter combination X */)
this.myObjectList.Add(object1);
// Exercise
result = this.LPSolve(this.myObjectList);
// Check
Assert.AreSame(null, result.Object);
Assert.AreEqual(-1, result.Number);
Assert.True(result.Messages.Contains(ErrorMessage1));
}
[Test]
public void MyTest2()
{
// Setup
IMyObject object1 = new MyObject(/* Parameter combination Y */)
IMyObject object2 = new MyObject(/* Parameter combination Y */)
this.myObjectList.Add(object1);
this.myObjectList.Add(object2);
// Exercise
result = this.LPSolve(this.myObjectList);
// Check
Assert.AreSame(object2, result.Object);
Assert.AreEqual(8, result.Number);
Assert.True(result.Messages.Contains(ErrorMessage1));
Assert.True(result.Messages.Contains(ErrorMessage2));
}
Решение 1: базовый класс с кодом настройки и превышения
[Test]
public virtual void MyTest1()
{
// Setup
IMyObject object1 = new MyObject(/* Parameter combination X */)
this.myObjectList.Add(object1);
// Exercise
result = this.LPSolve(this.myObjectList);
// Check
MyTest1Check();
}
[Test]
public virtual void MyTest2()
{
// Setup
IMyObject object1 = new MyObject(/* Parameter combination Y */)
IMyObject object2 = new MyObject(/* Parameter combination Y */)
this.myObjectList.Add(object1);
this.myObjectList.Add(object2);
// Exercise
result = this.LPSolve(this.myObjectList);
// Check
MyTest2Check();
}
...
/* Class ObjectCheck */
/* Check result object */
public override MyTest1Check()
{
Assert.AreSame(null, this.result.Object);
}
public override MyTest2Check()
{
Assert.AreSame(this.myObjectList[1], this.result.Object);
}
...
/* Class NumberCheck */
/* Check result number */
public override MyTest1Check()
{
Assert.AreSame(-1, this.result.Number);
}
public override MyTest2Check()
{
Assert.AreSame(8, this.result.Number);
}
...
/* and so on */
Решение 2: методы тестирования, вызывающие методы настройки / упражнения
public void SetupMyTest1()
{
// Setup
IMyObject object1 = new MyObject(/* Parameter combination X */)
this.myObjectList.Add(object1);
// Exercise
this.result = this.LPSolve(this.myObjectList);
}
[Test]
public void MyTest1ObjectShouldBeNull()
{
SetupMyTest1();
// Check
Assert.AreSame(null, this.result.Object);
}
[Test]
public void MyTest1ResultShouldBeMinus1()
{
SetupMyTest1();
// Check
Assert.AreEqual(-1, this.result.Number);
}
[Test]
public void MyTest1MessageShouldContainErrorMessage1()
{
SetupMyTest1();
// Check
Assert.True(this.result.Messages.Contains(ErrorMessage1));
}
public void SetupMyTest2()
{
// Setup
IMyObject object1 = new MyObject(/* Parameter combination Y */)
IMyObject object2 = new MyObject(/* Parameter combination Y */)
this.myObjectList.Add(object1);
this.myObjectList.Add(object2);
// Exercise
this.result = this.LPSolve(this.myObjectList);
}
[Test]
public void MyTest2ObjectShouldBeObject2()
{
SetupMyTest2();
// Check
Assert.AreSame(this.myObjectList[1], this.result.Object);
}
[Test]
public void MyTest2ResultShouldBeEight()
{
SetupMyTest2();
// Check
Assert.AreEqual(8, this.result.Number);
}
[Test]
public void MyTest2MessageShouldContainErrorMessage1()
{
SetupMyTest2();
// Check
Assert.True(this.result.Messages.Contains(ErrorMessage1));
}
[Test]
public void MyTest2MessageShouldContainErrorMessage2()
{
SetupMyTest2();
// Check
Assert.True(this.result.Messages.Contains(ErrorMessage2));
}
Решение 3: использование атрибутов хранит настройку / упражнение / проверку в одном месте и выполняет одну проверку / проверку (оба метода выполняются 3 и 4 раза соответственно)
[Test, Sequential]
public void MyTest1([Values("CheckObject", "CheckNumber", "CheckErrorMessage1") string check)
{
// Setup
IMyObject object1 = new MyObject(/* Parameter combination X */)
this.myObjectList.Add(object1);
// Exercise
result = this.LPSolve(this.myObjectList);
// Check
if (check == "CheckObject") Assert.AreSame(null, result.Object);
else if (check = "CheckNumber") Assert.AreEqual(-1, result.Number);
else if (check = "CheckErrorMessage1") Assert.True(result.Messages.Contains(ErrorMessage1));
else throw new ArgumentOutOfRangeException(check);
}
[Test, Sequential]
public void MyTest2([Values("CheckObject", "CheckNumber", "CheckErrorMessage1", "CheckErrorMessage2") string check)
{
// Setup
IMyObject object1 = new MyObject(/* Parameter combination Y */)
IMyObject object2 = new MyObject(/* Parameter combination Y */)
this.myObjectList.Add(object1);
this.myObjectList.Add(object2);
// Exercise
result = this.LPSolve(this.myObjectList);
// Check
if (check == "CheckObject") Assert.AreSame(object2, result.Object);
else if (check = "CheckNumber") Assert.AreEqual(8, result.Number);
else if (check = "CheckErrorMessage1") Assert.True(result.Messages.Contains(ErrorMessage1));
else if (check = "CheckErrorMessage2") Assert.True(result.Messages.Contains(ErrorMessage2));
else throw new ArgumentOutOfRangeException(check);
}