2014-10-07 2 views
1

У меня есть большая программа, для которой мне нужно написать тесты. Мне интересно, было бы неправильно писать тесты, которые выполняются в определенном порядке, поскольку некоторые из них обязательно должны выполняться по порядку и зависят от предыдущего теста.Является ли модульное тестирование в заказе невосприимчивым?

Например сценарий вроде следующего:

  • CreateEmployer
    • CreateEmployee (требует работодатель)
    • Добавить департаменту

Недостаток я вижу в этот подход что если один тест не удастся, все последующие тесты также потерпят неудачу. Но в любом случае мне придется писать код для создания базы данных, поэтому может быть более эффективным подходом к использованию кода, который создает базу данных mock как своего рода интегральный тест, подобный интеграции.

Должен ли я создать базу данных без использования тестов в качестве метода семени, а затем снова запустить каждый из методов, чтобы увидеть результат? Проблема, которую я вижу при таком подходе, заключается в том, что если метод семян не работает, все тесты потерпят неудачу, и сразу не станет ясно, что ошибка заключается в методе семян, а не в самих сервисах или самих тестах.

ответ

2

Да, это обескураживает. Тесты не должны быть «временно связаны».

Каждый тест должен выполняться в полной изоляции других испытаний. Если вы окажетесь в ситуации, когда артефакты, созданный Тест А нужны испытания В то у вас есть две проблемы, чтобы исправить:

  • Испытание А не должны быть создание артефактов (или побочных эффектов).
  • Тест B должен использовать макет данных как часть его «аранжировки».

В основном, модульные тесты не должны использоваться с реальной базой данных. Они должны тестировать логику кода, а не взаимодействие с зависимостями инфраструктуры. Выделите эти зависимости, чтобы проверить только код.

+0

Имеет смысл. Я предполагаю, что то, что я описываю, будет скорее интеграционным тестом. Дайте этим модульным тестам не тестировать взаимодействие с базой данных и только логику, я могу думать о нескольких местах, где мне действительно нужны тесты. Кажется расточительным для проверки того, что по существу является функцией setter'a. Department = foo'. Я бы сказал, что около 2% моего кода имеет логику, которая не является тривиальной. –

+1

@ RaySülzer: Ну, вы не будете * напрямую * тестируете простые сеттеры. Вы проверили бы бизнес-операции, и логика, выполняемая в этих операциях, вызовет сеттеры. (Если они * не * вызывают сеттеры, то ни одна из ваших бизнес-операций * не использует * эти сеттеры, а сеттеры должны быть полностью удалены из кода.) Для тестов интеграции вы хотите полностью удалить логику из тестов и тестируют только сами точки интеграции (обычно операции DAL). Есть некоторые варианты там, в зависимости от того, что работает для вашей команды. Но временная связь все равно должна быть удалена. – David

+0

Спасибо! Большинство моих вызовов службы - простые сеттеры, чем вызов _orm.Update (object). Только некоторые из моих функций действительно требуют бизнес-логики, которая должна быть объединена. Это довольно простая программа. –

2

Плохая идея иметь модульные тесты зависят друг от друга. В вашем примере у вас может быть дефект как в CreateEmployer, так и в AddDepartment, но когда все три не работают из-за теста CreateEmployer, вы можете ошибочно предположить, что только тест CreateEmployer «действительно» не работает. Это означает, что вы потеряли потенциально ценную информацию, которую также добавляет AddDepartment.

Другая проблема заключается в том, что в будущем вы можете создать отдельный рабочий процесс, который вызывает AddDepartment без вызова CreateEmployer. Теперь ваши тесты предполагают, что CreateEmployer всегда будет вызван, но на самом деле это не так. Все три теста могут пройти, но приложение все равно может сломаться, потому что у вас есть зависимость, которую вы не знали.

Лучшие тесты не будут полагаться на базу данных вообще, но вместо этого вы сможете вручную указать или «Макет» данных. Тогда вам не нужно беспокоиться о неподдельной проблеме с базой данных, нарушающей все ваши тесты.

1

Если это действительно модульные тесты, то да, требующий определенного порядка, является плохой практикой по нескольким причинам.

  1. Сцепление. Как вы указываете, если один тест не удался, то последующие также потерпят неудачу. Это замаскирует реальные проблемы.
  2. TDD - Основной принцип TDD - это простой в использовании тест. Если вы это сделаете, разработчики с большей вероятностью будут запускать их. Если их трудно запускать (например, я должен запускать весь пакет), то они с меньшей вероятностью будут запущены, и их значение будет потеряно.
1

В идеале, модульные испытания не должны зависеть от завершения другого испытания для его запуска. Также трудно запускать их в заданной последовательности, но это может зависеть от вашего инструмента тестирования устройства.

В вашем примере я бы создал тест, который проверяет метод CreateEmployer и гарантирует, что он вернет новый объект так, как вы ожидаете.

Второй тест, который я бы создал, будет CreateEmployee, и если для этого теста требуется объект Employer, используя инъекцию зависимостей, ваш метод CreateEmployee может получить объект Employer. Здесь вы должны использовать макетный объект (тот, который создается для создания кода, возвращая фиксированный/известный работодатель) в качестве объекта Employer, который будет использовать метод CreateEmployee. Это позволяет протестировать метод CreateEmployee и его действия на этом объекте с данным/известным экземпляром объекта Employer.

Ваш третий тест, AddDepartment, я полагаю, также зависит от объекта Employer. Этот модульный тест может следовать одному и тому же шаблону и получать притворный объект Employer потребителю во время его теста. (Тот же объект, который вы переходите на единичный тест, приведенный выше.)

Каждый тест теперь запускается/сбой сам по себе и может работать в любой последовательности.

Смежные вопросы