Юзер менеджмент та костилі з якими ви стикнетесь в житті
Відео починається з еволюції конфігурації тестового проєкту — від environment variables і локального `.env` до структурованих config-файлів, CI secrets та централізованого config server. Друга частина розбирає testability користувачів: чому спільний статичний акаунт блокує паралельність, як перейти до керованого створення тестових користувачів і які шви потрібні для SSO, OTP, зовнішніх провайдерів, банківських процесів і state machines.
Примітка: конспект укладено за автоматичними українськими субтитрами; технічні терміни нормалізовано. Будь-який test-only обхід авторизації має бути технічно недоступний у production, а не захищений лише домовленістю команди.
Після цього уроку ви зможете
Відокремити config values від коду й зберегти однакові logical keys між environments.
Пояснити, чому shared test users блокують parallel execution.
Спроєктувати керований шлях створення test users через script або support API.
Виявити auth і state-machine dependencies, які потребують testability seam.
Environment variable передає процесу значення на кшталт base URL, username або password без hardcode у вихідному коді. У Unix-подібній оболонці змінну можна експортувати перед запуском; у Windows вона задається іншим системним механізмом. .env є зручним локальним представленням таких пар ключ–значення, яке застосунок читає під час старту.
Проблема з'являється, коли один продукт має кілька web/API/admin-сервісів і кожному потрібні окремі URL та credentials. Плоский набір ключів розростається, префікси дублюються, а залежності між значеннями стають неочевидними. Для невеликого проєкту .env достатній; переходити на складніший формат варто після реального зростання конфігурації.
Термін
Environment variable
String key/value у process environment. У Python os.environ надає mapping цих значень, а os.getenv() повертає value або default.
Приклад коду
Прочитати обов'язковий base URL з environment
import os
base_url = os.environ["BASE_URL"]
assert base_url.startswith("https://")
print(base_url)
Код використовує один logical key і fail-fast, якщо required value відсутнє або не відповідає мінімальному contract.
Очікуваний результат: Виводить https://example.test і завершується без помилки.
Наступний рівень — JSON, YAML, XML або інший структурований формат, який можна десеріалізувати у типізований config object. Це допомагає групувати налаштування за сервісами й середовищами, але файл із секретами все одно не можна публікувати в Git.
У складнішій системі конфігурацію може віддавати централізований config server. Він дозволяє сервісам отримувати актуальні домени, ключі й feature flags, інколи без повного redeploy. Тестовий код не повинен створювати паралельне джерело правди, якщо може безпечно використати той самий контрольований механізм, що й продукт.
Для dev, staging, UAT та інших середовищ можуть існувати окремі локальні файли, і кожен із них має бути проігнорований. Якщо файл випадково додали до індексу, простого нового правила в .gitignore недостатньо: треба забрати його зі staged/tracked стану й тільки тоді перевірити ignore.
Середовище не завжди визначається окремим доменом. Маршрутизація може залежати від path, cookie, custom header або feature flag; у production подібний механізм використовується для canary release. У тестах ці параметри мають бути явною конфігурацією, а не розкиданими константами.
Ланцюжок розвитку у відео: hardcode → .env → структурований config → централізований config server. Перехід потрібен лише тоді, коли попередній варіант уже створює вимірювану незручність або ризик.
Код має звертатися до стабільних логічних ключів на кшталт BASE_URL, не до DEV_BASE_URL або STAGE_BASE_URL з ручним replace. Цільове середовище вибирає джерело значень, а не інші назви змінних. Завдяки цьому локальний і CI-запуск проходять тим самим шляхом.
У CI значення зберігаються як захищені secrets/variables або як секретний файл. Репозиторій містить лише .env.example чи аналогічний шаблон зі структурою та без реальних credentials. Якщо використовується config server, CI може зберігати лише мінімальні credentials для доступу до нього.
Термін
CI secret
Protected value, яке workflow отримує через secret context або environment, а не з version-controlled source. Відсутній secret у GitHub Actions expression повертає порожній string.
Практика
Спроєктувати config і test-user lifecycle
Складіть однаковий список config keys для local, dev і CI без environment prefixes у коді.
Опишіть, хто створює test user, як він резервується для parallel worker і як відновлюється після failure.
Позначте зовнішні auth dependencies та окремо визначте production acceptance check і test-only seam.
Результат: Config matrix і state diagram без shared mutable user між parallel workers.
Спільний тестовий користувач створює race conditions: паралельні тести змінюють один стан, заважають один одному й роблять результат нестабільним. Найкращий шов — створювати унікального користувача або іншу сутність під конкретний тест чи worker.
Фізичне видалення даних може зламати foreign keys та історичні зв'язки з orders, invoices або іншими сутностями. Через це продукт часто застосовує soft delete: запис залишається, але отримує статус deleted/inactive. Для тестових середовищ потрібно знати реальну політику refresh/cleanup; не слід бездумно накопичувати персональні production-дані або копіювати їх без маскування й визначеного строку зберігання.
Найгірший варіант — один статичний користувач у локальному config. Він блокує паралельність і звужує набір доступних станів. Трохи кращий, але все ще дорогий процес — просити іншу команду вручну створювати набір акаунтів після кожного refresh тестового середовища.
Якщо tester не може сам створити invoice, user або іншу передумову, перевірка залежить від чужого робочого часу. Це не просто незручність автоматизації, а властивість системи: feedback loop довгий, а критичні сценарії важко повторювати. Обмеження потрібно фіксувати як testability risk і обговорювати з командою продукту.
Перша практична ітерація — отримати контрольований доступ до наявного скрипта створення користувачів. Скрипт може приховувати складну синхронізацію з державними або сторонніми системами та створювати валідний mocked-профіль для тестового середовища. Далі варто параметризувати потрібний тип і стан користувача та, за потреби, запускати provisioning за розкладом.
Кращий довгостроковий шов — test-support endpoint або інший сервісний контракт для створення сутності з унікальним email та потрібними атрибутами. Його можна спочатку викликати з Postman, Insomnia, Bruno чи IDE HTTP client, а потім перенести в test setup. Endpoint видалення не є автоматично безпечним: треба врахувати зв'язки даних і реальну модель lifecycle.
Створення та вхід можуть залежати від payment provider, державного сервісу, SSO, email/SMS OTP або MFA. Зовнішній провайдер не завжди має повноцінний sandbox; навіть коли він є, можливості та тарифи тестового режиму відрізняються.
Для тестового середовища потрібен офіційний test tenant/API key, тестові картки або керований спосіб отримати OTP. Інший варіант — окрема test-only форма з login/password, увімкнена серверною конфігурацією лише поза production. Це дає автоматизації стабільний шов, але не замінює окремі acceptance-тести справжньої інтеграції з провайдером.
Увага
Test hook не повинен послаблювати production authentication
Окремий header, account або form для automation має бути технічно недоступний у production. Production path повинен зберігати потрібні authentication factors, а authentication failures і lockouts — логуватися та моніторитися.
Термін
Multi-factor authentication
Authentication, що вимагає додатковий незалежний factor verification і зменшує ризик password-related attacks.
Типовий login flow проходить через frontend, backend і auth provider: клієнт надсилає ідентифікатор, provider доставляє або перевіряє challenge, backend після підтвердження видає session/token для наступних запитів. Розуміння цього маршруту показує, де саме тест блокується зовнішньою системою.
У відео пропонується test-only custom header або спеціальний акаунт, за яким backend пропускає зовнішній challenge. Такий hook допустимий лише з жорстким fail-closed дизайном: production build/config його не реєструє; доступ обмежений тестовою мережею та авторизованим test service; credentials короткоживучі; використання журналюється. Перевірка одного секретного header у production-коді створює критичний auth bypass і є неприйнятною.
Якщо команда не може створити користувача в потрібному статусі або змінити його стан, неможливо гарантувати комбінаторне покриття критичних flows. Це треба формулювати через вплив: які сценарії не перевіряються, скільки триває підготовка та який ризик проходить у release.
У регульованих системах інколи дозволений лише затверджений набір акаунтів. Тоді файл із ними залишається поза Git, передається через CI secret або контрольований config service, а тест обирає вільний профіль відповідного типу. Випадковий вибір без reservation не вирішує concurrency: потрібна оренда, блокування або розподіл акаунтів між workers.
У banking та інших регульованих доменах onboarding може проходити довгий Business Process Management flow з compliance-перевірками. Одна сутність не завжди може одночасно рухатися двома переходами стану, тому паралельні тести на спільному профілі конфліктують або блокують processing.
Для стабільної автоматизації потрібно знати state machine, зовнішні залежності та правила блокування. Якщо динамічне створення неможливе, керований pool тестових сутностей має враховувати їх поточний стан, reservation, recovery після падіння тесту та регулярне відновлення після refresh середовища.