При написании тестов MSpec BDD я столкнулся с сценарием, в котором тест, который я ожидал сбой, проходил, но только когда я запускал все свои тесты. Когда я проводил тест по отдельности, он потерпел неудачу, как ожидалось. После некоторого расследования я обнаружил, что какое-то состояние, которое было установлено в предыдущем тесте, не было сброшено до того, как было выполнено второе испытание, и это привело к тому, что второй тест прошел, когда я ожидал, что он потерпит неудачу. Следующий надуманный код воспроизводит сценарий:Как состояние статического объекта совместно используется/устанавливается между контекстами MSpec?
public class ContextBase
{
protected static object state;
}
public class Context_a : ContextBase
{
Establish context =() => { state = new object(); };
It should_set_state =() => state.ShouldNotBeNull();
}
public class Context_b : ContextBase
{
Establish context =() => { };
It should_set_state =() => state.ShouldNotBeNull();
}
Оба эти тестового прохода, поскольку Context_a выполняется перед Context_b и в то время Context_B выполняется состояние, которое было установлено в Context_A еще установлен. Если вы запускаете Context_B в изоляции, тогда тест завершается с ошибкой, поскольку состояние не установлено. Интересно, что если вы удалите пустой оператор Set из Context_B, Context_B всегда будет терпеть неудачу, как ожидалось.
Я относительно новичок в MSpec, и это поведение меня удивило. Я предположил, что подобное состояние будет сброшено между выполнением каждого контекста. Возможно, я что-то пропустил ... Правильно ли я строю эти тесты? Если MSpec не сбрасывает состояние, подобное этому между контекстами, автоматически, какую стратегию я должен использовать, чтобы обеспечить сброс состояния в случаях, подобных тому, что приведен в моем примере? Должен ли я помещать метку «Установить лямбда» в класс ContextBase, который устанавливает все поля состояния равными нулю?
Спасибо за ответ. Я заметил, что в примере, к которому вы ссылаетесь, вы также повторяете переменные статического состояния в каждом контексте вместо того, чтобы помещать их в базовый класс, который, как я думаю, сам по себе решает проблему, с которой я столкнулся. Вы находите, что повторяющийся код, подобный этому, в каждом контексте усложняет рефакторинг тестов при изменении дизайна системы? Вы упомянули, что DRY не относится к тестированию вообще, но меня всегда учили (возможно, ошибочно), что я должен проявлять большую осторожность, чтобы мои тесты были сухими, как с любым другим кодом. Еще раз спасибо за ответ! – John
Эй, Джон. Чтобы уточнить комментарий Александра по DRY, исполняемые спецификации предназначены для моделирования данного взаимодействия с системой. Все в порядке, чтобы определить детали вспомогательной настройки, но факторизация сотрудничества, которые уместны для понимания данного взаимодействия, приводит к неясным испытаниям. Для дальнейшего ознакомления см. Https://lostechies.com/derekgreer/2011/07/19/effective-tests-avoiding-context-obscurity/?preview=true&preview_id=514&preview_nonce=7b4ddbe974 –