Найкращі способи тестування ваших безсерверних програм

Без сервера - це більше, ніж модель виконання хмарних обчислень. Це змінює спосіб планування, створення та розгортання програм. Але це також змінює спосіб тестування наших додатків.

Знайомтесь з Алексом. Алекс - звичайний розробник JavaScript, орієнтований на Node.js останнім часом.

Це Олексій

Останні кілька місяців його хороші друзі, Анна та Джефф, завжди говорять про те, що без сервера. Навіть через те, що час від часу вони дратують, йому подобається ідея додатків без серверів. Він навіть розгорнув кілька простих функцій для AWS Lambda та Azure в якийсь момент.

Анна та Джефф завжди говорять про те, що без сервера

У якийсь момент Алекс та його команда отримали новий проект. Після деякого аналізу Алекс подумав, що це буде ідеально підходить для безсерверних. Він представив ідею своїй команді. Деякі члени команди були схвильовані, одному з них це не сподобалось, але більшість із них не мали сильної думки. Тож вони вирішили спробувати - проект був не надто великий, а ризик був низьким.

Команда Алекса обговорювала використання сервера у своєму новому проекті

Команда прочитала про безсерверний сервіс, і вони зрозуміли, як структурувати свій новий додаток. Але ніхто не був впевнений, як вони повинні вписуватися без сервера в їх спільний процес розробки.

У цей момент їх процес виглядає приблизно так:

  1. Вони аналізують нову особливість.
  2. Для менш складних функцій вони починають з коду, потім запускають його локально і додають кілька тестів врешті-решт.
  3. Для більш складних функцій вони роблять свою версію TDD: починають з тестів, потім записують код і тестують його локально.
  4. Коли функція готова, вона переходить до інструмента CI, який розгортає її до тестового середовища.
  5. Тоді команда QA бере нову функцію для чергового раунду ручного тестування. Якщо все виглядає добре, додаток переходить через CI до виробництва.
Загальний процес розвитку команди Алекса

Вони вирішили почати крок за кроком, а потім вирішити проблеми, коли вони зіткнулися з ними.

Вони вибрали невелику функцію, і як це було просто, вони почали з коду. Коли частина кодування була готова, вони потрапили на перший блокпост: як запускати безсерверні програми на локальному рівні?

Місцеве тестування

За допомогою серверних додатків ви не керуєте інфраструктурою. Звучить чудово, але як потім запустити свою програму локально? Ви навіть можете це зробити?

Перше блокування: як запускати додаток без сервера на локальному рівні?

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

  • Основні інструменти Azure Functions (для функцій Azure)
  • AWS SAM CLI (для додатків AWS Lambda, побудованих за допомогою AWS SAM)
  • Сторонні інструменти (тобто локальний стек)
  • docker-lambda для локального моделювання AWS Lambda
  • Запустіть функцію Node.js локально

Звичайно, список не повний - є більше інструментів, і нові інструменти ми бачимо майже кожен день.

Більшість цих інструментів мають певні обмеження. Вони можуть імітувати безсерверні функції та декілька інших сервісів, таких як API шлюз. А як щодо дозволів, рівня авторства та інших служб?

Місцеве тестування допомагає у швидкій валідації, щоб переконатися, що ваша функція працює. Але чи є кращий спосіб переконатися, що ваш додаток без сервера працює за призначенням? Так, є. Перший і найважливіший крок: написання тестів.

Тож Олексій та його команда спробували свою першу функцію на місцях, і, як здавалося, це працює. Потім вони перейшли до наступного кроку.

Автоматизовані тести

Алекс та його команда просто перейшли на Jest для тестування своїх програм Node.js. Вони все ще мають багато передньої частини, тому хочуть використовувати ті самі інструменти для повного стеку, коли тільки можуть. Чи можуть вони використовувати Jest і для тестування додатків без серверів? І що вони повинні перевірити?

Другий блокпост: як сервер впливає на автоматичне тестування?

Після швидкого розслідування вони зрозуміли, що можуть використовувати свої улюблені інструменти тестування Node.js. Jest, Жасмін, Мока та інші прекрасно працюють без серверів.

Що слід перевірити в додатку без сервера?

За допомогою своїх додатків Node.js Алекс та його команда слідкують за трирівневою пірамідою автоматизації тестів. Тестову піраміду вперше згадував Майк Кон в своїй книзі «Успіх з Agile».

Як визначає тестова піраміда, вони мають:

  • Багато одиничних тестів, тому що вони найдешевші (найшвидші для написання та запуску)
  • Менше інтеграційних тестів, оскільки вони дорожчі, і вони потребують більше часу для запуску
  • Кілька тестів на користувальницький інтерфейс, оскільки вони найдорожчі (вимагає певного інструменту графічного інтерфейсу) і найповільніші для запуску

Окрім них, у них також є ручне тестування на основі сеансів, проведене їхньою командою з контролю якості.

тестова піраміда з ручним тестуванням

Як сервер впливає на піраміду автоматизації тестів?

Відповідь залежить від рівня. Але тестова піраміда виглядає менш як єгипетські піраміди, а більше нагадує піраміди майя.

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

Рівень тестів на інтеграцію стає важливішим, ніж будь-коли, тому що додатки без сервера сильно покладаються на інтеграцію. Це також дешевше, тому що мати безсерверну базу даних лише для тестування - це дешево. Отже, у «тестовій піраміді» без сервера потрібно мати більше інтеграційних тестів.

Шар тестів GUI також дешевший і швидший через дешевшу паралелізацію.

Шар ручного тестування залишається таким же. Але сервер може допомогти вам трохи покращити його. Ми детально розберемося пізніше.

Алекс і його команда нарешті мали деяке уявлення, куди зосередитись. Наступна проблема полягала в тому, як написати функцію, щоб легше їх перевірити.

Як написати тестовані функції без сервера

Під час написання функції без сервера потрібно думати про наступні ризики:

  • Ризики конфігурації Чи правильна база даних та таблиця? Або у вас є права доступу?
  • Технічні ризики робочого процесу Чи аналізуєте ви та використовуєте вхідний запит як слід? Або ви правильно обробляєте успішні відповіді та помилки?
  • Ризики ділової логіки Ви дотримувалися всіх правил ділової логіки, які має ваша програма?
  • Ризики інтеграції Чи правильно ви читаєте структуру вхідного запиту? Або ви правильно зберігаєте замовлення в базі даних?

Щоб підтвердити, що ваша безсерверна функціонує правильно, потрібно перевірити всі ці ризики.

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

Уявіть, якби тестування автомобілів робилося саме так. Це означало б, що кожного разу, коли ви хотіли випробувати один гвинт або навіть дзеркало в машині, вам доведеться зібрати і потім розібрати всю машину.

Щоб зробити додаток більш випробуваним, чітке рішення - розділити свою функцію на кілька менших.

Один із чудових способів зробити це - застосувати шестикутну архітектуру до функцій без сервера.

Шестикутна архітектура або «Порти та адаптери» - це форма архітектури додатків, яка сприяє розділенню проблем через шари відповідальності. Як її творець Алістер Кокберн пояснює:

Дозвольте програмі рівноправно керувати користувачами, програмами, автоматизованими тестовими або пакетними скриптами, а також розробляти та перевіряти їх у відриві від можливих пристроїв та баз даних, що працюють.

Отже, як це стосується функцій без сервера?

Оскільки Алекс та його команда використовують AWS, вони отримали таку структуру:

  • Функціональна бізнес-логіка відкриває кілька «портів» (або очікує мало аргументів). Наприклад, один для вхідних подій, один для постійного зберігання та один для сповіщень.
  • У них є два адаптери для події, яка запускає функцію, один для справжнього тригера AWS Lambda та інший для локального тестування.
  • Вони мають кілька адаптерів для постійного зберігання та оповіщення. Наприклад, адаптер таблиці DynamoDB та адаптер пам'яті.
Шестикутна архітектура функції AWS Lambda

Олексій та його команда були щасливі, що вони рухалися вперед. Але перш ніж ми продовжимо свою роботу, давайте подивимось, як шестикутна архітектура впливає на кожен рівень тестової піраміди.

Блок тестування

Одиничні тести залишилися колишніми. Але простіше писати одиничні тести через шестикутну архітектуру. Вони можуть просто використовувати локальний адаптер або макет як адаптер, щоб перевірити функціональний рівень бізнесу ізольовано.

Інтеграційне тестування

Інтеграційні тести багато виграли від шестикутної архітектури. Вони змогли повністю перевірити інтеграції, якими вони володіють. Інтеграція сторонніх моделей моделюється за допомогою інших адаптерів.

Як це працює на практиці?

Кожна їх безсерверна функція має файли lambda.js та main.js. Основний файл містить ділову логіку функції без сервера. І файл lambda.js відповідає за підключення адаптерів та виклик файлу main.js.

Основний файл має власний блок та тести інтеграції. Але його інтеграційні тести не перевіряють повну інтеграцію з кінцевими службами, такими як AWS S3, тому що це уповільнить їх. Натомість вони використовують адаптер в пам'яті для перевірки функції з інтеграцією файлового сховища.

Інтеграція AWS S3 здійснюється через FileRepository, який має власний блок та тести інтеграції. Для перевірки інтеграційних тестів використовується AWS S3, щоб переконатися, що кінцева інтеграція справді працює.

На відміну від main.js, у файлі lambda.js немає тестів, оскільки він у більшості випадків містить лише кілька рядків коду.

Візуальне представлення однієї функції AWS Lambda за допомогою тестів

Цей підхід схожий на техніку, яку команда MindMup використовує для тестування функцій без сервера. З його допомогою ви можете легко протестувати інтеграцію своїх функцій і все ж робити тести на інтеграцію швидше.

Тестування GUI

Оскільки Алекс та його команда будували задній додаток для програми, рівень тестів на графічний інтерфейс не був відповідним. Але дізнавшись більше про сервер, вони зрозуміли, що можуть використовувати його для покращення рівня тестів GUI для інших додатків, над якими вони працювали.

Тести на інтерфейс є дорогими та повільними, оскільки вони працюють у браузері. Але без сервера - це дешево, і він швидко масштабується.

Якби вони могли запустити браузер в AWS Lambda, вони отримали б дешеву паралелізацію. Це зробило б їх тести на інтерфейс користувача дешевшими та швидшими.

Але чи можете ви запустити браузер, як-от Chrome, всередині функції без сервера?

Так! І це легко за допомогою таких інструментів, як Chrome без сервера, Chromeless та Puppeteer.

Використання функцій AWS Lambda для паралелізації тестів на інтерфейс користувача

Поєднання безсерверних та безголівкових браузерів може принести нам нове покоління інструментів тестування інтерфейсу користувача. Ми вже можемо побачити та спробувати деякі з них, наприклад, Оцінити.

CI / CD

Оскільки Алекс та його команда перевірили свою першу функцію без сервера, настав час розгорнути код у тестовому середовищі. Це постало нове питання: як вони можуть використовувати інструменти CI / CD для розгортання своєї програми без сервера?

Відповідь проста: вони можуть використовувати інструмент CI для запуску тестів та розгортання програми. Щоб розгорнути додаток, використовуйте будь-який популярний інструмент, такий як Claudia.js, AWS SAM та Serverless Framework.

Ви все ще можете використовувати свій улюблений інструмент CI (наприклад, Jenkins, TravisCI або SemaphoreCI), або якщо ви хочете дотримуватися AWS, ви можете спробувати AWS CodeBuild.

Тестування вручну

Навіть через тестування вручну, на яке сервер не впливає безпосередньо, команда знайшла спосіб вдосконалити процес QA.

Етапи та розгортання безсерверного додатка - це дешево і часто швидко налаштовується. Крім того, без сервера ви не платите за додаток, якщо ніхто ним не користується.

Це означає, що наявність тестового середовища ніколи не була дешевшою!

Крім того, без сервера ви можете часто просувати функцію від одного етапу до іншого. Це означає, що ваша команда з контролю якості може перевірити функцію, і коли вони підтвердять, що вона працює, ви можете просувати цю функцію у виробництво.

Поза тестуванням

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

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

Екіпаж безсерверних проповідників отримав нового члена

Пост-сценарій

Але, хоча їх додаток було добре перевірене, щось сталося за ніч.

Після розслідування вони з’ясували, що одна з інтеграцій змінилася. Вони дізналися, що тестування важливе для серверних додатків, але цього недостатньо.

Оскільки додатки без сервера сильно залежать від інтеграції, ризик переходить від вашого коду до інтеграцій. І щоб отримати можливість інтегрувати зміни інтеграції та швидко реагувати, ваш додаток потребує належного моніторингу.

На щастя, з кожним днем ​​на ринку з’являється все більше безсерверних засобів моніторингу. Деякі з хороших і популярних варіантів - IOpipe, Thundra, Dashbird і Epsagon.

Але у безсерверних додатків часто є товстий клієнт, а це означає, що моніторингу зворотнього кінця недостатньо. Вам потрібен аналогічний інструмент для переднього кінця. Цей ринок також має багато приємних інструментів, таких як «Сентри» та «Роллбар».

Але в дусі безсерверного ми створили додаток для відстеження помилок з відкритим кодом під назвою Desole. Це безсерверний додаток, який можна встановити у своєму обліковому записі AWS. Це дає змогу організаціям відслідковувати винятки та помилки програм, не вибираючи між зручністю програмного забезпечення та послугою безпеки рішення, яке розміщується самостійно. Перевірити це можна тут: https://desole.io.

Desole, відкритий код відстеження помилок, тісно інтегрований з AWS
Усі ілюстрації створені за допомогою програми SimpleDiagrams4.

Якщо ви хочете дізнатися більше про тестування та створення програм без серверів за допомогою Node.js та AWS, перегляньте "Програми без сервера з Node.js", книгу, яку я написав з Олександром Симовичем для Manning Publications:

Книга навчить вас більше про тестування без сервера, на прикладі коду, але ви також дізнаєтесь, як створити та налагодити API реального світу без сервера (з БД та автентифікацією) за допомогою Node та Claudia.js. Ви навчитеся створювати чати, для Facebook Messenger та SMS (за допомогою Twilio) та Alexa.