Как бороться с огромным количеством неудачных тестов? [закрыто]

22

Я работаю над разработкой старого проекта, написанного на Java. У нас более 10 миллионов LOC и, что еще хуже, более 4000 функциональных тестов.

Тесты, запланированные Хадсоном, проваливаются, как сумасшедшие, с каждым большим изменением кода. Проверка неудачи теста - если это проблема в продукте или в тесте, занимает месяцы. Мы не можем удалить старые тесты, потому что мы не знаем, что они тестируют!

Что мы можем сделать? Как поступить с таким количеством устаревших тестов?

Гектор Бросули
источник
6
Реальные вопросы имеют ответы. Вместо того, чтобы объяснять, почему ваша ситуация ужасна или почему ваш босс / коллега делает вас несчастными, объясните, что вы хотите сделать, чтобы сделать это лучше. Для получения дополнительной информации, нажмите здесь ...
Гнат
13
Почему вы позволили тестам начать проваливаться? КСТАТИ 4000 не так много тестов для 10 MLOC
BЈовић
6
Остановись, брось и катись.
Навин
13
Узнайте, что тестируют тесты. Затем снова зайдите и спросите себя, во-первых, на какие испытания на земле ушли месяцы, чтобы найти проблему, а также выясните, насколько сильно изменились ваши требования. Тесты предназначены для инкапсуляции требований в приложении. Если ваши тесты не пройдены, ваш код не работает в соответствии с требованиями - либо вы написали их неправильно, либо ваш код не соответствует вашим требованиям.
Дэн Кладовая
6
Мы все видели, как компилятор выбрасывал миллионы ошибок из-за одного пропущенного '}'. Если это функциональные тесты с множеством зависимостей, возможно, проблема такого же рода работает?
Дэн Пичельман

Ответы:

37

Оставь их.

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

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

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

Килиан Фот
источник
9
Я не вижу логики в вашей точке зрения: «Набор тестов должен дать вам уверенность в том, что система делает то, что должна делать. [...] Теперь вам нужен новый набор тестов, который работает без ошибки «. Если у вас есть неисправный код, который делает тесты неудачными, это не значит, что вы должны переписать тесты так, чтобы неисправный код прошел.
Д.Бедренко
13
Ситуация Гектора такова, что он не знает, неправильны ли код или тесты . Если бы он это сделал, он мог бы работать с базой кода и иногда менять тесты, иногда бизнес-код. На самом деле, даже этот вид рутинной работы не окупится, поскольку вы не знаете, решаете ли вы проблемы или совершаете их.
Килиан Фот
5
«Предполагается, что набор тестов даст вам уверенность в том, что система делает то, что [должна делать]». Нет, он должен сказать мне, делает ли система то, что должна; ложная уверенность хуже, чем ничего. «Вам нужен набор тестов, который работает без ошибок» Нет, ему нужен набор тестов, который дает ему полезную информацию о правильности кода. Теперь у него есть много загадочных сигнальных огней, которые лучше, чем зеленый свет от нового блестящего набора тестов, который ничего не тестирует. Он должен временно отключить старые тесты , но не отказываться от тех, которые он не признал поддельными.
бета
4
Этот ответ невероятно плохой совет! Если небольшие изменения кода приводят к большому количеству неудачных тестов, у вас, вероятно, есть проблемы с качеством кода. Тест по крайней мере уведомит вас, что вы что-то сломали. Вам нужно улучшить код (путем тщательного рефакторинга с помощью тестов). Если вы просто удалите тесты, вы не сможете узнать, что вы что-то сломаете.
JacquesB
4
Это ужасный совет. Если ОП и его команда уже не могут понять кодовую базу и ее тесты, то выбрасывание тестов и повторный запуск вряд ли решат основную проблему ОП - понимание кодовой базы. Я думаю, что мы можем предположить, что тесты сработали, когда они были написаны - поэтому его команде нужно отследить, что тестирует каждый тест, и прочитать исходный код, чтобы определить, является ли кодовая база или тест неправильным сегодня. Намного проще, чем начинать заново с неверно ориентированных и неинформированных / наивных тестов.
SnakeDoc
29

Иди и исправь тесты.

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


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

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

BЈовић
источник
4
Это то, что в идеале должно быть сделано, но кажется, что тесты здесь настолько плохи, что программисты даже не знают, что они тестируют. Я думаю, что в этом случае лучше всего избавиться от тестов WTF и сразу же начать писать новые и значимые! В недавнем проекте у меня была похожая проблема с коллегой, чьи тесты всегда не удавались без веских причин (это не было ошибкой, потому что то, что должно было быть проверено, ошибалось, а потому, что тестовый код был настолько хрупким и даже не детерминированным!) , Я провел дни, переписывая все, что мог, и разгромил все остальное!
Шаути
@Shautieh Тесты WTF не обходятся без кода WTF, поэтому исправление тестов обычно означает рефакторинг кода. И случайно провалившиеся тесты являются признаком некомпетентности. И руководитель вашей коулиги виноват в том, что не выполняет свою работу.
BЈовић
2
Иногда жизнь бывает суровой: парень, ответственный за тесты WTF (и код), получил самую высокую зарплату в команде (на 20% больше, чем я), и когда он ушел в середине проекта (потому что он нашел более высокооплачиваемую работу ) Мне пришлось взять на себя некоторых из его разработчиков: / Но вы совершенно правы, что наш руководитель тоже был виноват ^^
Shautieh
@Shautieh: мой коллега однажды сказал, что ошибка в коде - это две ошибки: ошибка в коде и слепая зона в тестах. Я предполагаю, что на самом деле это три, если вы считаете разработчика, который терпит неудачные тесты, и четыре, если вы считаете менеджеров, которые продвигают такого некомпетентного.
Бета
@ Beta Звучит очень похоже на определение, которое иногда используется в TDD: «Ошибка - это тест, который вы еще не написали».
Восстановите Монику
22

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

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

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

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

Временно отключите неудачные тесты.

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

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

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

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

Вы можете переместить тесты в исходное дерево, которое обычно не включено в сборку.

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

Цель состоит в том, чтобы Дженкинс как можно скорее стал Зеленым, чтобы вы могли начать движение в правильном направлении как можно скорее.

Держите тесты актуальными.

Разрешите добавлять новые тесты по мере добавления или изменения кода и обязуйтесь не сдавать все проходящие тесты.

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

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

Определите цель каждого теста.

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

  • Проверяет ли он функцию, которая была специально удалена из базы кода? Тогда вы, вероятно, можете удалить его.

  • Это ошибка, которую еще никто не заметил? Восстановите тест и исправьте ошибку.

  • Это сбой, потому что он делал необоснованные предположения (например, предполагая, что текст кнопки всегда будет на английском языке, но теперь вы локализовали свое приложение для нескольких языков)? Затем выясните, как сделать тест сосредоточенным на одной вещи, и изолировать его от несвязанных изменений как можно лучше.

  • Распространяется ли тест на все приложение и представляет собой системный тест? Затем удалите его из основного набора тестов Jenkins и добавьте его в набор регрессии, который запускается реже.

  • Изменилась ли архитектура приложения до неузнаваемости, поэтому тест больше не дает ничего полезного? Удали это.

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

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

Билл Мичелл
источник
1
Это действительно очень плохая идея - отключить тесты только потому, что они не пройдены! Остальные ваши советы хороши, но не это. Тесты, которые вы не понимаете, никогда не должны быть отключены. Цель тестирования не в том, чтобы получить зеленую полосу, а в том, чтобы получить работающее программное обеспечение!
JacquesB
Это зависит от масштаба проблемы. Но я согласен, я на самом деле не дал это понять.
Билл Мичелл,
Добавлен абзац, в котором делается различие между «мы зеленые, но каждое изменение заставляет вещи становиться красными» и «мы были красными так долго, мы забыли, как выглядит зеленый»
Билл Мичелл,
Вместо того, чтобы отключать или даже удалять тест, некоторые платформы также предоставляют понятие ожидаемого сбоя . Это может помочь увеличить SNR, потому что вы будете более непосредственно предупреждены о новых сбоях (чего не будет, если всегда есть огромное количество отказов), но все равно будете получать уведомления об известных сбоях и - возможно, даже более важно - когда ранее провалившийся тест неожиданно снова проходит. Если неожиданные сбои считываются, а ожидаемые сбои оранжевого цвета, сделайте так, чтобы красные тесты были зелеными первыми, а оранжевые - вторым приоритетом.
5gon12eder
11

4000 тестов - неразрешимая проблема. 40 тестов более податливы. Произвольно выберите управляемое количество тестов для запуска и анализа. Классифицируйте результаты как:

  1. Бесполезный тест
  2. Полезный тест, который работает чисто
  3. Полезный тест, который не проходит

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

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

Патриция Шанахан
источник
2
+ (int) (PI / 3) за предоставление действительного и простого способа тестирования набора тестов - хотя я согласен с тем, что, как правило, такие тесты, как описано в OP, являются признаком неисправного проекта - но без тестирования что не так, любые советы по самому набору тестов (будь то «отказаться от них», «исправить тесты», «написать новые тесты») просто бесполезны. Точно так же, как вы говорите: если бы у меня было 4k тестов, а для 40 совершенно случайных из этих 3/4 дрянные и бесполезные - я бы не стал спешить выбросить весь пакет. Если бы 3/4 из них были бы действительно полезны - я бы оставил их и сосредоточился на улучшении кода.
vaxquis
7

Если это утверждение верно,

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

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

Повторяйте, пока у вас не будет последней версии кода.

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

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

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

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

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

gbjbaanb
источник
1
Вот почему мне нравится @Ignoreаннотация JUnit - вы можете сохранять свои тесты, но не выполнять их. Тогда это просто вопрос их повторного включения и исправления по одному. Это позволяет сузить фокус до нескольких тестов за раз, вместо того, чтобы быть перегруженным тысячами сбоев.
TMN
1
Это плохой совет. Вы не должны удалять или отключать тест, который вы не понимаете. Только если вы делаете понять тест, и вы уверены , что он проверяет устаревшую функцию, она должна быть отключена или удалена.
JacquesB
2

Самое важное, что я бы сделал, - это вернусь к основам того, что должно делать тестирование, и что бизнес должен продолжать двигаться. Задача тестирования - выявить проблемы, прежде чем они станут дорогостоящими, чтобы их можно было исправить позже. Я думаю, что ключевое слово в этом предложении «дорого». Эти вопросы требуют бизнес-решения. Дорогие проблемы появляются в поле? Если это так, тестирование не проходит сразу.

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

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

Затем начинается искусство: как вы можете управлять этим двуглавым зверем, чтобы успехи в одной ветви также помогали другой ветви? Каким образом ваши обновления ветки «visonary» могут возвращаться к ветке «legacy», несмотря на жесткие требования к тестированию. Как постоянные запросы клиентов в «устаревшей» ветке могут улучшить ваше понимание требований, которые потребуются вашим прежним клиентам, если вы в конечном итоге повторно объедините продукты?

Корт Аммон - Восстановить Монику
источник
-3

Мы не можем удалить старые тесты, потому что мы не знали, что они тестируют!

Именно поэтому вы должны удалить старые тесты! Если вы не знаете, что они делают, то неудача не имеет смысла, а запуск их - пустая трата времени. Выкинь их и начни сначала.

Мохер
источник
2
кажется, это просто повторяет уже высказанное и объясненное в верхнем ответе
комнат
4
Отказ не является «бессмысленным», это означает, что вы не понимаете систему так, как думали.
Бен Фойгт
Неудача здесь определенно бессмысленна, потому что ОП четко заявили, что не понимают систему.
мохер