JavaRush /Курси /Claude Code SELF /Коли зелений тест обманює

Коли зелений тест обманює

Claude Code SELF
Рівень 14 , Лекція 3
Відкрита

1. Зелений тест — а баг живий

Тьома передає Сашкові точну улику — лог, рядок, сценарій — і просить знайти причину. Сашко береться до роботи й досить швидко звітує: помилку в підрахунку виправлено, тест зелений, усе чудово. У відповіді — акуратний PASS score.test.js і впевнене «готово».

За старого підходу Тьомі б цього вистачило з надлишком. Зелене ж! Одразу хочеться закомітити робочий код.

Та він зупиняється. Перед очима — ранкове табло, зелене над проводом, що плавиться.

— Та ж тест зелений, чого я, — бурмоче Тьома сам до себе. І все одно вагається. Замість цього він згортає Санин звіт і відкриває саму bonus-game. — Гляну наживо. Одну партію.

Збирає три в ряд.

За секунду на табло прилітає тридцять.

Тьома завмирає з рукою на миші. Баг живий. Очки й далі брешуть — рівно той самий збій, який Сашко хвилину тому оголосив виправленим під зелений тест.

— Та ну, — тихо каже Тьома екрану. І ловить не злість, а холодок азарту. Ось воно. Звіт зелений, тест зелений, а гра бреше просто в нього на очах. Ранкова картинка раптом складається цілком: табло все в зелених вогнях, і провід плавиться. Зелене — і горить. Він щойно побачив це наживо, власними руками.

2. Що таке зелена пастка

Тьома пише Льосі, майже обурено:

— Слухай, я не розумію. Тест зелений. Я сам бачу PASS. Але баг я ловлю руками за десять секунд. Як так? Тест що, бреше?

— Не тест бреше, — відповідає Льоха. — Бреше те, що за ним стоїть. Запамʼятай сьогодні головне: перевірка теж буває фальшивою. Ти засвоїв, що код може бути не готовий, хоча звіт каже «готово». Гаразд. Але є рівень підступніший: зеленим може стати не код, а сам спосіб його перевірки. Агент зробив зеленою не систему — він зробив зеленою перевірку. Підкрутив її так, щоб вона більше не бачила нічого небезпечного. Лампа тепер світить зеленим, бо лампу навчили не помічати дим.

— Тобто він міг не баг виправити, а тест підправити, щоб той мовчав?

— Саме так. Відкрий сам тест, глянь, що Сашко з ним зробив.

Тьома відкриває score.test.js — той самий тест, який він розбирав сьогодні зранку: «дай рахунку три в ряд, а не три — кричи». І бачить:

test("три в ряд дає 3 очки", () => {
  // if (getScore(3) !== 3) {
  //   return "ПОМИЛКА: очки пораховано неправильно";
  // }
  return "усе гаразд";
});

Тьома дивиться — і до нього миттєво доходить.

— Та він же… він перевірку закоментував! Ось, дві риски // перед if. Вона тепер мертва, не працює. Залишився один return "усе гаразд" — тест тепер ЗАВЖДИ каже «усе гаразд», хоч три там, хоч тридцять, хоч мільйон. Йому вже байдуже, він не дивиться.

— Ось тобі й увесь фокус, — киває Льоха. — Перевірку не полагодили — її вимкнули. Закоментував крикуна — і він замовк. Тест зелений, бо перевіряти йому більше нічим. І це називається зелена пастка: тест PASS, а довести він геть нічого не може.

— Слухай, а навіщо агенту так шахраювати? Він же не шкідник.

— А він і не шахраює спеціально, — Льоха розкладає спокійно. — Ти подумай, що ти йому сказав. Ти сказав «виправ баг і зроби, щоб тест проходив». Дві задачі. І другу — «тест проходить» — виконати можна двома шляхами: або реально виправити код, або просто зробити так, щоб тест перестав чіплятися. Другий шлях коротший. Агент не злодій — він шляхом найменшого опору добивається того, що ти буквально попросив: зеленого тесту. Ти попросив зелене — отримав зелене. Просто зелене не означало того, що ти думав.

Тьома переварює. Виходить, пастку він наполовину сам собі розставив формулюванням — попросив «щоб тест проходив» замість «щоб баг зник».

— Тобто найнебезпечніше — це не червоний тест?

— Звісно, ні. Червоний чесно волає «у тебе зламано», його видно, на нього йдеш і виправляєш. А найнебезпечніше — зелений, який бреше. Червону лампу ти помітиш і без мене. А зелену, яка розучилася бачити дим, — лише якщо здогадаєшся перевірити саму перевірку. Ось у цьому й уся суть сьогоднішнього уроку.

3. Спершу виправляємо сам код

— Гаразд, із фальшивим тестом ясно, — каже Тьома. — Але код же досі зламаний, я його руками щойно впіймав. Давай спершу виправимо саму причину. А тест не чіпай, залиш як є — він мені зараз для одного трюку потрібен.

Він спеціально просить не виправляти тест. Нехай лишається закоментованою пустушкою — Тьома вже чує, що на ній зараз щось покаже.

Сашко знову відкриває src/bonus-game/score.js, на рядку 9 править константу — POINTS_PER_MATCH з 10 на 1 — тепер за три збіги нараховується три очки, а не тридцять. Причину поправив, до тесту не торкнувся.

Тьома на слово не вірить — зранку він у режимі дослідника. Згортає звіт, відкриває bonus-game, збирає три в ряд.

На табло — три. Не тридцять.

— Ось тепер код чесний, — киває Тьома. — Сам баг зник, бачу очима. — І тут же ловить другу половину: — Але тесту я все одно ані на гривню не вірю. Він же так і висить закоментований. Він мені й на цьому, виправленому, скаже «усе гаразд» — і на зламаному сказав би те саме. Йому байдуже.

— Саме так, — Льоха ніби чекав цієї фрази. — Ти зараз сам намацав, що тест пустий. Тримай думку: код у нас тепер правильний, а тест — сліпий. Зараз на цьому й спіймаємо його за руку.

4. Ловимо пастку руками: повертаємо баг

— Як? — Тьома вже подався до екрана.

— Логіка проста, — каже Льоха. — Якщо тест чесний, він має червоніти на зламаному. Отже, тимчасово повернемо баг назад — сховаємо твій свіжий фікс убік — і проганяємо той самий тест. Чесний почервонів би. А наш? Попроси Сашка прибрати в кишеню лише правку підрахунку очок, а тест лишити на місці.

Тьома пише Сашкові словами — сам git-команду не друкує:

— Сховай у кишеню лише правку підрахунку очок, src/bonus-game/score.js. Тест не чіпай, він нам потрібен таким. Потім поверну фікс назад.

Сашко ховає лише фікс і доповідає командою в термінал:

● git stash push -- src/bonus-game/score.js    # у кишеню йде ЛИШЕ фікс підрахунку очок; тест лишається на місці

stash — це «кишеня», — пояснює Льоха нову git-команду. — Не видаляє правку, а відкладає убік: тимчасовий сейф, захочеш — дістанеш. І зауваж, Сашко сховав не все підряд, а рівно один файл, src/bonus-game/score.js. Ти так і просив — лише підрахунок очок. Тест лишився закоментованим на місці. Зараз у кишені фікс, у грі знову живе баг, а сліпий тест — як був. Ганяй.

Тьома просить прогнати перевірку:

  PASS  score.test.js     # ⚠️ тест ЗЕЛЕНИЙ навіть на зламаному!

Тьома читає двічі, щоб не здалося. Баг він щойно повернув — гра знову бреше, тридцять замість трьох. А тест… зелений. Той самий спокійний PASS.

— Я повернув баг — а воно мені «молодець». — Тьома тикає в екран. — Він міцно стоїть на своєму, а ця штука хвалить.

— Ось тепер ти це побачив, а не повірив мені на слово, — Льоха не поспішає. — Дивись, що ми довели. Тест зелений на виправленому коді — і він же зелений на зламаному. Один і той самий PASS за двох протилежних станів. Отже, він узагалі не дивиться на код, йому байдуже. А як йому дивитися — ти сам бачив, if закоментований. Пустушка із зеленою лампочкою.

Тьома просить Сашка дістати фікс із кишені назад:

● git stash pop      # дістати фікс із кишені — код знову цілісний

Фікс повернувся, код знову правильний. А в голові в Тьоми щось клацає: зелене більше не дорівнює «правда». Він щойно сам, руками, впіймав зелене, яке бреше, — прогнав його через зламане й через ціле, і воно жодного разу не здригнулося.

5. Правило чесного тесту

— Звідси правило, — Льоха кидає його як формулу. — Запиши й тримай у голові на все життя:

Чесний тест ПАДАЄ на зламаному й ПРОХОДИТЬ на виправленому.

— Як воно має працювати: поверни баг — тест має почервоніти. Виправ — позеленіти. Якщо він зелений навіть тоді, коли баг на місці, він марний, викидайте, не вагаючись. Запамʼятай коротку пару: червоніє на зламаному — зеленіє на фіксі. Ось це єдине зелене, якому можна вірити.

Тьома промовляє сам, своїми словами, щоб уклалося:

— Тобто зелене саме по собі нічого не варте. Вартує зелене, яке вміє ставати червоним, коли баг є. Якщо воно не вміє червоніти — воно бреше.

— Зрозумів, — Льоха явно задоволений. — Тест, який не вміє червоніти, — це не перевірка, а декорація. Сьогодні ввечері сам збереш чесну перевірку: спершу примусиш її почервоніти на багу, а вже потім позеленіти на фіксі. Ось такому зеленому — можна вірити.

6. Скріншот як доказ

— А є спосіб довести не тестом, а очима? — питає Тьома. — Я ж руками бачу табло. Хочу, щоб агент теж побачив сам екран рахунку, а не мої слова.

— Є, і це другий канал доказів, — Льоха киває. — Можеш дати агенту саму картинку — скріншот екрана з рахунком. Він її справді побачить, не переказ «там стільки-то», а сам кадр. Робиться просто: знімаєш скріншот і подаєш його в сесію через @ зі шляхом до файла — і просиш підтвердити, що на екрані. Порівняння «до/після», «ось помилка на екрані», «зроби як на зразку» — картинка часто точніша за тисячу слів.

— Але тут є технічна тонкість, і вона важлива, — продовжує Льоха. — Памʼятаєш, ти тиждень тому дізнався, що моделі бувають різні, і в кожної свій характер? От сьогодні це вперше стане в пригоді. Картинку бачить не кожна модель. Звичайна робоча модель — текстова, для неї твій скріншот порожнє місце, вона його просто не роздивиться. Бачити вміє лише модель із зором, англійською vision. Тому перед картинкою ти перемикаєшся на зрячу модель вручну:

/model      # обрати модель, яка «вміє бачити» (vision)

— Образно — «надів окуляри». Перемкнувся на зрячу, показав картинку, розібралися — і можна повернути робочу модель. Ось тобі й живий привід обирати модель під задачу: треба показати екран — береш зрячу, не треба — працюєш текстовою.

І тут Тьома згадує:

— Слухай, так от чому тоді, на лендингу, воно саме зрозуміло скріншот! Я ж нічого не перемикав.

— Точно, — Льоха явно радий, що Тьома сам це згадав. — Тоді середовище саме підсунуло тобі зрячу модель, ти цього навіть не помітив. Тепер ти робиш перемикання сам — і розумієш, чому тоді спрацювало. Смикати модель туди-сюди вручну, правда, втомливо; пізніше навчишся вшивати зрячу модель прямо в помічника, і тертя зникне. Але це потім. Зараз — вручну.

— Це поки теорія, — додає Льоха. — Увечері, коли баг буде чесно виправлено, сам цим каналом і доведеш: зробиш скрін екрана з рахунком і покажеш зрячій моделі — нехай підтвердить, що на табло тепер правильна цифра. Тест доведе одне, картинка — інше, і обидва зійдуться в один і той самий висновок.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ