Scrum без плану тестування: POC на максималках
Сьогодні більшість успішних проектів розпочинаються з Proof of Concept (POC) – відносно невеликої оцінки концепції. На цьому етапі обрана технологія та набір функцій проходять первинну перевірку. Оцінюється їх потенційний вплив на бізнес-користувачів. Якщо POC підтверджує доцільність інвестицій, формується повноцінна команда для розробки та випуску повнофункціонального продукту.
Для Scrum-команди це ідеальний сценарій. Команда швидко створює прототип, додаючи значущі нові функції з кожним спринтом. Бізнес-користувачі спостерігають за прогресом у реальному часі, бачачи, як ідея втілюється з нуля протягом 10 спринтів. Це створює сильне враження (що є головною метою POC). Але є один важливий нюанс – мінімум тестування, а іноді і повна його відсутність. Думати про процес тестування на цьому етапі вважається зайвим.
Для команди Scrum це не є пріоритетом, адже розробка без процесів, що уповільнюють її, здається привабливішою. Будь-яка тестова діяльність неявно створюватиме затримки. А хто хоче зайвої повільності, коли потрібно максимально вразити кінцевого користувача?
Коли команда продовжує працювати в такому ж режимі після завершення POC, ми маємо справу з “POC на стероїдах”. Це виробнича система, яка розширюється в розмірах і функціональності, але поводиться як POC. Це готовий продукт з прихованими дефектами та невідомими крайніми випадками, які лише чекають на серйозний збій.
З часом команді стає все важче встигати за стабільними релізами від спринту до спринту, оскільки виправлення проблем у процесі ускладнюється.
Ось кілька методів, які довели свою ефективність у вирішенні подібних проблем. Вони допоможуть впровадити надійні процеси тестування, не перешкоджаючи прогресу розробки. Адже саме до цього прагне будь-яка Scrum-команда.
Розподіл навантаження
З чого ще можна почати боротьбу із зайвими проблемами, як не з розподілу навантаження? 🙂
Під цим я розумію розробку плану, який вимагатиме від розробників невеликих додаткових дій, але це значно сприятиме досягненню спільної мети з часом, поступово, але послідовно.
#1. Розробка модульних тестів для нового коду
Якщо вам вдасться переконати вашу Scrum-команду додати до “Definition Of Done” вимогу розробки модульних тестів для кожного нового коду, створеного під час спринту, це буде великим досягненням у довгостроковій перспективі.
Причини очевидні:
Це змусить розробників подумати про різні нестандартні шляхи виконання коду.
- Такі модульні тести можна інтегрувати в автоматизовані конвеєри DevOps і запускати під час кожного розгортання в середовищі розробки або тестування. Показники з конвеєра можна легко експортувати та використовувати для демонстрації бізнес-користувачам відсотка охоплення тестами, безпосередньо прив’язаного до вихідного коду.
Найважливіше – почати якомога раніше. Чим пізніше почнеться розробка модульних тестів, тим більше часу доведеться витратити розробникам на їх додавання під час спринту.
- Зворотна розробка модульних тестів для вже існуючого коду потребуватиме значних зусиль. Деякі частини коду можуть бути створені іншим розробником, і поточному розробнику не зовсім зрозуміло, як це має працювати в кожній окремій частині коду. У деяких випадках це може дійти до того, що додавання модульного тесту до зміненого коду займе більше часу, ніж розробка зміни функціональності для спринту. (Цей стан ніхто не враховував під час планування спринту).
#2. Регулярне виконання модульних тестів в середовищі розробки
Перш ніж створювати запит на злиття нового коду в головну гілку (Master), обов’язковою має бути перевірка як коду функції, так і коду модульного тестування в середовищі розробника. Це гарантує, що:
- Код модульних тестів дійсно працює для кожної частини (адже це просто ще один код, який потрібно перевірити). Дуже часто цей крок пропускається. Якимось чином передбачається, що якщо модульний тест підключено до конвеєра DevOps, він буде виконаний і перевірений. Однак це лише перенесення проблем на вищі рівні, де команда зазвичай має менше часу і більше стресу, щоб завершити кожну історію.
- Новий код функції перевірений розробником на базову функціональність. Звісно, це не повна перевірка бізнес-логіки, але це підтвердить, що код поводиться так, як задумав розробник.
#3. Виконання модульних тестів після злиття коду в головну гілку
Одна справа мати функціональний код у локальній гілці, але зовсім інша – той самий код, що працює після запиту на злиття в основну гілку.
Головна гілка містить зміни від інших членів команди Scrum. Навіть якщо конфлікти вирішено, і все виглядає добре, код після злиття залишається неперевіреним, тому ризиковано відправляти його далі без попередньої перевірки.
Ефективним рішенням є повторне виконання тих самих модульних тестів, які вже проводилися в середовищі розробника, а також у середовищі, створеному з версії коду головної гілки.
Для розробників це може бути ще один додатковий крок, але він не потребує великих зусиль, оскільки не потрібно вигадувати нічого нового. Просто потрібно повторно виконати те, що вже було зроблено.
Цей крок можна пропустити лише в одному випадку:
- Автоматизовані модульні тести в конвеєрах DevOps настільки всеохоплюючі, що вони вже охоплюють усе ручне тестування, яке виконується поверх цього.
Хоча це можливо, я ніколи не стикався з таким у реальному житті. Для розробників було б занадто часозатратно створити такі деталізовані автоматизовані модульні тести. Власник продукту може не дозволити команді приділяти стільки часу, оскільки це вплине на кількість доставлених історій протягом спринту.
Однак обсяг спринту ніколи не має бути виправданням для того, щоб не проводити модульні тести. Інакше код знову буде недостатньо протестований, і тоді для виправлення буде вже запізно.
З цих причин я рекомендую повторно виконувати модульні тести на версії головного коду. Це не потребує великих зусиль, але приносить значну користь.
Це остання перевірка готовності головної гілки до етапу тестування випуску. Це також допоможе виявити більшість технічних помилок, залишивши наступний етап для перевірки бізнес-логіки.
Підготовка до функціонального тестування
Усі попередні дії з тестування мають привести до одного – головний код гілки вільний від технічних помилок і готовий для наскрізних функціональних потоків.
Цей етап може легко охопити одна людина, і їй навіть не потрібна технічна освіта.
Набагато краще, якщо це буде хтось, не пов’язаний з розробниками, але з розумінням того, як бізнес-користувачі очікують поведінку коду. Необхідно виконати дві основні дії:
#1. Функціональне тестування нових історій спринту
В ідеалі кожен спринт має приносити нову функціональність. Тому її потрібно перевірити. Важливо переконатися, що нова частина програмного забезпечення працює так, щоб бізнес-користувачі були задоволені. Вони, очевидно, чекали на це весь останній спринт :).
На жаль, буває так, що довгоочікувана функція, виявляється, не працює належним чином.
Тому правильне тестування нової функціональності спринту є критичним. Щоб досягти успіху, рекомендовано заздалегідь зібрати важливі тестові випадки від відповідних зацікавлених сторін (власника продукту або кінцевих користувачів) і скласти список усіх тестових випадків, необхідних для вмісту всередині спринту.
На перший погляд це може здатися складним, але з мого досвіду з цим цілком впорається одна людина. Спринти переважно короткі (наприклад, двотижневий період). Крім нового контенту, спринт включає в себе інші види робіт (історії технічного боргу, документацію, історії про дизайн тощо).
Потім виконуються тестові приклади, щоб перевірити бажану функціональність. Якщо виникає проблема, до відповідного розробника звертаються для її вирішення.
Таким чином, розробники витрачатимуть мінімум часу на функціональне тестування та зможуть зосередитися на діяльності, яка їм найбільше подобається.
#2. Виконання регресійних тестів
Інша частина функціонального тестування повинна полягати в тому, щоб переконатися, що все, що працювало раніше, також працюватиме після наступного випуску. Для цього потрібні регресійні тести.
Регресійні тести найкраще, якщо їх регулярно підтримувати та переглядати перед кожним випуском. Вони повинні бути простими, але охоплювати більшість основних функцій і важливі наскрізні потоки.
Зазвичай у кожній системі є процеси, які стосуються багатьох різних областей, і це найкращі кандидати для регресійних тестів.
У деяких випадках регресійні тести навіть неявно охоплюють нові функції в спринті, наприклад, якщо нова історія в спринті змінює певну частину існуючого потоку.
Отже, виконати регресійні тести разом із тестуванням нових історій спринту нескладно, особливо якщо це робиться регулярно перед кожним випуском.
Наполегливість на виконанні перевірок якості перед кожним випуском продукції
Тест забезпечення якості (QA) є останнім кроком перед випуском у виробництво, і часто його пропускають як неважливий. Особливо, якщо команда Scrum націлена на новий контент.
Навіть бізнес-користувачі скажуть, що їх цікавлять нові функції, а не стільки збереження функціональності чи низька кількість дефектів. Але це саме та причина, чому команді розробників згодом доведеться сповільнитися, і бізнес-користувачі все одно не отримають того, що хочуть.
Перевірка якості повинна виконуватися людьми поза командою Scrum. В ідеалі це мають бути бізнес-користувачі у спеціальному середовищі, яке максимально наближене до виробничого. Власник продукту може замінити тут кінцевих користувачів.
Це має бути функціональний тест з точки зору кінцевого користувача, без будь-якого зв’язку з командою розробників Scrum. Це буде останній погляд на продукт, який використовуватимуть так, як ніхто не очікував. Це час для останніх виправлень.
Може стати зрозуміло, що очікування не були добре зрозумілі команді Scrum. У такому випадку ми можемо узгодити план дій до випуску. Це краще, ніж визнати невдачу після звіту про успішний випуск.
Куди рухатись далі?
Застосування цих практик може привести до більш стабільних і передбачуваних звичок випуску спринтів. Ви не будете затримувати випуски або витрачати весь спринт на підготовку до наступного випуску. Ніхто не буде виконувати те, що йому не подобається.
Але не варто зупинятися на цьому.
Необхідно включити тестування продуктивності. Його часто ігнорують. Проте я завжди сумнівався, як можна очікувати розвитку виробничої системи, якщо її продуктивність не перевіряється.
Потрібно впровадити автоматизовані тести.
Я вже згадував автоматизовані модульні тести. Але ви можете розробити повні наскрізні регресійні тести, повністю автоматизовані та виконувані після кожного розгортання в тестовому середовищі. Це ще більше звільнить команду розробників. Але для розробки та підтримки таких автоматизованих тестів потрібна окрема команда. Це стане постійною роботою, оскільки щоразу, коли змінюється код, існуючі тести можуть стати недійсними, і їх потрібно оновити. Це зусилля, на які готові платити не всі, але переваги для Scrum-команди були б великими.
Ці теми виходять за рамки цієї статті. Потрібно з’ясувати правильний розклад і час для кожного типу тесту, щоб ви могли зробити це в межах вікна спринту. Я буду радий поговорити про це наступного разу!