Ти підняв ставку середньої знижки з 5% до 7% у функції знижка(). Червоними стали два тести: на саму знижку і на до_сплати(), яку ти навіть не відкривав. Чому впав другий?
Чому так. Це і є регресія: ти правив одну функцію, а зламалась та, що її використовує — 300 × 0.93 = 279.0 замість 285.0. Варіант про порядок запуску спокусливий, але хибний: тести в pytest незалежні, і падіння одного нічого не робить із рештою. Саме тому набір і показує рівно два червоних, а не шість.
Питання 2 / 8
Файл називається перевірка_кошика.py. Усередині дві функції з бездоганними іменами: test_знижка() і test_межі(). Скільки тестів збере pytest?
Чому так. Спершу фільтрується файл (має бути test_*.py або *_test.py), і лише потім функції в ньому. Файл не підійшов — отже pytest у нього навіть не зазирне, і обидві правильно названі функції зникнуть разом із ним. Найнеприємніше тут те, що це не червоний тест, а відсутній: у звіті просто буде менше рядків.
Питання 3 / 8
Тест написано так: «def test_знижка(): знижка(300) == 0.05» — слово assert загубилось. Тест зелений. Що це доводить про функцію знижка()?
Чому так. Без assert це просто вираз: Python обчислює 0.05 == 0.05, отримує True і викидає його. Тест зелений завжди — і на правильному коді, і на будь-якому зламаному. Саме такі «тести» ловить правило «побач тест червоним хоча б раз»: якщо він не падає навіть на явно поламаній функції, він не перевіряє нічого.
Питання 4 / 8
Набір із шести тестів на суми 50, 150, 300, 450, 700, 850 повністю зелений. Але в коді написано «if сума <= 200» замість «if сума < 200». Чому набір нічого не знайшов?
Чому так. Помилка на одиницю змінює відповідь рівно на двох значеннях із девʼятисот — на самих порогах. Шість точок, обраних «на око», промахуються повз них майже напевно. Перебирати всі 900 не треба: достатньо чотирьох межових тестів (199, 200, 499, 500), і обидві помилки знайдуться з першого запуску.
Питання 5 / 8
Тест написаний так: with pytest.raises(ValueError): підсумок(28.5, -1). Хтось прибрав із підсумок() перевірку аргументів, і тепер вона спокійно повертає -28.5. Що покаже pytest?
Чому так.pytest.raises не ловить помилку, а перевертає її значення: відсутність винятку всередині блоку і є провалом. Саме тому такий тест ловить того, хто колись «спростить» функцію. А от рукописний try/except ValueError: pass у цій ситуації лишився б зеленим — і поломку пропустив.
Питання 6 / 8
Чотири набори даних перевіряють знижку на межах. Один із них зламаний. Чим parametrize кращий за цикл for усередині одного тесту?
Чому так.assert кидає виняток і завершує функцію, тому цикл зупиняється на першому ж розходженні: набори після нього не запускаються взагалі. parametrize розгортає одну функцію в чотири окремі тести, тож у звіті буде «3 passed, 1 failed» і точна назва винуватця — test_знижка[500-0.1].
Питання 7 / 8
Керівник радіє: покриття коду тестами 100%. Що з цього насправді випливає?
Чому так. Покриття рахує виконані рядки, а не перевірені твердження. Тест, який просто викликає три функції й не має жодного assert, дає повне покриття й нуль гарантій. Низьке покриття — точно погано, високе саме по собі не означає нічого: дивись, чи є серед тестів межі й помилкові дані.
Питання 8 / 8
Тест проходить, коли запускаєш увесь файл, і падає, якщо запустити його окремо: pytest test_кошик.py::test_межа_200. Про що це говорить?
Чому так. Правило звучить так: будь-який тест має проходити, якщо запустити його самого. Порушення означає спільний змінюваний стан — глобальну змінну, файл на диску, базу, — який один тест лишив, а другий на нього спирається. Ліки саме такі: фікстура, що створює все заново для кожного тесту, і жодних глобальних змінних, які тести правлять.