Что вы можете сделать с качеством существующих интеграционных и модульных тестов, будучи новым парнем в команде?

21

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

Во время собеседования администрация говорит вам, что они «решительно поддерживают юнит-тестирование» и открыто его поощряют. Они делают, но все в самих тестах просто неправильно. Например, тот факт, что они заявляют о 100% -ном покрытии, когда есть 100-процентное покрытие интеграционных тестов, но менее чем 10-процентное повторяемое покрытие модульных тестов. Некоторые другие проблемы, которые я обнаружил:

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

  2. Интеграционные тесты, которые имеют необъявленные явные зависимости от очень специфических динамических данных в базе данных конкретной среды.

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

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

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

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

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

Что вы делаете, когда попадаете в эту ситуацию? Какой, по вашему мнению, лучший план атаки заключается в том, чтобы заняться чем-то вроде этого?

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

maple_shaft
источник
6
Добро пожаловать в реальный мир, приятель.
tdammers
20
Будьте счастливы, у вас есть тестирование.
Джоэл Этертон
3
Почему вы работаете в компаниях, которые явно ниже вашего уровня компетенции?
TrojanName
3
@ Брайан, я ценю удар эго, но без большего количества людей, думающих как я, эти компании никогда не поднимутся выше. Это первый раз, когда я нахожусь в реальной власти, так как раз я разработал скромное политическое значение. У меня есть реальная возможность направить ресурсы, чтобы сделать вещи лучше. Я еще не нашел компанию, которая была бы идеальной без работы. Это как идеальный муж или жена, они не просто приходят, приходит достаточно хороший человек, а затем вы превращаете их в того, кем вы хотите, чтобы они были;)
maple_shaft
1
Я думаю, что мы могли бы работать на одну команду. Теперь вы (и я) знаете, как на самом деле задавать вопросы во время наших следующих интервью. (На самом деле, моя среда не имеет почти 100% или даже 10% охвата интеграционными тестами [настоящие юнит-тесты? Это сумасшедший разговор!], Но вы прибили все остальные моменты, с которыми я имею дело.)
Энтони Пеграм,

Ответы:

6

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

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

Лучшей идеей будет попытаться поговорить с ними, чтобы они могли участвовать в усилиях, и у вас будет меньше шансов выступить в роли умницы, это будет больше «мы», чем «я».

Теперь расставьте приоритеты в том, что вы хотите сделать. Расставьте приоритеты задач, всегда зная, что вашим первым приоритетом всегда будет текущее задание проекта ... Что касается вашей тестовой задачи, вот что я бы сделал, в три этапа:

  1. Как сделать разницу между модульными и интеграционными тестами? Следующие решения могут применяться и не являются исключительными:

    • Рефакторинг имени методов тестового набора (не классов, так как правильное поведение - иметь тестовый набор с тем же именем, что и у тестируемого класса)
    • Создайте две аннотации, одну с именем «UnitTest», другую «IntegrationTest». Эти аннотации могут использоваться на классах и на методах. Если весь класс состоит из модульных или интеграционных тестов, вы можете пометить класс правильной аннотацией. Если нет, вы можете пометить каждый метод с правильной аннотацией. Кроме того, эти аннотации могут быть полезны для динамического введения осветителей перед запуском тестов (фаза 3).
  2. Для каждого интеграционного теста перечислите, что такое «набор данных», который должен находиться в базе данных в начале каждого теста, и что следует удалить в конце этого теста (например, таблица X, нужна запись с «id»). установите в «1», а «name» в «foo» и т. д.). Обратите внимание, что то, что вы удаляете, может быть больше / меньше, чем то, что у вас есть в начале, поскольку сам код может соответственно добавлять / удалять объекты из уровня персистентности. Скорее всего, вы быстро заметите, что для некоторых из этих тестовых случаев требуется один и тот же набор данных или часть одного и того же набора данных.

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

Вы можете заметить, что этапы 1, 2 и 3 могут быть выполнены в одном тестовом классе, если вы хотите быстро показать коллегам / руководству, как это можно сделать. Это также было бы полезно, как писал Петер Тёрёк, чтобы немедленно показать «хороший путь» своим товарищам по команде, чтобы они прекратили создавать плохой код. Однако я думаю, что оставшаяся часть фазы 2, идентифицирующая весь набор тестовых данных, лучше всего сделать за один большой шаг.

Что касается API / технологии, стоящей за всем этим, вы, кажется, знаете предмет.

Надеюсь, это немного помогло.

Примечание: для моего предложения я предполагаю, что вы пишете код либо на Java / C #, где я знаю аннотации, и AOP возможен. Я уверен, что это возможно и на других языках, но я не буду писать о том, чего не знаю.

Jalayn
источник
1
Спасибо ... Я подумал об использовании аннотаций в качестве меток, чтобы определить, что такое интеграционный тест и что такое модульный тест ... Знаете ли вы, можно ли настроить CI-сервер, такой как CruiseControl, для исключения определенных тестов на основе аннотаций? Может быть, это отдельный вопрос.
maple_shaft
Извините, я не знаю, используйте CruiseControl, поэтому я не знаю об этом. Я посмотрел в конфигурации плагина Maven Surefire просто для любопытства, и это не представляется возможным, однако вполне возможно пропустить тесты, основанные на названиях, конечно.
Джалайн
14

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

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

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

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

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

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

c_maker
источник
8
+1, и я добавлю «начни с примера». Никто не ценит парня, который входит и говорит: «Вы делаете это неправильно», но если вы показываете улучшения, они, скорее всего, последуют за вами.
StevenV
2
+1 за правило бойскаута , его гораздо проще использовать и продавать, чем любой капитальный ремонт.
Матье М.
10

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

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

IMO Ваша первая цель должна состоять в том, чтобы помешать команде производить более плохие тесты . Итак, начните с демонстрации преимуществ каждого конкретного улучшения своим товарищам по команде. Если они увидят полезность определенного метода - будь то сокращение внешних зависимостей, восстановление исходного состояния после каждого теста или разделение модульных и интеграционных тестов - они начнут применять их. Это само по себе будет медленно, но верно улучшать общее качество тестовой базы в долгосрочной перспективе (если у вас сейчас 1000 неудачных тестов, а команда подготовит 1000 хороших тестов к следующему году, вы снизите соотношение плохих тестов). от 100% до 50%). Как только это будет обеспечено, вы можете принять решение о рефакторинге существующих тестов в каждом конкретном случае. Опять же, небольшие улучшения со временем приведут к большим изменениям.

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

Петер Тёрёк
источник
6

Работайте в направлении проверки независимости. Если test X изменяет тестовую базу данных таким образом, что тест Y завершается неудачей, то меняйте тест Y. В этом небольшом сценарии основное внимание уделяется не тому, что X испортил базу данных, а тому, что Y имеет неподходящие зависимости. Удалите эти зависимости (заглушив базу данных, перестроив тест или инициализировав базу данных в состояние, в котором Y пройдет), и теперь у вас есть еще один независимый рабочий тест. Это прогресс (возможно, «исправить» X, чтобы не испортить базу данных не будет).

Будьте терпеливы и уважительно относитесь к людям, с которыми вы работаете, несмотря на беспорядок, который они создали. Они пытаются поступить правильно, по всей вероятности; имейте это в виду и помогите им сделать это.

Карл Манастер
источник
2
Я должен был упомянуть, что ни один из оригинальных создателей беспорядка здесь больше нет. Им не хотелось иметь дело с техническим долгом, который они создали и пошли дальше.
maple_shaft
4
@maple_shaft: это хорошо, что они ушли ... вы можете улучшить положение вещей, не теряя лица.
Кевин Клайн
2

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

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

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

Том Ау
источник
2

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

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

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

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

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

джастин
источник
2

Исправить их со временем

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

Мне лично все равно, является ли тест модульным или интеграционным, если это хороший тест. Под хорошим тестом я имею в виду, что это:

  • убирает за собой
  • повторяется
  • сводит к минимуму взаимодействие с окружающей средой
  • согласуется

По пути я проповедовал лучшую тестовую конструкцию (то есть я много гнал людей).

dietbuddha
источник