Как вы оцениваете качество ваших юнит-тестов? - PullRequest
35 голосов
/ 04 ноября 2008

Если вы (или ваша организация) стремитесь провести тщательное модульное тестирование своего кода, как вы оцениваете успех или качество ваших усилий?

  • Используете ли вы покрытие кода, на какой процент вы рассчитываете?
  • Считаете ли вы, что такие философии, как TDD, оказывают большее влияние, чем метрики?

Ответы [ 13 ]

34 голосов
/ 04 ноября 2008

Мой совет - не способ определить, есть ли у вас хорошие модульные тесты как таковые, но это способ вырастить хороший набор тестов с течением времени.

Всякий раз, когда вы сталкиваетесь с ошибкой, либо в процессе разработки, либо сообщенной кем-то еще, исправьте ее дважды. Сначала вы создаете модульный тест, который воспроизводит проблему. Когда у вас есть провальный тест, вы идете и решаете проблему.

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

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

Кроме того, +1 для значения и ловушек тестового покрытия, уже упомянутых другими.

12 голосов
/ 04 ноября 2008

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

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

9 голосов
/ 04 ноября 2008

Я очень сторонник TDD, но я не придаю особого значения статистике покрытия. Для меня успех и полезность модульных тестов ощущается в течение периода разработки командой разработчиков, так как тесты (а) обнаруживают ошибки заранее, (б) позволяют рефакторинг и изменения без регрессии, (в) помогают раскрыть модульная, отделенная конструкция, (d) и еще много чего.

Или, как выразился Мартин Фаулер, неподтвержденные данные в поддержку модульных тестов и TDD огромны, но вы не можете измерить производительность. Подробнее о его бликах здесь: http://www.martinfowler.com/bliki/CannotMeasureProductivity.html

8 голосов
/ 04 ноября 2008

Чтобы достичь полной уверенности в своем коде, вам нужны разные уровни тестирования: модульное, интеграционное и функциональное. Я согласен с приведенным выше советом, в котором говорится, что тестирование должно быть автоматическим (непрерывная интеграция) и что модульное тестирование должно охватывать все ветви с различными наборами данных пограничного уровня. Инструменты покрытия кода (например, Cobertura, Clover, EMMA и т. Д.) Могут выявлять дыры в ваших ветвях, но не в качестве ваших тестовых наборов данных. Статический анализ кода, такой как FindBugs, PMD, CPD, может выявить проблемные области в вашем коде, прежде чем они станут проблемой, и пройти долгий путь к продвижению лучших методов разработки.

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

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

В целом, я бы поддержал подход разработки, основанный на тестировании, основанный на некоторой разновидности автоматического модульного тестирования (JUnit, nUnit и т. Д.). Для интеграционного тестирования я бы порекомендовал иметь тестовую базу данных, которая автоматически заполняется при каждой сборке известным набором данных, который иллюстрирует распространенные случаи использования, но позволяет использовать другие тесты. Для функционального тестирования вам понадобится какой-нибудь робот с пользовательским интерфейсом (SeleniumRC для веб-сайтов, Abbot для Swing и т. Д.). Метрики каждого из них могут быть легко собраны в процессе сборки и отображены на CI-сервере (например, Hudson) для просмотра всеми разработчиками.

8 голосов
/ 04 ноября 2008

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

6 голосов
/ 04 ноября 2008

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

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

Например, покрытие кода глубоко вводит в заблуждение, потому что покрытие кода на 100% далеко от полного покрытия теста. Кроме того, цифра типа «80% покрытия кода» также вводит в заблуждение без контекста. Если это покрытие находится в самых сложных битах кода и просто пропускает код, который настолько прост, что это легко проверить на глаз, тогда это значительно лучше, чем если бы это покрытие было смещено в обратном направлении.

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

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

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

5 голосов
/ 04 ноября 2008

Обычно я делаю TDD, поэтому сначала пишу тесты, которые помогают мне понять, как я хочу использовать объекты.

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

Помимо этого и получения максимально возможного покрытия кода (иногда невозможно получить 100%), вы более или менее готовы. Затем, если в будущем появятся какие-либо ошибки, вы просто должны написать для него тестовый пример, который сначала его обнаружит и пройдет, когда будет исправлено. Затем исправить в соответствии с нормой.

5 голосов
/ 04 ноября 2008

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

3 голосов
/ 05 ноября 2008

Мониторинг коэффициентов покрытия кода может быть полезен, но вместо того, чтобы сосредоточиться на произвольной целевой ставке (80%, 90%, 100%?), Я считаю полезным стремиться к положительной тенденции во времени.

2 голосов
/ 04 ноября 2008

Я думаю, что некоторые лучшие практики для юнит-тестов:

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

Не ожидайте достижения 100% покрытия кода, если вы не разрабатываете критически важное программное обеспечение. Достижение этого уровня может быть очень дорогостоящим, и для большинства проектов оно не будет стоить усилий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...