Від «тестуємо все» до «тестуємо на вимогу»
Привіт, я Микола Панасюк, QA Team Lead в компанії MOJAM. Наш продукт — це платформа для кіберспортсменів і гравців у CS2, яка налічує понад 4.7 мільйони користувачів зі 168 країн світу. На першому місці інтерактивність, реактивність і відмовостійкість системи.
Я відповідаю за побудову та впровадження процесів Quality Assurance на всіх рівнях в компанії, лідерство та управління QA-командою, автоматизацію функціонального тестування, а також розробку фреймворків та інструментів для тестування.
У статті поділюся нашим шляхом трансформації від хаотичного «тестуємо все» до системного «тестуємо за вимогою» за час, відколи я приєднався до компанії. Розповім про стан речей у точці відліку та отримані результати. І ні, тут не буде ні слова про штучний інтелект і як він почав робити всю роботу за нас.
Ця публікація буде однаково корисна як представникам команди розробки (QA + розробники), так і менеджерам усіх рівнів. Якщо ви хочете, щоб ваші QA дійсно займалися Quality Assurance активностями, а не лише тестили тікети, тоді ви потрапили за адресою. Погнали.
З чого все почалося
У травні 2024 року я «напросився» (Рома Лепетюхін, привіт) на співбесіду в MOJAM. Ще тоді СТО компанії запитав мою думку стосовно того, як підняти рівень відповідальності за свою роботу, зменшити накладні витрати на тестування та пришвидшити доставку коду на продакшн. Іншими словами, як зробити так, щоб тестували розробники замість QA, викинути одну «зайву» ланку з процесу та як саме зрозуміти, чому і коли вона «зайва». Ну і, звісно, було запитання, чи готовий я побудувати такі процеси в компанії (на що я відповів згодою).
Сама по собі концепція тестування розробником власного ж коду без QA (читай тут як «тестувальника») не нова. Є досить відома в QA-спільноті книга «How Google Tests Software», в якій описано, як компанія Google вже багато років досить успішно випускає на ринок нескінченну кількість продуктів, не маючи в штаті класичних для нас QA Engineers.
Так, хтось із читачів може зауважити, що в Google є Software Engineer in Test (SDET), але по суті це все одно розробники, які просто працюють на сусідньому «станку». Саме через цю книгу усіх QA почали лякати, що їхня професія скоро вимре і потрібно якомога швидше навчитися кодити. Як бачимо, не вимерли 🙃
Стан речей у точці відліку
Як у класичних задачах зі шкільного курсу фізики (ех... які ж чудові були часи і трава здавалася зеленішою), маємо вихідні дані:
- Декілька продуктових команд
(3-4 розробники, дизайнер, product owner per team). - Окрема DevOps-команда.
- Окрема QA-команда (кілька General QA, переважно в бік Manual), яка досить довгий час працювала без тімліда.
- Розробка по принципу Trunk-Based Development із використання Feature Flags (FF).
- Стандартний конвеєр розробки: «постановка задачі → написання коду розробником → тестування задачі QA-інженером → реліз на продакшн».
Так, на той момент QA-команда фактично працювала як «сервісна» (хоч і не офіційно), а продуктові тіми не мали виділених QA-інженерів. І все це у продуктовій компанії, а не в аутсорсі. Одна невелика QA-команда на декілька продуктових — це автоматично означало високе навантаження та безперервний потік задач.
І, мабуть, уже очевидно, де часто виникав той самий bottleneck. Рядовий QA-інженер навіть не мав часу думати про якісь «високі матерії» Quality Assurance. Додамо до цього ще й застарілий та не надто надійний фреймворк для запуску UI-автотестів (Python + Selenium), відсутність чітких процесів тестування, які підходили б для Trunk-Based Development, а також великий обсяг присідань та ручної роботи для проведення одного релізу (повірте, її дійсно було багато).
Тож роботи у мене і команди було більш ніж достатньо.
Формування концепції «QA Required» або «тестуємо за вимогою»
Було очевидно, що щось потрібно змінювати або принаймні вибрати вектор руху. Варіантів було два: або кількісно й якісно нарощувати QA-команду, або оптимізовувати процеси. Як зрозуміло із назви статті, ми обрали саме вектор оптимізації процесів. Ініціатива отримала назву «QA Required» або «тестування за вимогою». Якщо хочеш досягти цілі, то візуалізуй її.
Втім мушу визнати, що згодом ми все ж найняли плюс одного QA-інженера — і це було виправдано: зросла кількість розробників та кількість контекстів, які потрібно тримати в голові.
Чого ж хотілось досягти? Ми прагнули якщо не повністю прибрати, то принаймні значно скоротити «зайву» ланку з тестування кожної задачі із реліз-кандидата, тобто спростити конвеєр (мал. 1).
Мал. 1. Спрощення конвеєра SDLC
Також нам необхідно було:
- Зменшити накладні витрати на передачу контексту між розробником і тестувальником у межах конкретної задачі. Якщо задача проста (привіт, декомпозиція) й розробник у змозі її самостійно протестувати/провалідувати, то це банально буде значно «дешевше», ніж залучати ще одну людину. Навіть якщо час, витрачений розробником і QA, приблизно однаковий, ми все одно виграємо з точки зору комунікації. Так, можна апелювати, що час розробника зазвичай дорожчий. Але головне питання — інше: чи виграємо ми на довгій дистанції й чи пришвидшимо випуск продукту?
- Зменшити кількість перекидань багів «через паркан». Цей пункт нерозривно повʼязаний із попереднім. Заведення багів, які ти бачиш в перші дві хвилини тестування задачі, потребують значного часу від QA-інженера (банально наклацати кнопочки в Jira по баг репортах), який міг би бути направленим у більш конструктивне русло. Чому тоді самому розробнику не провести ці дві хвилини за тестуванням і не уникнути бюрократії?
- Додати більше відповідальності за свою виконану роботу (читай як «підвищити культуру розробки»). Коли над однією задачею працюють і розробник, і QA-інженер, то відповідальність між ними розмивається: складніше зрозуміти, хто «крайній», і зростає рівень невизначеності.
- Можна заперечити, що схожа логіка є й у співпраці продакт-розробник. Відповідальність між ними теж не дуже чітка, але це не означає, що продакт сам має писати код. Тут важливо не впадати в крайнощі, про що і прошу свого читача. Вважаю, що необхідно розділити постановку задачі та її виконання.
Лаконічнно наша мета звучала так: «Досягти більшої швидкості/ефективності і не втратити в якості». Так, поставлена ціль може бути досягнута й в інших площинах. Наприклад, впровадити різні інструменти контролю якості коду в CI/CD, покращити процес Code Review, інтегрувати AI-агентів. Але наголошу, що стаття описує роботу саме в площині Quality Assurance. Та одне іншому не заважає.
Підготовка до впровадження концепції
Думаю, це очевидно, що неможливо прийти і заявити, що сьогодні за помахом чарівної палички задачі тестують розробники, а не QA. Отже, потрібно було визначити ключові речі та етапи для запуску концепції «QA Required».
Ми визначили наступні пункти, які потрібно було реалізувати/доробити:
- Правильна піраміда тестування.
- Зменшення бюрократії або автоматизація релізного процесу.
- Адаптація процесів та інструментів під нову для нас концепцію.
Далі розглянемо основні деталі нашої підготовки.
Реалізація правильної піраміди тестування
У точці відліку ми мали радше «трапецію» тестування, а не піраміду. Unit та інтеграційні тести у нас пишуть розробники і стан справ там був цілком непоганий. Зі свого боку я підключив туди збір метрик по Code Coverage з подальшим відображенням в Grafana, а також вивів результати покриття коду тестами в Merge Requests. Верхня частина піраміди, яка переважно завжди у зоні відповідальності QA-інженерів, була не у критичному стані, але роботи там усе ж було багато.
Що ж було не так із верхівкою піраміди тестування? Передусім вона просто не була готова до швидкого масштабування і ледь витримувала темп роботи, який ми мали на той момент. Якщо ж говорити про конкретні речі, то можна виділити дві основні проблеми:
- Ненадійні E2E (UI) автотести.
- Невизначеність та хаос у тестуванні нового функціоналу.
Нові E2E (UI) автотести
Наведу декілька проблем зі старим фреймворком та набором E2E тестів:
- Довга тривалість одного запуску
(10-15 хв на запуск ~60 тестів). - Відсутність підтримки горизонтального масштабування у самому фреймворку.
- Багато хардкоду, багато звʼязності, мінімальне використання динамічної генерації даних.
- Велика кількість флакі-тестів, які «лікувалися» ретраями всього підряд.
- Неповноцінна, незручна система репортингу та логування результатів.
- Базова інтеграція в CI/CD.
- Фреймворк писався частинами з залученням багатьох різних людей.
- Багато мертвого коду.
- Використання Selenium WebDriver замість Plawright (пробачте, любителі олдскулу).
Можна згадати ще низку більш дрібних проблем, але, думаю, що стан справ ви вже вловили. На правах QA Team Lead я мав повноваження вирішити, що робити далі: обрати глибокий рефакторинг чи переписати все з чистого аркушу. Оп-оп, я вибрав другий варіант.
Тут зіграло два фактори:
- Моя основна мова програмування C#. З нею я вже пройшов вогонь і воду, тож був готовий швидко й якісно створити базову архітектуру саме на C#. Ціна відмови від Python була мінімальна 🙈
- Я не хотів працювати із Selenium WebDriver, тому що вже встиг пощупати Plawright.
Тож накидав верхньорівневу архітектуру (мал. 2), написав PoC, захистив своє рішення перед СТО (тут дякую за довіру) і за три місяці ми уже повністю «перекатилися» на новий фреймворк із переписаними тестами.
Мал. 2. Верхньорівнева архітектура нового тестового фреймворку
Як ви вже здогадалися, всі мінуси попереднього фреймворку були перетворені у плюси в новому. З основних досягнень можна виділити наступні:
- Тривалість тестів скоротилася до ~ 3 хв 30 сек, і це на 80 тестів (мал. 3). Самі ж тести тривають десь біля 2 хв 30 сек, весь інший час — уже накладні витрати, які ми намагалися скоротити до мінімуму.
- Додали горизонтальне масштабування і значно підвищили стабільність (мал. 4).
- Створили найкращу систему репортингу, яку тільки змогли :) (мал. 5, тест зафейлив навмисно, щоб показати репортинг).
Мал. 3. Зменшення тривалості тестів
Мал. 4. Горизонтальне масштабування тестів
Мал. 5. Система репортингу результатів тестів
Великою перевагою нового рішення із репортингом стало те, що всі артефакти хостяться на AWS S3 стореджі і ми маємо доступ до них просто через URL. Plawright Trace Viewer, який ми хостимо на власній інфраструктурі, самостійно підвантажує ZIP-архів, парсить його і ми відразу можемо працювати з ним у браузері. Не потрібно нічого завантажувати на localhost чи перекидатися файликами у робочих чатах.
Сподіваюся, я зміг переконати свого читача, що перший пункт плану ми виконали на совість. До речі, BDD (SpecFlow чи Cucumber) я не використовував, бо я не фанат додаткового текстового рівня абстракції. Переходимо до наступного етапу.
Формування «визначеності»
Як можна прийти і «качати права», якщо у власній команді ще роботи непахане поле? Найбільшою проблемою QA-команди була невизначеність. Усі відповідали за все підряд і водночас ні за що конкретно. Виривання із контексту (чи з так званого робочого потоку) було звичною справою.
Responsible QA. Перше, що ми зробили, це впровадили поняття Responsible QA. Це стосувалося всього: від ведення релізу до обробки запитів від support-команди чи звернень від інших тіммейтів із проханням допомогти. Те ж саме стосувалося і тестування нового функціоналу (тут маю на увазі великий блок змін, що офромлений у Epic в Jira). Так ми отримали відповідь на запитання «Хто за що відповідає?» Ми більше не витрачали свій ресурс на зайву комунікацію, не чекали одне одного, не «виривалися» із контексту. Ну, і, звісно, ми почали транслювати цей підхід іншим.
Traceability Matrix. Ідемо далі. Спершу було досить складно отримати відповідь на запитання «Як і що ми тестуємо в межах епіка?». Не було чіткої стратегії, задачі тестувалися часто без врахування контексту і робота дублювалася на фінальній стадії розробки нового функціоналу. Брали технічне завдання і на ходу звіряли, що було зроблено, чого бракує або що реалізовано не так як слід.
Для мене як для ліда це було критично важливо вирішити. Проблему вдалося закрити за допомогою такого інструменту, як Traceability Matrix (мал. 6).
Мал. 6. Зразок Traceability Matrix
Так, перш ніж мій читач потягнеться до клавіатури, я з вами погоджуюся, що це радше старий добрий чекліст на максималках. Але я справді надихався класичними Traceability Matrix, коли формував цей Google Sheets шаблон. Тому й назву ми залишили відповідну. Такий артефакт ми складаємо для кожного епіку ще на ранніх етапах розробки нового функціоналу. Джерелом для нас є три речі:
- Технічне завдання.
- Дизайн-документ (технічне рішення від команди розробки).
- UI/UX від команди дизайнерів.
Також варто пояснити, чому я вибрав саме Google Sheets як інструмент для формування і ведення матриць, а не такого монстра як TestRail чи вже існуючий у нас Allure TestOps. І справа тут зовсім не в грошах. Наведу свої аргументи:
- Надзвичайно низький поріг входу, фактично доступний для кожного. Спробуйте запросити когось із розробників чи продактів зайти, наприклад, в TestRail. Як довго вони там пробудуть і як часто туди заглядатимуть?
- Дуже потужний функціонал, завжди on the cutting edge.
- Легкий в адмініструванні: корпоративний імейл і погнали.
- Неперенавантажений інтерфейс, все перед очима.
- У нас не проєкт по запуску космічних кораблів чи старезний e-commerce з купою «корнер кейсів» і сценаріїв, що вимагали б прискіпливої документації та сотень тест-кейсів. Динаміка нашої розробки вбивала б всі наші тест-кейси за лічені тижні, а ціна підтримки їх актуальності надто висока. Хоча так, тестову документацію ми все ж таки ведемо у Confluence з описом складного функціоналу для себе у майбутньому.
І ось ми дійшли до етапу, коли навели лад у себе «вдома» (принаймні мені дуже в це хочеться вірити). З трапеції ми зробили піраміду тестування. Також я значно вклався у технічний розвиток своєї QA-команди, але це вже зовсім інша історія, тому не відволікаємось і рухаємось далі.
Зменшення бюрократії або автоматизація релізного процесу
Насправді я вам набрехунькав — зменшити бюрократію мені не вдалося. Ймовірно, що своїми змінами я навіть її трохи поглибив. Так, можна собі просто робити «тікетосіки», доставляти на продакшн і не запарюватися. Проте коли підіймають питання про метрики, аналіз, постмортеми, звітність і так далі, то вся ця бюрократія видається дуже потрібною. Вона свого роду задає «правила гри», дозволяє зберігати рамки пристойності і не втрачати тонус. Варто уточнити: я говорю саме про ту частину бюрократії, яка виникає відразу після того, як розробник завершив свою задачу, влив її в master/main бранчу і код доїхав до тестового контуру. Далі вся робота з доставки змін була на QA-команді.
Тепер для повноти картини давайте поглянемо на основні дії, які Responsible QA робив для кожного релізу:
- Ручне створення релізу в Jira.
- Ручне додавання Fix Version для кожного тікету.
- Ручна зміна статусів тікетів по Jira-борді.
- Ручний запуск джоби із E2E-тестами та транслювання результатів.
- Ручне тестування усіх задач перед викаткою на продакшн.
- Ручна нотифікація про стадії релізу в Slack повідомлення, в так званому Release Candidate Message.
- Ручний апдейт продакшна.
- Ручне прокидування release notes (changelog) в спеціальний канал в Slack.
- Ручний апдейт статусів тікетів в Jira та закриття релізу й закриття самого релізу.
Можна подумати, що «ну, норм, не так вже й страшно». В такому випадку пропоную поглянути на динаміку релізів (мал. 7).
Мал. 7. Динаміка розробки
Я не дарма вище у списку постійно згадував «ручну» роботу. Тепер давайте спробуємо зіставити навантаження та кількість ручної роботи для QA-команди з таким розкладом. За день
Що ж ми зробили? Ми взялися за автоматизацію всієї рутини в релізному процесі. Від автоматичного створення релізів в Jira до постингу release notes у Slack-канал.
QA-команда виступила тут як «замовник» і сформувала технічне завдання, тобто вимоги до автоматизованого релізного процесу. Звісно, технічне завдання пройшло всі рівні погодження, після чого його взяли в роботу. Станом на зараз реалізовано приблизно 80% від початкового скоупу. Квінтесенцією всього стало Release Candidate Message в Slack під кожен реліз (мал. 8).
Мал. 8. Release Candidate Message в Slack
Таким чином ми знаємо й автоматично фіксуємо кожен крок релізу, більше жодного ручного пересування тікетів по статусах на Jira-борді. В тред релізного повідомлення відразу кидається запланований changelog, а також туди падає ще низка автоматичних повідомлень по ходу «розвитку сюжету». За кулісами (в Jira, в GitLab) усе так само автоматизовано і синхронізовано із тим, що ми бачимо у Slack.
Відверто скажу, що на момент запуску нашої концепції «QA Required» релізний процес ще не був автоматизованим. Було сформоване технічне завдання і роботи тільки розпочалися. Проте вже за деякий час ми отримали перші й найважливіші для нас порції автоматизації. Це був фʼючерс.
Адаптація процесів та інструментів
Фінальна частина нашої підготовки до впровадження концепції «QA Required» стосувалася процесів та інструментів.
Ми використовуємо досить банальний project management інструмент для IT індустрії — Jira. Тому не буде секретом, що
Ми зібрали робочу групу (насправді, їх було декілька у різний час), завданням якої було узгодити всі тонкощі щодо того, хто, що і коли тестує. Не буду вас втомлювати всіма раундами дискусій, а наведу відразу фінальні домовленості.
В тікет Jira ми ввели два нових поля:
- QA Required
- 🟡 QA: yes
- 🟤 QA: no
- Testing Status:
- ⬜ not tested
- 🟪 in progress
- 🟩 passed
- 🟦 safe
- 🟥 failed
Цей набір емодзі ви могли бачити вище у Release Candidate Message, а саме у треді. Чому емодзі? Тому що за ними легко та швидко орієнтуватися (мал. 9). Вертикальна кольорова палітра на картах відображає Testing Status.
Мал. 9. Адаптація Jira під «QA Required»
Кожен тікет мав стан за замовчуванням: 🟤 QA: no + ⬜ not tested. Тобто фактично кожна окрема задача як одиниця змін (це дуже важливе уточнення!) за замовчуванням тестується розробником. Втім, у нього є право для конкретної задачі «вимагати» її тестування силами QA-інженера (звідси й назва «QA Required»).
Вище я вже наводив наше бачення того, що підпадає під «🟡 QA: yes», а що ні. Таким чином, на етапі формування Release Candidate (статус Frozen у нас) ми уже знаємо, які тікети були протестовані або провалідовані розробниками, а які вимагають тестування від QA-інженера.
Варто сказати кілька слів і про два значення Testing Status:
- 🟩 passed — це фінальне значення, яке каже «задача повністю протестована і не потребує уваги»;
- 🟦 safe — це також фінальне значення, яке каже «задача безпечна для поставки на продакшн» (тут памʼятаємо про роботу із використанням Feature Flags). Фактично така задача зазвичай має «відкладене» тестування, але не як окрема одиниця змін, а вже як частина повноцінного нового функціоналу. Наприклад, рання задача із якогось епіку, яку Responsible QA уже перевірить в рамках Traceability Matrix.
Чисто технічно значення 🟩 passed та 🟦 safe мають однакову силу, але нам, людям, із ними простіше працювати.
Для контрасту — як було раніше? Практично всі задачі проходили через руки QA-інженера, коли потрібно, і коли ні. Також варто зазначити, що у нас існував лейбл qa_skipped. Його суть в самій назві: задачу, яка має цей статус, можна безпечно пропустити на етапі тестування QA-інженером. Ви можете зауважити, що це фактично те ж саме, що зробили ми, але діаметрально протилежне, і ви будете праві.
І тут я вам відповім, що...це взагалі не працювало. Чітких домовленостей не було, лейбл потрібно було ставити додатково, а цим дуже часто нехтували. Ну, і на той час сама QA-команда не могла дати кращих «гарантій безпеки». От воно все й буксувало.
Всі наші домовленості ми зафіксували у документах в Confluence після декількох раундів переговорів. І були готові до впровадження.
Запуск «QA Required» та результати
До календаря кожного представника команди розробки полетіло запрошення на загальний мітинг-анонс відносно нової для них концепції «QA Required». Все було готове з мого боку:
- Погоджено із представниками менеджерського складу.
- «Прогріта» аудиторія через тімлідів back-end та front-end напрямків.
- Проведений інструктаж QA-команди з попередніми обговореннями.
- Написана документація із детальним поясненням всіх аспектів.
- Виконані всі кроки, які я описував вище, окрім повної автоматизації релізного процесу.
Проте всюди подушку не підстелиш 🥲 Із «залу» все ж було декілька уточнюючих запитань. Це була та сама стадія заперечення. Після презентації ми провели кілька дискусій в особистих чатах (і це супер, бо показує небайдужість людей!) та позитивне рішення було прийнято. Все йшло до неминучого — до стадії прийняття.
Найбільший страх чи ризик, який підсвічували, звучав приблизно так: «Я ж звик, що мене страхують, за мною тестують, що є інша точка зору...» Найголовнішим було донести до розробника думку: «У тебе не забирають QA-інженера, ти маєш право вимагати його допомоги, проте роби це свідомо та ефективно. Тоді ти сам будеш ефективнішим, твоя команда буде ефективніша, твоя компанія буде ефективніша».
Ми не «спустили» процес тоталітарно згори, ми слухали людей і точково вносили зміни то тут, то там. Власне, на фідбеках команди ми і будували саму концепцію перед впровадженням (я буквально бігав до тіммейтів і збирав їхні попередні фідбеки і побажання). Тімліди розробки були представниками своїх напрямів.
Що ж, ми поїхали. Старт вийшов значно легшим, ніж я очікував: кілька невеликих правок, дискусії в чатах, і робота кипіла.
Перші результати виглядали так:
- перший місяць:
- 🟡 QA: yes — 26%
- 🟤 QA: no — 74%
- другий місяць:
- 🟡 QA: yes — 35%
- 🟤 QA: no — 65%
Загалом ми розцінюємо це як хороший старт. Ми не ставили якогось цільового співвідношення цих показників. Натомість вирішили оцінювати результати ретроспективно.
Спочатку статистику збирали руками, аналізуючи запити в Jira. Потім QA-команда розробила сервіс по збору Quality Metrics, і одним із джерел стала Jira (один із графіків ви вже бачили вище на мал. 7). Зараз ми можемо оцінювати в динаміці, як працює наша концепція і вчасно реагувати на події (мал. 10). Сам сервіс ми запустили повноцінно на початку вересня.
Мал. 10. Динаміка «QA Required»
Загалом із даною концепцією ми уже живемо понад 8 місяців. На такій дистанції вона себе виправдала і показала ефективність. Ми вийшли на показник у 34% «🟡 QA: yes» за цей час.
Окей, ви запитаєте:
- «А як змінилася динаміка релізів?» — зросла від
40-50 до50-70 релізів за місяць. - «А як змінилася динаміка розробки?» — зросла із
200-250 до250-350 задач на місяць. - «А як змінилася кількість багів і чи не просіли ви з точки зору якості?» — ні, ми не втратили у якості. У нас є свій коефіцієнт якості (кількість багів високого пріоритету на продакшн / на кількість випущених задач * 100%). Порівняйте:
- за пів року до введення: мінімальний 2.86, максимальний 4.78;
- пів року після введення: мінімальний 1.15, максимальний 4.47;
- політ останні два місяці: 1.85 (мал. 11). Нагадаю, що метрики у лайв-форматі збираємо саме два останні місяці, тому старт із нуля самої метрики.
- «А як розробники анонімно оцінюють нову концепцію, ви робили опитування?» — так, робили анонімне опитування через декілька місяців польоту. Поставили два запитання:
- твоя оцінка ефективності від впровадження QA Requried? — 8.7 із 10;
- твоя оцінка задоволення від впровадження QA Requried? — 8.0 із 10.
- «А ви впевнені, що ваші показники покращилися лише за рахунок „QA Required“?» — звісно ж ні, не тільки за рахунок нової концепції. Ми живемо у відкритій моделі із безліччю вхідних параметрів, кожен із яких так чи інакше впливає на фінальний результат. Наприклад, не буду лукавити і скажу, що великим фактором у зростанні динаміки розробки (релізи + кількість задач) відіграв автоматизований релізний процес та правильна піраміда тестування. Проте вважаю, що вони є невідмʼємною частиною нашої концепції.
Мал. 11. Динаміка якості розробки
Ось такими є наші результати. Якщо я чогось не передбачив з ваших запитань, то сміливо задавайте їх у коментарях. Настав час закінчувати статтю та переходити до висновків.
Висновки та післяслово
Ми не здійснили революцію, не «хакнули» цей світ. Ймовірно, ми навіть винайшли свій власний велосипед. Проте ми зробили його з увагою до деталей, «під себе, а не на продаж». Тож на ньому приємно і не страшно їхати у довгу подорож.
Так, в кінцевому підсумку, ми тестуємо все, але уже не по декілька разів, як це було раніше. Кожен це робить у своїй зоні відповідальності, на своєму рівні. Ми відкинули усе зайве. Це й стало запорукою «легкості», яку ми отримали.
Стаття була б злочинно неповною, якби я не підкреслив, що я не «Д’артаньян», який зробив усе самотужки. Це були колективні обговорення, наша спільна робота та досягнення. Велика подяка Дмитру О., Сергію, Ігору, Юліану, Павлу, Ромі, Костянтину, Микиті, Дмитру К., Тимофію та всім, хто також доклав своїх зусиль. «Merci beaucoup» 🫰моїй Анастасії!
Сподобалась стаття? Підписуйтесь на автора, щоб отримувати сповіщення про нові публікації на пошту.

17 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів