Я не знаю ни одной ситуации, когда было бы неплохо иметь несколько утверждений внутри самого метода [Test]. Основная причина, по которой людям нравится иметь несколько утверждений, заключается в том, что они пытаются создать один класс [TestFixture] для каждого тестируемого класса. Вместо этого вы можете разбить свои тесты на несколько классов [TestFixture]. Это позволяет увидеть несколько способов, которыми код, возможно, не отреагировал так, как вы ожидали, а не тот, в котором первое утверждение не удалось. Способ достижения этого заключается в том, что у вас есть по крайней мере один каталог на класс, который тестируется с большим количеством классов [TestFixture] внутри. Каждый класс [TestFixture] будет назван в соответствии с конкретным состоянием объекта, который вы будете тестировать. Метод [SetUp] переводит объект в состояние, описываемое именем класса. Затем у вас есть несколько методов [Test], каждый из которых утверждает разные вещи, которые, как вы ожидаете, будут истинными, учитывая текущее состояние объекта. Каждый метод [Test] назван в честь того, что он утверждает, за исключением того, что, возможно, он может быть назван в честь концепции, а не только для чтения кода на английском языке. Тогда каждой реализации метода [Test] нужна только одна строка кода, в которой он что-то утверждает. Еще одним преимуществом этого подхода является то, что он делает тесты очень удобочитаемыми, поскольку становится совершенно ясно, что вы тестируете, и что вы ожидаете, просто взглянув на имена классов и методов. Это также будет лучше масштабироваться по мере того, как вы начнете понимать все мелкие крайние случаи, которые вы хотите протестировать, и по мере обнаружения ошибок. за исключением, возможно, он может быть назван в честь концепции, а не просто чтение кода на английском языке. Тогда каждой реализации метода [Test] нужна только одна строка кода, в которой он что-то утверждает. Еще одним преимуществом этого подхода является то, что он делает тесты очень удобочитаемыми, поскольку становится совершенно ясно, что вы тестируете, и что вы ожидаете, просто взглянув на имена классов и методов. Это также будет лучше масштабироваться по мере того, как вы начнете понимать все мелкие крайние случаи, которые вы хотите протестировать, и по мере обнаружения ошибок. за исключением, возможно, он может быть назван в честь концепции, а не просто чтение кода на английском языке. Тогда каждой реализации метода [Test] нужна только одна строка кода, в которой он что-то утверждает. Еще одним преимуществом этого подхода является то, что он делает тесты очень удобочитаемыми, поскольку становится совершенно ясно, что вы тестируете, и что вы ожидаете, просто взглянув на имена классов и методов. Это также будет лучше масштабироваться по мере того, как вы начнете понимать все мелкие крайние случаи, которые вы хотите протестировать, и по мере обнаружения ошибок. и что вы ожидаете, просто посмотрев на имена классов и методов. Это также будет лучше масштабироваться по мере того, как вы начнете понимать все мелкие крайние случаи, которые вы хотите протестировать, и по мере обнаружения ошибок. и что вы ожидаете, просто посмотрев на имена классов и методов. Это также будет лучше масштабироваться по мере того, как вы начнете понимать все мелкие крайние случаи, которые вы хотите протестировать, и по мере обнаружения ошибок.
Обычно это означает, что последняя строка кода внутри метода [SetUp] должна хранить значение свойства или возвращаемое значение в частной переменной экземпляра [TestFixture]. Тогда вы можете утверждать несколько разных вещей об этой переменной экземпляра из разных методов [Test]. Вы также можете сделать утверждение о том, какие различные свойства тестируемого объекта установлены сейчас, когда он находится в желаемом состоянии.
Иногда по ходу дела вам нужно делать утверждения, когда вы переводите тестируемый объект в желаемое состояние, чтобы убедиться, что вы не ошиблись, прежде чем перевести объект в желаемое состояние. В этом случае эти дополнительные утверждения должны появиться внутри метода [SetUp]. Если что-то пойдет не так внутри метода [SetUp], будет ясно, что что-то не так с тестом, прежде чем объект попадет в желаемое состояние, которое вы намеревались проверить.
Еще одна проблема, с которой вы можете столкнуться, заключается в том, что вы можете тестировать исключение, которое вы ожидали получить. Это может соблазнить вас не следовать приведенной выше модели. Тем не менее, это все еще может быть достигнуто путем перехвата исключения внутри метода [SetUp] и сохранения его в переменной экземпляра. Это позволит вам утверждать разные вещи об исключении, каждый в своем собственном методе [Test]. Затем вы можете также утверждать и другие вещи относительно тестируемого объекта, чтобы убедиться в отсутствии непреднамеренных побочных эффектов от создаваемого исключения.
Пример (это будет разбито на несколько файлов):
namespace Tests.AcctTests
{
[TestFixture]
public class no_events
{
private Acct _acct;
[SetUp]
public void SetUp() {
_acct = new Acct();
}
[Test]
public void balance_0() {
Assert.That(_acct.Balance, Is.EqualTo(0m));
}
}
[TestFixture]
public class try_withdraw_0
{
private Acct _acct;
private List<string> _problems;
[SetUp]
public void SetUp() {
_acct = new Acct();
Assert.That(_acct.Balance, Is.EqualTo(0));
_problems = _acct.Withdraw(0m);
}
[Test]
public void has_problem() {
Assert.That(_problems, Is.EquivalentTo(new string[] { "Withdraw amount must be greater than zero." }));
}
[Test]
public void balance_not_changed() {
Assert.That(_acct.Balance, Is.EqualTo(0m));
}
}
[TestFixture]
public class try_withdraw_negative
{
private Acct _acct;
private List<string> _problems;
[SetUp]
public void SetUp() {
_acct = new Acct();
Assert.That(_acct.Balance, Is.EqualTo(0));
_problems = _acct.Withdraw(-0.01m);
}
[Test]
public void has_problem() {
Assert.That(_problems, Is.EquivalentTo(new string[] { "Withdraw amount must be greater than zero." }));
}
[Test]
public void balance_not_changed() {
Assert.That(_acct.Balance, Is.EqualTo(0m));
}
}
}