Подтвердить что ты не робот

Каким должен быть "блок" при модульном тестировании?

В Proggit сегодня я читал поток комментариев в представлении, озаглавленном " Почему модульное тестирование является отходами времени".

Я не очень беспокоюсь о посылке этой статьи, так как я с comment, сделанной по этому поводу:

Основой проблемы является то, что большинство "единиц" кода в бизнес-программном обеспечении проекты тривиальны.

Измените размер устройства, пока он уже не тривиальна? Кто черт возьми определил единицу кода как единую функции или метода в любом случае!?

и

Ну, некоторые из парней, с которыми я работал хотел определить единицу как единую функции. Это было совершенно глупо. Мое любимое определение "единица": самый маленький фрагмент кода, который могут быть успешно протестированы.

Проводим ли мы слишком много времени для того, чтобы вырезать некоторые объекты и протестировать тривиальный фрагмент кода и не добавить ничего полезного?

Каким должен быть "блок" при модульном тестировании? Являются ли тесты уровня производительности слишком зернистыми?

4b9b3361

Ответ 1

Может показаться тривиальным процитировать Wikipedia, но я считаю это очень кратким и точным в этом случае:

Единица является наименьшей проверяемой частью приложения.

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

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

Честно говоря, нет четкого или строгого определения "единицы" в "модульном тестировании", и именно поэтому используется неопределенный термин "единица"! Изучение того, что нужно протестировать, и на каком уровне это вопрос опыта, а нередко просто проб и ошибок. Это может показаться немного неудовлетворительным ответом, но я считаю, что это правильное правило.

Ответ 2

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

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

UPDATE: я всегда добавлял unit test, когда клиент или пользователь сообщают о крайнем случае, который нарушает взаимодействие в моем приложении. Исправить это недостаточно для меня - добавление unit test, чтобы гарантировать, что исправление удерживает, предотвращает регрессию и помогает сохранить стабильность на линии.

Ответ 3

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

Рациональность здесь весьма важна; вполне возможно написать модульные тесты для каждого аксессора каждого класса, который у вас есть; однако это явно overkill. Аналогичным образом, возможно, но глупо определять ваше приложение как единое целое и рассчитывать на проведение одного теста для его тестирования.

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

Здесь нужно указать, что единица, которую вы хотите протестировать, - это единица, которая имеет смысл. Вы хотите, чтобы модульное тестирование проверяло и проверяло функциональность; поэтому те тесты unit test - это то, что вы определяете как функциональность. Что такое блок функциональности? Это зависит от вашей индивидуальной ситуации.

Ответ 4

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

Например, если вы пытаетесь выполнить ряд шагов для обработки некоторых данных, например

  • сканировать набор данных для минимального, максимального, среднего, среднего
  • создать гистограмму
  • создать функцию переназначения
  • переназначить данные
  • вывод данных

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

Ответ 5

Ничто не является тривиальным, если вы принимаете во внимание Закон Мерфи.

Анекдоты и предполагая OO environement, я подхожу к Unit Testing, беря класс в качестве единицы, потому что часто различные методы изменяют внутреннее состояние, и я хочу быть уверенным, что состояние между различными методами согласовано.

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

Ответ 6

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

Ответ 7

Для меня "единица" - это какое-то значительное поведение класса, которое через 8-12 месяцев в будущем я не буду вспоминать.

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

Ответ 8

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

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

Итак, одним словом: mu.

Ответ 9

Измените размер устройства, пока он уже не тривиальна? Кто черт возьми определил единицу кода как единую функции или метода в любом случае!?

Если слишком сложно проверить "единицу", определенную как метод, то вполне вероятно, что этот метод слишком велик или сложен для создания unit test.

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

Я также использую mocks для проверки контрактов между компонентами.

Ответ 10

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

Там есть отличная статья с явным названием "Модульные тесты - это не тесты". Заголовок - наживка для кликов, и он отлично читается сам по себе, но здесь я остановлюсь только на важных моментах.

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

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

К сожалению, высокая способность к компоновке и эффекты появления не могут быть измерены инструментально, я могу только высказать несколько мыслей из головы:

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