Всіх вітаю з початком весни! Я Влад і сьогодні ми розглянемо заключне питання, але надважливе з точки зору грамотної та професійної розробки загалом і операторів та контролерів k8s зокрема. Нагадаю, що в минулій статті ми приступили до практичної частини поставленої задачі та написали невеличкий контролер, що керує valkey (open-source redis).
Інші статті циклу:
Частина 2. Імплементація контролера
Тестування є критично важливим етапом розробки будь-яких застосунків, адже саме тести дають впевненість, що все працює так, як задумано. Не є виключеннями і Kubernetes оператори та Custom Resource Definition (CRD) контролери. Якісне, багаторівневе тестування забезпечує надійність, стабільність та передбачуваність роботи оператора в різних умовах та сценаріях використання.
Kubernetes оператори часто керують критично важливими ресурсами та процесами в кластері, тому помилки в їх роботі можуть мати серйозні наслідки. Правильно організоване тестування допомагає виявити потенційні проблеми на ранніх етапах розробки.
У цій статті ми розглянемо різні підходи до тестування k8s операторів: від простих unit-тестів до повномасштабних end-to-end тестів у кластері тестового середовища. Також обговоримо інструменти та фреймворки, які допомагають автоматизувати процес тестування та забезпечити високу якість коду.
Особливу увагу приділимо специфічним аспектам тестування CRD контролерів, включаючи перевірку логіки reconciliation, валідацію Custom Resource об'єктів та тестування взаємодії з Kubernetes API.
Увесь код, що стосується практичної частини можна знайти на нашому GitHub:
https://github.com/uagolang/k8s-operator
Пропоную трохи зануритись (але не глибоко) в теорію тестування, щоб всі були на same page. В багатьох мовах програмування є свої назви для різних видів тестів, але загалом, стандартизуючи, я би виділив 3 основні види.
Модульні (unit) тести - є базовим рівнем тестування, що перевіряє окремі функції та методи на коректність роботи. Для більш складних випадків часто використовують табличні тести (table-driven tests). Вони дозволяють перевірити функцію з різними вхідними даними та граничні випадки.
<aside> 1️⃣
При написанні unit-тестів важливо дотримуватися таких практик:
Інтеграційні (integration) тести - перевіряють взаємодію між різними компонентами системи та їх коректну роботу разом. На відміну від unit-тестів, які тестують окремі функції ізольовано, інтеграційні тести перевіряють, як різні частини коду працюють разом. Для тестового середовища будемо використовувати пакет testenv
від Kubernetes.
<aside> 2️⃣
Особливості інтеграційних тестів:
End-to-end (e2e) тести - є найвищим рівнем тестування, який перевіряє всю систему в цілому, імітуючи реальне використання програми із реальною взаємодією із зовнішніми сервісами, тестуванням через користувацькі інтерфейси (API endpoints, CLI тощо) та перевірку всього потоку даних через всю систему.
<aside> 3️⃣
Особливості e2e тестів:
Мокування (mocking) - це техніка в тестуванні, де реальні об'єкти замінюються їх імітаціями для ізоляції тестованого коду від зовнішніх залежностей. У Go існує кілька підходів до мокування: