Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

01.11.2024

TSSpec - Перевірка збіжності фронтенду та бекенду

Цього тижня довелося виправляти доволі типову ситуацію: фронтенд в разі помилки показував не детальний текст з бекенду, а натомість загальну “щось пішло не так”. По-перше, дякувати тестувальнику, що це помітив. По-друге, інтеграційні тести покривали тільки успішний випадок.

По-третє, оскільки ця функціональність вже існувала, а моя зміна тільки додавала ще одну детальну помилку, тому я її додав у сервісі, написав на нього юніт-тест та був задоволений — якби не тестувальник, то нічого б не помітив.

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

Засмучує те, що фронтенд та бекенд живуть окремим життям, а перевірка взаємодії обмежується інтеграційними тестами. От якби вони обидва були на TypeScript, тоді можна вживати однакові типи для клієнта та сервера API. Так ця категорія помилок зникає, навіть якщо тестів не писати — ось вам ще одна величезна перевага TS.

А що коли бекенд на Ruby (on Rails)? Три роки тому я задав собі це питання та винайшов гем tscheck. Він поєднує типи TypeScript з тестами RSpec. В (нормальних) проєктах на Rails є юніт-тести контролерів, де ми перевіряємо варіанти їхніх відповідей. TSCheck дозволяє також перевірити, що відповідь контролера вірно реалізує деякий тип TypeScript. Це обмежена, але гарантія, що фронтенд та бекенд розуміють один одного.

Як воно працює? Простіше, ніж думаєте. Я будую файл TypeScript, що містить імпорт типу та константу зі змістом відповіді. Та передаю його у мовний сервіс tsserver - це той, що здійснює перевірку для VSCode тощо. У відповідь отримую перелік помилок: якщо вони є, тип не сходиться.

Є й інші розвʼязки цієї задачі — зокрема перевірка за схемою OpenAPI - але вони потребують додаткової роботи. А в мене все спирається на типи TypeScript, які у вас вже повинні бути. (Повинні бути, правда?)