Інтеграційне тестування гарантує те, що компоненти програми функціонують коректно, коли зібрані разом. ASP.NET 5 підтримує інтеграційне тестування за допомогою фреймворків для тестування і вбудованого тестового веб хоста, який можна використовувати для обробки запитів без навантаження на мережу.
Введення в інтеграційне тестірованіе¶
Інтеграційні тести перевіряють, щоб різні частини програми коректно працювали разом. На відміну від `` модульного тестірованія`_ інтеграційні тести часто запитують компоненти інфраструктури додатки, наприклад, БД, файлову систему, веб запити і відповіді і так далі. На місці цих компонентів юніт тести використовують mock-об'єкти, а інтеграційні тести повинні перевіряти, чи добре ці компоненти працюють в системі.
Оскільки інтеграційні тести працюють з великими сегментами коду і оскільки їм потрібні елементи інфраструктури, вони повільніше, ніж юніт тести. Тому вам не варто використовувати занадто багато інтеграційних тестів, особливо якщо ви можете перевірити деякий функціонал за допомогою юніт тесту.
Якщо один і той же поведінку можна протестувати за допомогою юніт тесту та інтеграційного тесту, виберіть юніт тест, оскільки він фактично завжди буде швидше. У вас можуть бути сотні юніт тестів, але всього лише кілька інтеграційних тестів, що покривають найбільш важливі сценарії.
Тестування логіки всередині методів зазвичай є завданням юніт тестів. А інтеграційні тести входять в гру тоді, коли треба перевірити, як додаток працює у фреймворку (наприклад, ASP.NET Core) або з БД. Вам не потрібно створювати занадто багато інтеграційних тестів, щоб перевірити, що ви можете додати запис або витягти її з БД. Вам не потрібно тестувати кожне можливу зміну в коді для доступу до даних - ви просто повинні переконатися, що додаток працює належним чином.
Інтеграційне тестування в ASP.NET Core¶
Щоб налаштувати інтеграційні тести, вам треба створити тестовий проект, пов'язаний з вашим ASP.NET Core веб проектом, і встановити механізм запуску тестів. Цей процес описаний в документації Unit testing. поряд з більш докладними інструкціями по запуску тестів і рекомендацій по іменування тестів і тестових класів.
Юніт тести і інтеграційні тести варто зберігати в різних проектах. Тоді ви випадково не включите елементи інфраструктури в юніт тести, і тоді ви зможете запускати або всі тести, або якийсь певний набір тестів.
тестовий хост¶
ASP.NET Core включає тестовий хост, який може бути доданий в проекти інтеграційних тестів і використовується для хостингу ASP.NET Core додатків, обробляючи тестові запити без необхідності реального веб хостингу. В даний приклад ми включили проект інтеграційних тестів, який буде використовувати `xUnit`_ і тестовий хост, як ви бачите нижче:
Після того як пакет Microsoft.AspNet.TestHost буде включений в проект, ви зможете створити і налаштувати TestServer. Наступний тест показує, як перевірити, то запит, відправлений до кореневої директорії сайту, повертає "Hello World!", І цей тест повинен пройти успішно для шаблону за замовчуванням ASP.NET Core Empty.
Ці тести використовують патерн Arrange-Act-Assert, але в даному випадку етап Arrange проходить в конструкторі, який створює екземпляр TestServer. Тут буде використовуватися WebHostBuilder для створення TestHost; в даному випадку ми передаємо метод Configure з класу SUT Startup. Цей метод використовується для настройки потоку запитів TestServer ідентично тому, як буде налаштований SUT сервер.
У частині Act тесту до примірника TestServer робиться запит для шляху "/", а відповідь зчитується в рядок. Цей рядок потім порівнюється з очікуваної рядком "Hello World!". Якщо вони однакові, тест пройде успішно, інакше - немає.
Ми можемо додати кілька додаткових інтеграційних тестів, щоб перевірити, що в веб додатку працює функціонал первинної перевірки:
Зверніть увагу, що ми не намагаємося протестувати правильність нашого механізму первинної перевірки, нам просто потрібно побачити, що веб додаток робить те, чого ми очікуємо. У нас вже є юніт тести, які працюють з PrimeService. як ви бачите:
Про юніт тестах ви можете дізнатися більше в статті Unit testing.
Тепер настав час подумати про те, чи подобається нам те, як виглядає наш додаток. Якщо ми побачимо погано пахне код. то варто провести рефакторинг додатки, щоб поліпшити його.
Рефакторинг для використання сполучного ПО¶
Рефакторинг - це процес зміни коду програми для поліпшення його зовнішнього вигляду без зміни його поведінки. В ідеалі рефакторингом потрібно займатися, коли у вас є набір пройдених тестів, оскільки тоді ви будете знати, що поведінка системи буде однаковим до і після змін. Якщо подивитися на спосіб, яким реалізована логіка первинної перевірки в нашому додатку, то ми побачимо наступне:
Цей код працює, але він далекий від того, як би ми хотіли реалізувати такий функціонал в ASP.NET Core додатку, навіть таке просте, як наше. Уявіть собі, на що буде схожий метод Configure. якщо нам знадобиться записувати в нього більше коду кожного разу, коли ми будемо додавати іншу кінцеву точку для URL!
Ми можемо додати в додаток MVC і створити контролер для обробки первинної перевірки. Але це трохи перебір, оскільки на даний момент нам не потрібен інший MVC функціонал.
Крім того, ми можемо використовувати ASP.NET Связующее ПО (Middleware). і тоді ми зможемо инкапсулировать логіку первинної перевірки в окремому класі і досягти кращого розподілу відповідальності всередині методу Configure.
Ми хочемо, щоб шлях до сполучній ПО був вказаний як параметр, так що клас очікує в своєму конструкторі RequestDelegate і PrimeCheckerOptions. Якщо шлях запиту не відповідає тому, який очікує побачити зв'язуюча ПО, ми просто викликаємо наступне сполучна ПО в ланцюжку. Частина, що залишилася коду, який був в Configure. тепер перебуває в Invoke.
Оскільки наше сполучна ПО залежить від сервісу PrimeService. ми також запрошуємо через конструктор екземпляр цього сервісу. Фреймворк надасть цей сервіс через Впровадження залежностей (Dependency Injection). і ми припускаємо, що він налаштований (наприклад, в ConfigureServices).
Оскільки сполучна ПО працює як кінцева точка в ланцюжку делегатів запиту, якщо шлях відповідає, то _next.Invoke НЕ буде викликаний в тому випадку, якщо це сполучна ПО обробляє запит.
Коли сполучна За на місці і створені деякі корисні методи розширення для полегшення конфігурації, після рефакторінга метод Configure виглядає ось так:
Після рефакторинга ми також знаємо, що додаток працює, як і раніше, оскільки інтеграційні тести пройшли успішно.
Також вам непогано коммітов зміни після того, як ви провели рефакторинг і всі тести пройшли успішно. Якщо ви практикуєте Test Driven Development, додайте Комміт в цикл Red-Green-Refactor.
Інтеграційне тестування надає більш високий рівень верифікації, ніж модульне тестування. При інтеграційному тестуванні ми перевіряємо інфраструктуру і то, як різні частини програми працюють спільно. ASP.NET Core пропонує TestServer. який значно спрощує запуск інтеграційних тестів.