Жестко запрограммированные и ожидаемые значения в мягком коде для тестирования интеграции - PullRequest
0 голосов
/ 18 февраля 2019

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

Однако для тестирования интеграции все еще применяется тот же принцип?Для контекста, вот общий сценарий:

  • TodoController
  • TodoService
  • Сериализатор / Трансформатор / Как бы вы это ни называли

Вотвоображаемый код того, как могут выглядеть оба подхода:

  • с жестким кодом
// Arrange
$note = new Note('note123', 'John', 'example message');

$this->noteRepository->save($note);

// Act
$response = $this->json('GET', '/api/notes');

// Assert
$response->seeJsonEquals([
   'id' => 'note123',
   'author' => 'John',
   'message' => 'example message'
]);

  • с мягким кодом (вычислено)
// Arrange
$note = new Note('note123', 'John', 'example message');

$this->noteRepository->save($note);

// Act
$response = $this->json('GET', '/api/notes');

// Assert
$noteSerializer = new NoteSerializer();

$response->seeJsonEquals($noteSerializer->serialize($note));

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

Однако мы можем решить это с помощьюсоздание еще одного теста для Serializer.

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

Возможно, я что-то упустил, но я уже пытался Googleэто и все, что я вижу, всегда касаются модульных тестов, поэтому я подумал спросить, применяется ли тот же принцип и в интеграционных тестах

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

В вашем конкретном примере использование NoteSerializer не имело смысла, потому что ваши утверждения строятся с тем же кодом, что и реализация.

Вы бы назвали этот тест ценным?

// Arrange
$original = 42;
$expected = $original + 100;

// Act
$actual = $original + 100;

// Assert
this-> assertEquals($expected, $actual);

Проблема с использованием NoteSerializer для построения ожидаемого значения заключается в том, что, как вы уже заметили, если сериализатор не работает - тесты останутся зелеными.

Вместо этого вы можете десериализовать полученный ответ в класс и сравнить его с исходным $note

0 голосов
/ 19 февраля 2019

TL; DR: да, имеет смысл иметь интеграционные тесты, предполагающие, что другие стратегии тестирования разделяют ответственность за обнаружение ошибок.

Я думаю, вы обнаружите, что здесь есть две разные идеи, которые смешиваются.

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

UltimateAnswer lifeTheUniverseAndEverything = deepThought()

// Compare this
assertEquals(new UltimateAnswer(42), lifeTheUniverseAndEverything);

// to this
assertEquals(42, lifeTheUniverseAndEverything.toInt());

Что считается независимым?Я считаю, что это нечеткая строка - если у нас было достаточно тестов, чтобы иметь какое-то произвольное число девяток с уверенностью в UltimateAnswer :: equals, то было бы неплохо рассматривать эту проверку как независимую.С другой стороны, я был сожжен, по крайней мере, дважды, используя независимые от домена примитивы для «независимой» проверки того, что все работает, только для того, чтобы обнаружить, что я фактически выполняю зависимую проверку, и тесты не удавались.поймать ошибку, которую я ожидал.

Вторая проблема связана с подгонкой - часто бывает так, что ряд различимых видов поведения может быть удовлетворительным.Пример: каким должен быть результат List.shuffle()?Если тесты предназначены для описания ваших требований , то они будут более щадящими, чем тесты, в которых документируется пример поведения.

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

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

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

...