Является ли плохая форма рассчитывать на порядок ваших единичных тестов NUnit
Я создаю тесты Unit, такие как сумасшедшие, и обнаруживаю, что мне часто приходится настраивать что-то в одном тесте, которое я только что потерял в предыдущем тесте. Можно ли когда-нибудь создать что-нибудь (например, запись базы данных) в одном тесте (например, тест вставки), а затем использовать его для более позднего теста (например, тест удаления)? Или каждый тест всегда остается полностью самостоятельным?
Можете ли вы определить порядок тестов в NUnit или они всегда выполняются в алфавитном порядке?
Примечание. Я специально спрашиваю о порядке тестирования в одном тестовом файле. Не через тестовые файлы или каким-либо образом более глобально.
Обновление: Спасибо всем, кто ответил - было много хороших ответов, и чувство группы было довольно единодушным. Я выбрал ответ Джона Нолана, поскольку он предоставил наиболее полное объяснение и множество ссылок. Как вы, возможно, догадались, я был очень искушен нарушить это правило, несмотря на то, что думал, что это может быть немного "вонючий", как сказал Джон. Спасибо также Fortyrunner за добавление тега unit-testing.
Ответы
Ответ 1
Опираясь на порядок ваших тестов, вы указываете, что вы сохраняете состояние в тестах. Это вонючий
Более чистый способ тестирования - это то, где вы зависите только от одной части функциональности, которую вы хотите проверить. Обычно вы mock другие объекты, необходимые для проверки вашего метода.
Хороший способ подумать о приближающихся модульных тестах - это Упорядочить, Act, Assert.
Ниже приведен фрагмент от Карла Сегина, отличный eBook. Я отредактировал Arrange, Act и Assert.
[TestFixture] public class CarTest
{
[Test] public void SaveCarCallsUpdateWhenAlreadyExistingCar()
{
//Arrange
MockRepository mocks = new MockRepository();
IDataAccess dataAccess = mocks.CreateMock<IDataAccess>();
ObjectFactory.InjectStub(typeof(IDataAccess), dataAccess);
//Act
Car car = new Car();
Expect.Call(dataAccess.Save(car)).Return(389);
mocks.ReplayAll();
car.Save();
mocks.VerifyAll();
// Assert
Assert.AreEqual(389, car.Id);
ObjectFactory.ResetDefaults();
}
}
Ответ 2
Посмотрите настройки тестового оборудования, которые позволят вам указать функции, которые будут выполняться перед любым из тестов в приборе. Это позволяет вам выполнить общую настройку один раз, и она всегда будет работать, независимо от того, запускаете ли вы один тест или все тесты в пакете.
Ответ 3
Единичные тесты предназначены для автономной работы, а не для последовательного script. Если вам действительно нужно, чтобы они выполнялись последовательно, соберите их в одну тестовую функцию.
Если ваши тесты устройств страдают от дорогой настройки, вы можете проводить интеграционное тестирование, когда считаете, что выполняете модульное тестирование. Если вы попадаете в базу данных SQL в большинстве своих модульных тестов, вы фактически тестируете интеграцию с уровнем доступа к данным.
Ответ 4
Я бы рассматривал каждый тест как полностью независимый от любого другого теста. Даже если вы можете назначить порядок испытаний, это будет кошмар для обслуживания, когда тесты должны измениться.
Ответ 5
Я действительно не стал бы полагаться на заказ тестов. Вместо этого я бы вытащил общий код установки в отдельный метод и вызвал это как из простого теста, так и из более сложного. Кроме того, просто вызовите тест вставки в начале теста удаления.
Ответ 6
Я бы настоятельно советовал сделать все ваши модульные тесты независимыми.
Ваша бизнес-логика/структура базы данных и т.д. может со временем меняться, так что вам в конечном итоге придется заменить или переписать (или даже отказаться) существующие модульные тесты - и если у вас есть несколько других тестов в зависимости от того, повторная замена, это может вызвать ненужные проблемы, потому что вам придется пройти все остальные тесты и проверить, продолжают ли они работать, как ожидалось.
Кроме того, один неудачный unit test не должен перетаскивать многие другие (которые могут отлично работать самостоятельно) вниз.
Ответ 7
К сожалению, порядок работы unit test не предсказуем или, по крайней мере, может быть изменен в будущем. Например. модульная структура тестирования будет изменена, чтобы каждый тест выполнялся в отдельном потоке.
Поэтому с моей точки зрения использование тестового заказа нецелесообразно.
С другой стороны, вы можете создать набор небольших независимых тестов для проверки небольших частей вашего кода, а затем создать один или несколько крупных тестов, которые будут запускать ваши небольшие тесты в определенном порядке.
Ответ 8
Если у вас есть тесты с состоянием (общая проблема с работой базы данных - это то, что я делаю, когда я не нахожусь на SO), то мне кажется, что избежать порядка в тестовом файле не является абсолютно необходимым. Тем не менее, вы должны признать, что если у вас есть 2 теста с испытанием 2 в зависимости от прохождения теста 1, тогда вы получите "катастрофический" двойной сбой, если тест 1 завершится неудачно, потому что тест 2 не имеет ожидаемой установки (и, что еще, вы хотите волноваться, если тест 2 пройдет после того, как тест 1 провалился, если вы считаете, что тест 2 зависит от прохождения теста 1).
Вот почему вы хотите, чтобы тесты были независимы по возможности - как внутри файла, так и между файлами.
Было бы очень неразумно зависеть от порядка между (наборами) тестов в разных файлах.