Как далеко я должен пойти с поблочным тестированием?

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

, Если Вы просто используете его внутренне, Вы не можете заботиться так, и использование List<T> может быть в порядке.

6
задан Esteban Küber 29 July 2009 в 14:20
поделиться

8 ответов

Самое замечательное в модульном тестировании, по крайней мере для меня, это то, что оно показывает вам, где вам нужно провести рефакторинг. Используя приведенный выше пример кода, в одном методе, по сути, происходит четыре вещи:

//1. get the user from the DB
//2. in a big else, check if user is null
//3. create a array containing the userID, a code, and expiry
//4. delete any existing password resets
//5. create a new password reset

Модульное тестирование также великолепно, поскольку помогает выявить зависимости. Этот метод, как показано выше, зависит от БД, а не от объекта, реализующего интерфейс. Этот метод взаимодействует с системами, выходящими за пределы его области, и действительно может быть протестирован только с помощью интеграционного теста, а не модульного теста. Модульные тесты предназначены для проверки работоспособности / правильности единицы работы.

Рассмотрим Принцип единой ответственности : « Делай одно дело ». Это применимо как к методам, так и к классам.

I ' d предложить, чтобы ваш метод generatePasswordReset был реорганизован, чтобы:

  • получить предварительно определенный существующий объект / идентификатор пользователя. Проведите все эти проверки работоспособности вне этого метода. Сделайте одно:
  • поместите код сброса пароля в отдельный метод. Это была бы единая единица работы, которую можно было бы протестировать независимо от SELECT , DELETE и INSERT .
  • Создайте новый метод, который можно было бы вызвать OverwriteExistingPwdChangeRequests () , который позаботится об DELETE + INSERT.
6
ответ дан 9 December 2019 в 22:38
поделиться

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

Один способ справиться с обновлениями состояния удаленных объектов, подобных этому, - создать фиктивный объект, который предоставляет тот же интерфейс, что и БД (т.е. он выглядит идентично с точки зрения вашего кода). Затем в своем тесте вы можете проверить изменения состояния внутри этого фиктивного объекта и подтвердить, что получили то, что должны.

3
ответ дан 9 December 2019 в 22:38
поделиться

Вы можете еще немного разобрать его, эта функция делает много, что делает ее тестирование немного сложным, не невозможным, но и запутанным. Если, с другой стороны, вы вытащили несколько дополнительных функций меньшего размера (getUserByUsername, deletePasswordByUserID, addPasswordByUserId и т. Д., То вы можете достаточно легко протестировать их один раз и знать, что они работают, поэтому вам не нужно тестировать их снова. down, чтобы убедиться, что они исправны, поэтому вам не нужно беспокоиться о них дальше по цепочке. Затем для этой функции все, что вам нужно сделать, это передать ее несуществующему пользователю и убедиться, что он возвращается с ошибкой USER_DOESNT_EXIST затем тот, в котором пользователь действительно существует (здесь вы тестируете БД). Внутренние работы уже были выполнены в другом месте (надеюсь).

1
ответ дан 9 December 2019 в 22:38
поделиться

В общем, можно «имитировать» вызываемый вами объект, проверяя, что он получает ожидаемые запросы.

В этом случае я не уверен, насколько это полезно, вы почти закончили напишите ту же логику дважды ... мы думали, что отправили "УДАЛИТЬ из пароля" и т. д. О, смотрите, мы сделали!

Хммм, что мы на самом деле проверили. Если строка была сформирована неправильно, мы не узнаем!

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

0
ответ дан 9 December 2019 в 22:38
поделиться

Тестирование общедоступного интерфейса необходимо, но этого недостаточно. Существует множество философий относительно того, сколько требуется тестирования, и я могу высказать только свое мнение. Все протестировать. Буквально. У вас должен быть тест, который проверяет, что каждая строка кода проверена набором тестов. (Я говорю «каждая строка» только потому, что имею в виду C и gcov, а gcov обеспечивает детализацию на уровне строк. Если у вас есть инструмент с более высоким разрешением, используйте его.) Если вы можете добавить кусок кода в свой кодовая база без добавления теста, набор тестов должен завершиться ошибкой.

0
ответ дан 9 December 2019 в 22:38
поделиться

Модульные тесты служат для проверки того, что модуль работает. Если вы хотите узнать, работает ли модуль, напишите тест. Это так просто. Выбор написания модульного теста не должен основываться на какой-либо диаграмме или практическом правиле. Как профессионал, вы обязаны предоставить рабочий код, и вы не можете знать, работает он или нет, пока не протестируете его.

Это не значит, что вы пишете тест для каждой строки кода. Это также не обязательно означает, что вы пишете модульный тест для каждой отдельной функции. Решение тестировать или не тестировать конкретную единицу работы сводится к риску. Насколько вы готовы рискнуть, что ваш кусок непроверенного кода будет развернут?

Если вы спрашиваете себя: «Как мне узнать, работает ли эта функция», ответ будет: «Нет,

1
ответ дан 9 December 2019 в 22:38
поделиться

Базы данных - это глобальные переменные. Глобальные переменные - это открытые интерфейсы для каждого устройства, которое их использует. Поэтому ваши тестовые примеры должны варьировать входные данные не только для параметра функции, но и для входных данных базы данных.

0
ответ дан 9 December 2019 в 22:38
поделиться

Если у ваших модульных тестов есть побочные эффекты (например, изменение базы данных), то они становятся интеграционными тестами . В интеграционных тестах нет ничего плохого; любое автоматическое тестирование положительно сказывается на качестве вашего продукта. Но интеграционные тесты имеют более высокие затраты на обслуживание , потому что они более сложные и их легче взломать

. Таким образом, уловка состоит в том, чтобы минимизировать код, который можно протестировать только с побочными эффектами. Изолируйте и скройте запросы SQL в отдельном классе MyDatabase , который не содержит никакой бизнес-логики. Передайте экземпляр этого объекта в код бизнес-логики.

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

См. пример в документации SimpleTest (фреймворк имитации php).

0
ответ дан 9 December 2019 в 22:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: