Позвольте мне начать с подключения источников - Pragmatic Unit Testing на Java с помощью JUnit (есть версия с C # -Nunit ... но у меня есть эта ... по большей части ее агностик. Рекомендуется.)
Хорошие тесты должны быть ПОЕЗДКОЙ (The acronymn не липкие достаточно - у меня есть распечатка Cheatsheet в книге , которую я должен был вытащить , чтобы убедиться , что я получил это право ..)
- Автоматически : запуск тестов, а также проверка результатов на ПРОЙДЕН / ОТКАЗ должны быть автоматическими.
- Тщательно : покрытие; Хотя ошибки имеют тенденцию группироваться в определенных областях кода, убедитесь, что вы протестировали все ключевые пути и сценарии. Используйте инструменты, если вам необходимо знать непроверенные области.
- Повторяемость : тесты должны давать одни и те же результаты каждый раз ... каждый раз. Тесты не должны полагаться на неконтролируемые параметры.
- Независимый : Очень важно.
- Тесты должны проверять только одно за раз. Множественные утверждения допустимы, если все они тестируют одну функцию / поведение. Когда тест не проходит, он должен точно определить местонахождение проблемы.
- Тесты не должны полагаться друг на друга - изолированные. Никаких предположений о порядке выполнения тестов. Обеспечивайте «чистый лист» перед каждым тестом, используя надлежащую настройку / разборку
Профессионал : в долгосрочной перспективе у вас будет столько же тестового кода, сколько в продукте (если не больше), поэтому следуйте тому же стандарту хорошего дизайна для вашего тестового кода. Хорошо продуманные методы-классы с раскрывающими намерение именами, без дублирования, тесты с хорошими именами и т. Д.
Хорошие тесты также проходят быстро . любой тест, на выполнение которого уходит более полсекунды ... необходимо доработать. Чем дольше тестовый набор запускается ... тем реже он будет запускаться. Чем больше изменений попытается внести разработчик между запусками ... если что-то сломается ... потребуется больше времени, чтобы выяснить, какое изменение было причиной.
Обновление 2010-08:
- Разборчиво : это можно считать частью Professional, но это не может быть достаточно подчеркнуто. Кислотным испытанием было бы найти кого-то, кто не является частью вашей команды, и попросить его / ее выяснить поведение при тестировании в течение нескольких минут. Тесты необходимо поддерживать так же, как и производственный код, поэтому облегчите чтение, даже если для этого потребуется больше усилий. Тесты должны быть симметричными (следовать шаблону) и краткими (тестировать одно поведение за раз). Используйте согласованное соглашение об именах (например, стиль TestDox). Избегайте загромождения теста «случайными деталями» ... станьте минималистом.
Помимо этого, большинство других представляют собой рекомендации, которые сокращают объем работы с низкой пользой: например, «Не тестируйте код, которым вы не владеете» (например, сторонние библиотеки DLL). Не пытайтесь тестировать геттеры и сеттеры. Следите за соотношением затрат и выгод или вероятностью дефекта.
источник
Большинство ответов здесь, похоже, относятся к лучшим практикам модульного тестирования в целом (когда, где, почему и что), а не к написанию самих тестов (как). Поскольку вопрос казался довольно конкретным в части «как», я решил опубликовать его, взятый из презентации «коричневого мешка», которую я проводил в своей компании.
5 законов написания тестов Вомпа:
1. Используйте длинные описательные названия методов тестирования.
2. Напишите свои тесты в стиле « Упорядочить / Действовать / Утвердить» .
3. Всегда предоставляйте сообщение о неудаче в своих утверждениях.
4. Прокомментируйте причину теста - каково бизнес-предположение?
5. Каждый тест всегда должен возвращать состояние любого ресурса, которого он касается.
источник
Помните об этих целях (адаптировано из книги Месароса «Шаблоны тестов xUnit»)
Некоторые вещи, чтобы упростить это:
Не забывайте, что вы также можете проводить интеграционное тестирование со своей структурой xUnit, но держите интеграционные тесты и модульные тесты отдельно.
источник
Тесты должны быть изолированными. Один тест не должен зависеть от другого. Более того, тест не должен полагаться на внешние системы. Другими словами, тестируйте свой код, а не код, от которого зависит ваш код. Вы можете протестировать эти взаимодействия как часть интеграционных или функциональных тестов.
источник
Некоторые свойства отличных модульных тестов:
Когда тест не проходит, должно быть сразу ясно, в чем проблема. Если вам нужно использовать отладчик для отслеживания проблемы, то ваши тесты недостаточно детализированы. Здесь помогает наличие ровно одного утверждения на тест.
При рефакторинге никакие тесты не должны терпеть неудачу.
Тесты должны выполняться так быстро, чтобы их можно было запускать без промедления.
Все тесты должны проходить всегда; нет недетерминированных результатов.
Модульные тесты должны быть хорошо продуманы, как и ваш производственный код.
@Alotor: Если вы предлагаете, чтобы библиотека имела только модульные тесты для внешнего API, я не согласен. Мне нужны модульные тесты для каждого класса, включая классы, которые я не предоставляю внешним вызывающим объектам. (Однако, если я чувствую необходимость писать тесты для частных методов, мне нужно провести рефакторинг. )
EDIT: был комментарий о дублировании, вызванном «одним утверждением на тест». В частности, если у вас есть код для настройки сценария, а затем вы хотите сделать несколько утверждений об этом, но у вас есть только одно утверждение для каждого теста, вы можете дублировать настройку для нескольких тестов.
Я не придерживаюсь такого подхода. Вместо этого я использую тестовые инструменты для каждого сценария . Вот примерный пример:
источник
Вам нужно описать поведение тестируемого класса.
Основная цель - повысить вашу уверенность в поведении класса.
Это особенно полезно при рефакторинге кода. У Мартина Фаулера есть интересная статья о тестировании на его веб-сайте.
HTH.
ура,
Роб
источник
Изначально тест должен завершиться неудачно. Затем вы должны написать код, который заставит их пройти, иначе вы рискуете написать тест, который содержит ошибки и всегда проходит.
источник
Мне нравится аббревиатура Right BICEP из вышеупомянутой книги Pragmatic Unit Testing :
Лично я считаю, что вы можете довольно далеко продвинуться, проверив, что вы получаете правильные результаты (1 + 1 должен возвращать 2 в дополнительной функции), опробовав все граничные условия, о которых вы можете подумать (например, используя два числа, из которых сумма больше, чем целочисленное максимальное значение в функции добавления) и форсирует условия ошибки, такие как сбои сети.
источник
Хорошие тесты должны быть поддерживаемыми.
Я не совсем понял, как это сделать для сложных сред.
Все учебники начинают распадаться по мере того, как ваш код начинает доходить до сотен тысяч или миллионов строк кода.
Хорошая архитектура может контролировать некоторые из взрывов взаимодействия, но неизбежно по мере того, как системы становятся более сложными, автоматизированная система тестирования растет вместе с ней.
Здесь вы начинаете сталкиваться с компромиссами:
Также необходимо решить:
где вы храните тестовые примеры в своей базе кода?
Я мог бы продолжать бесконечно, но я хочу сказать следующее:
Тесты должны быть обслуживаемыми.
источник
Я уже рассказывал об этих принципах в статье журнала MSDN Magazine, которую, как мне кажется, важно прочитать любому разработчику.
Я определяю «хорошие» модульные тесты, если они обладают следующими тремя свойствами:
источник
источник
У Джея Филдса есть много хороших советов по написанию модульных тестов, и есть пост, в котором он суммирует наиболее важные советы . Там вы прочитаете, что вам следует критически относиться к своему контексту и судить, стоит ли вам совет. Здесь вы получите массу потрясающих ответов, но решать вам, какой из них лучше всего подходит для вашего контекста. Попробуйте их и просто выполните рефакторинг, если вам это неприятно.
С уважением
источник
Никогда не предполагайте, что тривиальный двухстрочный метод будет работать. Написание быстрого модульного теста - единственный способ предотвратить укус вас отсутствующим нулевым тестом, неуместным знаком минус и / или малозаметной ошибкой области видимости, когда у вас еще меньше времени, чтобы разобраться с этим, чем сейчас.
источник
Я второй ответ "ПУТЕШЕСТВИЕ", за исключением того, что тесты ДОЛЖНЫ полагаться друг на друга !!!
Зачем?
DRY - Dont Repeat Yourself - применимо и к тестированию! Тестовые зависимости могут помочь 1) сэкономить время на настройку, 2) сэкономить ресурсы устройства и 3) выявить сбои. Конечно, только при условии, что ваша среда тестирования поддерживает первоклассные зависимости. В остальном, признаю, они плохие.
Следите за http://www.iam.unibe.ch/~scg/Research/JExample/
источник
Часто модульные тесты основаны на фиктивных объектах или фиктивных данных. Мне нравится писать три вида модульных тестов:
Дело в том, чтобы не проигрывать все заново , чтобы иметь возможность протестировать все функции.
источник
Подумайте о двух типах тестирования и относитесь к ним по-разному - функциональное тестирование и тестирование производительности.
Используйте разные входные данные и метрики для каждого. Для каждого типа теста может потребоваться разное программное обеспечение.
источник
Я использую согласованное соглашение об именах тестов, описанное в стандартах именования модульных тестов Роя Ошерова. Каждый метод в данном классе тестового примера имеет следующий стиль именования MethodUnderTest_Scenario_ExpectedResult.
Первый раздел имени теста - это имя метода в тестируемой системе.
Далее идет тестируемый конкретный сценарий.
Наконец, результаты этого сценария.
Каждый раздел использует верхний регистр верблюда и ограничен нижней оценкой.
Я обнаружил, что это полезно, когда я запускаю тест, тесты сгруппированы по имени тестируемого метода. И наличие соглашения позволяет другим разработчикам понять цель теста.
Я также добавляю параметры к имени метода, если тестируемый метод был перегружен.
источник