Приведенный в действие этим потоком , я (снова) думаю об окончательном использовании модульных тестов в моих проектах. Несколько постеров там говорят что-то вроде «Тесты - это круто, если они хорошие тесты». Мой вопрос сейчас: что такое "хорошие" тесты?
В моих приложениях основная часть часто представляет собой некий числовой анализ, зависящий от большого количества наблюдаемых данных, и приводящий к функции подгонки, которую можно использовать для моделирования этих данных. Я обнаружил, что особенно сложно создавать тесты для этих методов, поскольку число возможных входных данных и результатов слишком велико, чтобы просто протестировать каждый случай, а сами методы часто бывают довольно длинными и не могут быть легко подвергнуты рефакторингу без ущерба для производительности. Я особенно заинтересован в «хороших» тестах для этого метода.
источник
Ответы:
Искусство модульного тестирования может сказать следующее о модульных тестах:
а затем добавляет, что он должен быть полностью автоматизированным, надежным, читаемым и обслуживаемым.
Я настоятельно рекомендую прочитать эту книгу, если вы еще этого не сделали.
На мой взгляд, все это очень важно, но последние три (заслуживающие доверия, удобочитаемые и поддерживаемые) особенно, как если бы у ваших тестов были эти три свойства, то и у вашего кода они тоже есть.
источник
It should run at the push of a button
, означает ли это, что модульное тестирование не должно требовать запуска ни контейнеров (сервера приложений) (для тестируемого модуля), ни соединения с ресурсами (например, БД, внешние веб-службы и т. д.)? Я просто запутался, какие части приложения должны тестироваться модульно, а какие нет Мне сказали, что модульные тесты не должны зависеть от соединения с БД и работы контейнеров и, возможно, вместо этого использовать макеты.Хороший модульный тест не отражает функцию, которую он тестирует.
В качестве упрощенного примера рассмотрим функцию, которая возвращает в среднем два целых числа. Самый полный тест будет вызывать функцию и проверять, является ли результат на самом деле средним. Это не имеет никакого смысла: вы копируете (копируете) функциональность, которую тестируете. Если вы допустили ошибку в основной функции, вы сделаете ту же ошибку в тесте.
Другими словами, если вы обнаружите, что копируете основные функции в модульном тесте, это, вероятно, признак того, что вы тратите свое время впустую.
источник
Хорошие юнит-тесты - это, по сути, спецификация в работоспособном виде:
Я обнаружил, что Test-Driven-Development очень хорошо подходит для библиотечных подпрограмм, поскольку вы сначала пишете API, а затем - реальную реализацию.
источник
для TDD «хорошие» тесты тестируют функции, которые хочет заказчик ; функции не обязательно соответствуют функциям, и тестовые сценарии не должны создаваться разработчиком в вакууме
в вашем случае - я предполагаю - «особенность» заключается в том, что функция подгонки моделирует входные данные в пределах определенной погрешности. Поскольку я понятия не имею, что вы на самом деле делаете, я что-то придумываю; Надеюсь, это анальгетик.
Пример истории:
Итак, вы идете поговорить с пилотами (и с целевым компьютером, если разум). Сначала вы говорите о том, что является «нормальным», затем говорите о ненормальном. Вы узнаете, что действительно имеет значение в этом сценарии, что является общим, что маловероятным, а что просто возможно.
Предположим, что обычно у вас будет полсекундное окно по семи каналам телеметрических данных: скорость, угол наклона, крен, рыскание, вектор цели, размер цели и скорость цели, и что эти значения будут постоянными или изменяются линейно. Ненормально у вас может быть меньше каналов и / или значения могут быстро меняться. Итак, вместе вы придумаете несколько тестов, таких как
Теперь вы, возможно, заметили, что нет сценария для конкретной ситуации, описанной в истории. После разговора с заказчиком и другими заинтересованными сторонами выясняется, что цель в оригинальной истории была лишь гипотетическим примером. Настоящие испытания вышли из последовавшего обсуждения. Это может случиться История должна быть переписана, но это не обязательно [так как история - просто место для разговора с клиентом].
источник
Создайте тесты для угловых случаев, например, набор тестов, содержащий только минимальное количество входов (возможно 1 или 0) и несколько стандартных случаев. Эти юнит-тесты не являются заменой для тщательных приемочных испытаний и не должны быть ими.
источник
Я видел много случаев, когда люди вкладывают огромные усилия в написание тестов для редко вводимого кода, а не в написание тестов для часто вводимого кода.
Прежде чем приступить к написанию каких-либо тестов, вы должны посмотреть на диаграмму вызовов, чтобы убедиться, что вы планируете адекватный охват.
Кроме того, я не верю в написание тестов просто ради того, чтобы сказать: «Да, мы тестируем это». Если я использую библиотеку, которая вставлена и останется неизменной, я не собираюсь тратить день на написание тестов, чтобы убедиться, что внутренности API, которые никогда не изменятся, работают должным образом, даже если определенные его части оцениваются высоко на графе вызовов. Тесты , которые потребляют указанную библиотеку (мой собственный код) указать на это.
источник
Не совсем так, TDD, но после того, как вы вошли в QA, вы можете улучшить свои тесты, настроив тестовые случаи для воспроизведения любых ошибок, возникающих в процессе QA. Это может быть особенно ценно, когда вы получаете долгосрочную поддержку и начинаете добираться до места, где вы рискуете людьми непреднамеренно повторно вводить старые ошибки. Наличие теста на месте, чтобы захватить это особенно ценно.
источник
Я стараюсь, чтобы каждый тест проверял только одну вещь. Я пытаюсь дать каждому тесту имя, как следует DoDoSomething (). Я пытаюсь проверить поведение, а не реализацию. Я тестирую только публичные методы.
У меня обычно есть один или несколько тестов на успех, а затем, может быть, несколько тестов на провал для каждого публичного метода.
Я часто использую макеты. Хорошие фреймворки, вероятно, были бы весьма полезны, такие как PowerMock. Хотя я пока не пользуюсь.
Если класс A использует другой класс B, я бы добавил интерфейс X, чтобы A не использовал B напрямую. Затем я бы создал макет XMockup и использовал его вместо B в своих тестах. Это действительно помогает ускорить выполнение теста, уменьшить сложность теста, а также уменьшает количество тестов, которые я пишу для A, так как мне не приходится справляться с особенностями B. Я могу, например, проверить, что A вызывает X.someMethod () вместо побочного эффекта вызова B.someMethod ().
Держите тестовый код в чистоте.
При использовании API, такого как уровень базы данных, я смоделировал бы его и включил макет, чтобы вызвать исключение при каждой возможности команды. Затем я запускаю тесты один без броска, и в цикле, каждый раз выбрасывая исключение при следующей возможности, пока тест не завершится снова. Немного похоже на тесты памяти, доступные для Symbian.
источник
Я вижу, что Андри Лоури уже опубликовал метрики модульных тестов Роя Ошерова; но, похоже, никто не представил (бесплатный) набор, который дядя Боб дает в Чистом коде (132-133). Он использует аббревиатуру ПЕРВЫЙ (здесь с моими резюме):
источник