Приклад написання юніт-тестів в 1с-бітрікс проект, блог e-pages
У цьому пості будуть розглянуті приклади юніт-тестів, які перевіряють працездатність класу по реалізації віртуальних груп в магазині на 1С-Бітрікс. Я опишу роботу функціонала віртуальних груп, а також детально розберу код PHPUnit-тестів для його тестування.
Що таке PHPUnit
PHPUnit - це фреймворк для модульного тестування в PHP проектах. Він є представником сімейства фреймворків xUnit на основі пакету sUnit, зізнався Кентом Беком. PHPUnit розроблений німецьким програмістом Себастьяном Бергманом.
PHPUnit був створений з позиції - чим раніше ви виявите помилки в коді, тим швидше ви зможете їх виправити. Як і всі фреймворки модульного тестування PHPUnit використовує твердження для перевірки, що поведінка одиниці тестованого коду поводиться як і очікувалося.
PHPUnit надає програмісту наступні можливості:
- Інструменти для створення модульних тестів і організації їх в ієрархічні набори.
- Інтерфейс командного рядка для тестування
- Постачальники даних - генератори для тестування даних для перевірки, як єдиний тест поводиться на різних вхідних даних.
- Підтримка тестування коду, що використовує базу даних.
- Можливість тестування винятків.
- Підтримка так званих фіктивних об'єктів
- Генератор звітів
- Інтеграція з інструментом Selenium RC для тестування користувальницьких інтерфейсів
PHPUnit без проблем дозволяє тестувати сайти на базі Bitrix Framework. Перед тим, як продовжити читання, рекомендую ознайомитися з моєю статтею. де описано як можна подружити 1С-Бітрікс і PHPUnit.
Який функціонал будемо тестувати
Припустимо, у нас стоїть завдання покрити тестами функціонал віртуальних груп, який реалізований у вигляді класу. Поняття віртуальних груп детально розглянуто в нашій статті - Віртуальні групи в інтернет-магазині на 1С-Бітрікс. Якщо коротко - ми заводимо в каталозі розділи, в якому "фізично" не прив'язані товари. Ми можемо наповнювати ці віртуальні розділи за допомогою заповнення спеціальних властивостей, за якими будується фільтр і товари з'являються в ньому на льоту. Це дає багато переваг і дозволяє гнучко додавати нові розділи для просування магазина при цьому зберігаючи основну структуру вашого каталогу.
Перейдемо до технічних деталей. Функціонал досить складний і робота його залежить від багатьох параметрів, які складно перевіряти вручну при виникненні помилки. Авто тести дозволяють вирішити цю проблему і швидко покажуть в якому місці коду відбувається недобре. Функціонал працює на базі користувацьких властивостей розділів, в які ми набиваємо правила визначення товарів, що входять в поточну віртуальну групу. Також у нас є методи, які витягують ці властивості і будують фільтр для методу CIblockElement :: GetList (). який отримує товари, що відповідають заданим правилам. У віртуальний розділ можна збирати товари за двома типами налаштувань: по прив'язці до інших розділів в Інфоблоки і по прив'язці за властивостями товару. При цьому, прив'язка по розділах і властивостями множинна і можна вказувати логіку (І / АБО) для співвідношення розділів і елементів між собою відповідно. З цього є окремі методи, які отримують фільтри за цими типами налаштувань.
Розбираємо приклади юніт-тестів
Для тестування цього всього функціоналу у нас написано з десяток тестів, давайте їх розглянемо. Перший тест - самий базовий і яким би банальним він не був, ми вважаємо його необхідним. Критичне умова для роботи віртуальних груп - це, в найпершу чергу, наявність встановленого модуля Інформаційних блоків в системі. Це може перевірити такий тест:
Далі потрібно перевірити чи всі потрібні для користувача властивості є в системі. Це можна зробити в тесті зробивши вибірку по заданих символьним кодами властивостей використовуючи API 1С-Бітрікс:
Цей тест є фундаментальним, з цього від нього залежать кілька інших тестів, які я опишу нижче. Тобто вони повинні виконуватися тільки за умови, що testCatalogSectionHasNeededUserProps () пройшов успішно, інакше немає сенсу їх перевіряти.
Наступні 2 тесту перевіряють чи правильно працюють методи по вилученню ідентифікаторів прапора І / АБО для розділів і властивостей елементів (потрібно для внутрішньої логіки функціоналу). Тестовані методи викликаються в конструкторі і зберігають ідентифікатори значень користувацьких властивостей в властивості об'єкта. Значить завдання тестів вручну отримати правильні ідентифікатори значень користувацьких властивостей, взяти їх за еталон, створити екземпляр тестового класу і перевірити потрібні властивості об'єкта на відповідність стандарту. Ось як це виглядає:
Зверніть увагу на анотацію методів - @depends testCatalogSectionHasNeededUserProps. Це анотація надається PHPUnit і вона встановлює правило, що конкретний тест повинен виконуватися тільки в тому випадку, якщо заданий в залежності тест пройшов успішно.
Далі нам потрібно перевірити як себе веде конструктів якщо передати йому невірний вхідний параметр. У нашому випадку він повинен викинути виняток базового класу винятків - Exception. Це можна перевірити за допомогою вбудованої анотації @expectedException. ось так:
Наступний крок - перевірка методів, які будують фільтр і повертають його клієнтського коду. Для проведення цих тестів нам потрібно скористатися мокко об'єкта тестованого класу. Мокка (англ. Mock) - це спеціальний фіктивний об'єкт, який дозволяє в нашому випадку зімітувати отримання даних по розділу із зовнішнього джерела. Наш тест не повинен залежати від інформації конкретного набору віртуальних розділів в БД, з цього ми підміняємо (імітуємо) реальне витяг масиву з БД на свій статичний заданий прямо в коді масив.
Так як цей фіктивний mock-об'єкт буде потрібен нам в декількох тестах - ми винесемо його в окремих protected-метод. PHPUnit при виконанні тестів не буде вважати цей метод тестом і не буде намагатися його виконати. Ось код цього методу:
Наступний тест з використання mock-об'єкта перевіряє роботу методу, що визначає який розділ був переданий конструктору на вхід: реальний або віртуальний:
Щоб протестувати роботу методу, який будує фільтр, нам потрібно перевірити, що він всередині себе хочаб один раз викликає методи з будівництва фільтра по частинах (прив'язка до розділів і властивості елементів):
Також нам критично важливо, щоб результуючий масив з фільтром повертав ключ VIRTUAL_GROUP. так як його використовує клієнтський код. Ось тест, який перевіряє цей момент:
Ось ще парочка тестів, які перевіряють внутрішні методи тестованого класу. Яка поведінка вони перевіряють можна зрозумілий з assert-методів:
PHPUnit - потужний інструмент, який позбавляє від ручної перевірки багатьох можливих параметрів при виникненні помилки. Маючи під рукою юніт-тести ми можемо сміливо вносити змінити в тестований клас, додавати і розширювати його функціонал, при цьому бути впевненими, що наші нові зміни не поламали поведінку, яке очікує від класу клієнтський код.
Упевнений, що покриваючи тестами код, який ви пишете, не раз повернеться до вас у вигляді економії маси часу при налагодженні вашого веб-сайту і пошуку виникла помилки. При розробці функціоналу віртуальних груп тести кілька разів вказали нам на допущені помилки при інтеграції нових змін, що дозволило відразу визначити і вирішити проблему, так що написання тестів це хороша інвестиція в якість вашого проекту.