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

Unit test принятие

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

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

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

Может кто-нибудь помочь определить проблему и как мы можем сделать модульные тесты для нас, а не против нас?

4b9b3361

Ответ 1

Советы:

Избегайте ввода процедурного кода

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

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

Найдите изменения, инкапсулируйте их и отделите их от того, что останется тем же.

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

  • Хорошая инкапсуляция приводит к хорошим, слабо связанным конструкциям.
  • Рефакторинг и модуляция.
  • Держите тесты маленькими и сфокусированными.

Чем больше контекст, окружающий тест, тем труднее будет поддерживать.

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

  • Используйте сложный метод рефакторинга для тестирования небольших фрагментов кода.
  • Используете ли вы новую платформу тестирования, например TestNG или JUnit4? Они позволяют удалять дублирование в тестах, предоставляя вам более тонкие крючки в жизненный цикл тестирования.
  • Изучите использование двойных тестов (mocks, fakes, stubs), чтобы уменьшить размер тестового контекста.
  • Изучите шаблон Test Data Builder.

Удалите дублирование из тестов, но убедитесь, что они сохраняют фокус.

Вероятно, вы не сможете удалить все дублирование, но все равно попытайтесь удалить его там, где он вызывает боль. Убедитесь, что вы не удаляете столько дублирования, что кто-то не может войти и сказать, что тест делает с первого взгляда. (См. Paul Wheaton "Evil Unit Tests" для альтернативного объяснения той же концепции.)

  • Никто не захочет исправить тест, если они не могут понять, что он делает.
  • Следуйте шаблону Arrange, Act, Assert Pattern.
  • Используйте только одно утверждение для каждого теста.

Проверьте на правильном уровне то, что вы пытаетесь проверить.

Подумайте о сложности, связанной с тестовым тестированием Selenium и тем, что может измениться под вами, и тестированием одного метода.

  • Изолировать зависимости друг от друга.
  • Использовать зависимость/инверсию управления зависимостями.
  • Использовать двойные тесты для инициализации объекта для тестирования и убедиться, что вы тестируете отдельные единицы кода в изоляции.
  • Убедитесь, что вы пишете соответствующие тесты
    • "Spring Ловушка", введя ошибку в цель и убедитесь, что она попадает в тест.
  • См. также: Интеграционные тесты являются мошенничеством

Знать, когда использовать тестирование на основе состояния и взаимодействия на основе

Истинные модульные тесты требуют истинной изоляции. Единичные тесты не попадают в базу данных или открытые сокеты. Прекратите насмехаться над этими взаимодействиями. Убедитесь, что вы правильно говорите со своими сотрудниками, а не то, что правильным результатом этого вызова метода было "42".

Продемонстрировать тестовый код

Он обсуждает, будет ли данная команда проходить тест-драйв всего кода или писать "тесты сначала" для каждой строки кода. Но должны ли они сначала написать хотя бы несколько тестов? Абсолютно. Существуют сценарии, в которых тест-первый, несомненно, лучший способ подойти к проблеме.

Ресурсы:

Ответ 2

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

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

Это стоит того, придерживайтесь его как можно лучше.

Ответ 3

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

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

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

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

  • Только утверждать, что тест необходимо. Не утверждайте на промежуточных, случайное или несвязанное состояние. Дизайнер контракт и испытание по контракту (например, если вы тестируете метод pop pop, не проверяйте свойство count после толкание - это должно быть отдельный тест).

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

  • Как и в случае с обычным кодом, используйте заводы и строители в ваших модульных тестах. Я узнал, что один, когда около 40 тестов потребовался вызов конструктора, обновленный после изменения API...

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

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

Ответ 4

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

Ответ 5

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

Исправьте код модульного тестирования на уровне набора и не часто меняйте свой код, особенно имена функций или другие модули.

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

Ответ 6

Хороший вопрос!

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

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

НТН

Ответ 7

Если проблема в том, что ваши тесты устаревают с фактическим кодом, вы можете сделать одно или оба:

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

Ответ 8

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

Ответ 9

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

Не сдавайтесь, пока его расстраивает, преимущество будет реализовано.

Ответ 10

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

  • Использование конкретных классов вместо интерфейсов
  • Использование синглетонов
  • Вызов множества статических методов для бизнес-логики и доступа к данным вместо методов интерфейса.

Из-за этого я обнаружил, что обычно мои тесты ломаются - не из-за изменения в тестируемом классе, а из-за изменений в других классах, которые вызывал тестируемый класс. В целом, классы рефакторинга, запрашивающие их зависимости данных и тестирование с помощью mock objects (EasyMock и др. Для Java), делают тестирование гораздо более целенаправленным и поддерживаемым. Мне очень понравились некоторые сайты, в частности, по этой теме:

Ответ 11

Почему вы должны менять модульные тесты каждый раз, когда вы вносите изменения в свою инфраструктуру? Разве это не должно быть наоборот?

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

Ответ 12

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

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

Когда вы приближаетесь к дате производства, вы будете счастливы, что у вас есть эти тесты, поверьте мне:)

Ответ 13

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

Вы должны протестировать интерфейс, а не внутреннюю реализацию.

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

Ответ 14

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

Существует тонкая линия с инструментом автоматизации, у вас наверняка будет лучший охват кода.

Тем не менее, с помощью тестов, основанных на проверке корректности, вы также проверите целостность системы.

Надеюсь, что это поможет.

Ответ 15

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

Рассмотрите возможность использования рефакторинга метода extract-метода, чтобы вытащить небольшие блоки кода, которые делают одно и только одно; без зависимостей, и напишите ваши тесты тем небольшим методам.

Ответ 16

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

Альтернативой является то, что когда ваша Framework изменяется, вы не проверяете изменения. Или вы вообще не проверяете Framework. Это то, что вы хотите?

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

Ответ 17

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

Моя точка зрения заключается в том, что многие из новых технологий разработки программного обеспечения работают только при совместном использовании. В частности, MVC, ORM, IoC, модульное тестирование и Mocking. DDD (в современном примитивном смысле) и TDD/BDD более независимы, поэтому вы можете их использовать или нет.

Ответ 18

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

Ответ 19

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