Різні методи тестування
Спочатку визначте, що ви робите: Тестування блоку або тестування інтеграції . Кількість шарів не має значення для одиничного тестування, оскільки ви протестуєте лише один клас. Решту ви знущаєтесь. Для тестування інтеграції неминуче тестування декількох шарів. Якщо у вас є хороші одиничні тести, фокус полягає в тому, щоб зробити інтеграційні тести не надто складними.
Якщо ваші одиничні тести хороші, вам не доведеться повторювати тестування всіх деталей під час інтеграційного тестування.
Умови, якими ми користуємося, трохи залежать від платформи, але їх можна знайти майже на всіх тестових / розробних платформах:
Приклад застосування
Залежно від технології, якою ви користуєтесь, імена можуть відрізнятися, але я буду використовувати це як приклад:
Якщо у вас є проста програма CRUD із моделлю Product, ProductsController та індексним представленням, яка генерує таблицю HTML з продуктами:
Кінцевим результатом програми є показ таблиці HTML із переліком усіх активних продуктів.
Блок тестування
Модель
Модель ви можете випробувати досить легко. Для цього існують різні методи; ми використовуємо світильники. Я думаю, що це ви називаєте "підробленими наборами даних". Отже перед тим, як проводити кожен тест, ми створюємо таблицю і вводимо вихідні дані. Більшість платформ мають для цього методи. Наприклад, у вашому тестовому класі метод методу setUp (), який запускається перед кожним тестом.
Потім ми запускаємо наш тест, наприклад: testGetAllActive products.
Тож ми перевіряємо безпосередньо тестову базу даних. Ми не знущаємось над джерелом даних; ми робимо це завжди однаково. Це дозволяє нам, наприклад, протестувати нову версію бази даних, і виникнуть будь-які проблеми із запитами.
У реальному світі ви не завжди можете дотримуватися 100% єдиної відповідальності . Якщо ви хочете зробити це ще краще, ви можете використовувати джерело даних, з якого ви знущаєтесь. Для нас (ми використовуємо ORM), що відчуває тестування вже існуючої технології. Також тести стають набагато складнішими, і вони насправді не перевіряють запити. Тож ми зберігаємо це таким чином.
Важко закодовані дані окремо зберігаються у світильниках. Таким чином, кріплення схоже на файл SQL із створенням оператора таблиці та вставками для записів, які ми використовуємо. Ми залишаємо їх маленькими, якщо немає реальної потреби перевірити з великою кількістю записів.
class ProductModel {
public function getAllActive() {
return $this->find('all', array('conditions' => array('active' => 1)));
}
}
Контролер
Контролеру потрібно більше роботи, тому що ми не хочемо тестувати модель з ним. Отже, ми робимо знущання над моделлю. Це означає: Ми перевіряємо: index () метод, який повинен повернути список записів.
Тож ми знущаємося з модельного методу getAllActive () і додаємо до нього фіксовані дані (наприклад, два записи). Тепер ми перевіряємо дані, які контролер надсилає до перегляду, і порівнюємо, чи справді ми повернемо ці два записи назад.
function testProductIndexLoggedIn() {
$this->setLoggedIn();
$this->ProductsController->mock('ProductModel', 'index', function(return array(your records) ));
$result=$this->ProductsController->index();
$this->assertEquals(2, count($result['products']));
}
Цього достатньо. Ми намагаємось додати якомога менше функціональних можливостей до контролера, оскільки це робить тестування важким. Але звичайно, в ньому завжди є якийсь код. Наприклад, ми перевіряємо такі вимоги, як: Показуйте ці два записи, лише якщо ви ввійшли в систему.
Отже, контролеру потрібна нормальна макет і невеликий фрагмент даних з твердим кодом. Для системи входу можливо ще одна. У нашому тесті у нас є хелперний метод для цього: setLoggedIn (). Це спрощує тестування з логіном або без входу.
class ProductsController {
public function index() {
if($this->loggedIn()) {
$this->set('products', $this->ProductModel->getAllActive());
}
}
}
Перегляди
Тестування переглядів важко. Спочатку ми відокремлюємо логіку, яка повторюється. Ми поміщаємо це в Helpers і перевіряємо ці класи суворо. Ми очікуємо завжди однакового результату. Наприклад, createHtmlTableFromArray ().
Тоді у нас є певні конкретні точки зору проекту. Ми їх не тестуємо. Не дуже бажано тестувати їх. Ми зберігаємо їх для інтеграційних тестів. Оскільки ми вивели чимало коду для перегляду, ми маємо тут менший ризик.
Якщо ви почнете тестувати ті, хто вам, ймовірно, потрібно міняти свої тести щоразу, коли ви змінюєте фрагмент HTML, який не корисний для більшості проектів.
echo $this->tableHelper->generateHtmlTableFromArray($products);
Інтеграційне тестування
Залежно від вашої платформи, тут ви можете працювати з історіями користувачів тощо. Це може бути веб-базування, як Selenium або інші подібні рішення.
Зазвичай ми просто завантажуємо базу даних світильниками і стверджуємо, які дані мають бути доступними. Для повного інтеграційного тестування ми зазвичай використовуємо дуже глобальні вимоги. Отже: Установіть продукт на активний і перевірте, чи продукт стає доступним.
Ми не перевіряємо все знову, як, наприклад, чи потрібні потрібні поля. Ми перевіряємо більші вимоги тут. Оскільки ми не хочемо копіювати наші тести з контролера чи перегляду. Якщо щось дійсно є ключовою / основною частиною вашої програми або з міркувань безпеки (перевірити пароль НЕ доступний), ми додаємо їх, щоб переконатися, що це правильно.
Важко закодовані дані зберігаються у світильниках.
function testIntegrationProductIndexLoggedIn() {
$this->setLoggedIn();
$result=$this->request('products/index');
$expected='<table';
$this->assertContains($expected, $result);
// Some content from the fixture record
$expected='<td>Product 1 name</td>';
$this->assertContains($expected, $result);
}