Я перевірив свій клас, тепер як почати тест на інтеграцію?


19

Я написав клас, який керує одержувачами у списку MailChimp, який називається MailChimpRecipient. Він використовує клас MCAPI, який є стороннім обгорткою API.

http://apidocs.mailchimp.com/api/1.3/ http://apidocs.mailchimp.com/api/downloads/

Я передаю об’єкт MCAPI в конструктор об'єкта MailChimpRecipient, тому я написав тестові одиниці за допомогою PHPUnit, які перевіряють всю логіку в моєму власному класі (я не тестую клас MCAPI). У мене 100% покриття коду і всі тести проходять. Це робиться глузуванням та заглушкою об'єкта MCAPI.

Наступним моїм кроком було написання тесту на інтеграцію, також за допомогою PHPUnit, де я побудував би кріплення MailChimpRecipient за допомогою реального об’єкта MCAPI, створеного для використання реального списку MailChimp.

Я написав те, що, на мою думку, є інтеграційним тестом, який, в основному, виконує тести, пов'язані з публічним інтерфейсом об'єкта, наприклад:

public function testAddedRecipientCanBeFound()
{
    $emailAddress = 'fred@fredsdomain.com';
    $forename = 'Fred';
    $surname = 'Smith';

    // First, delete the email address if it is already on the list
    $oldRecipient = $this->createRecipient();
    if($oldRecipient->find($emailAddress))
    {
        $oldRecipient->delete();
    }
    unset($oldRecipient);

    // Add the recipient using the test data
    $newRecipient = $this->createRecipient();
    $newRecipient->setForename($forename);
    $newRecipient->setSurname($surname);
    $newRecipient->setEmailAddress($emailAddress);
    $newRecipient->add();
    unset($newRecipient);

    // Assert that the recipient can be found using the same email address
    $this->assertTrue($this->_recipient->find($emailAddress));
}

Тест "інтеграції" не перевіряє жоден внутрішній клас класу - він просто переконує, що, даючи реальний об'єкт MCAPI, він поводиться так, як рекламується.

Це правильно? Це найкращий спосіб провести тест на інтергацію? Зрештою, внутрішні тести перевірені за допомогою одиничного тесту. Я маю рацію, думаючи, що тест на інтеграцію існує, щоб перевірити, чи справді він працює, відповідно до способів рекламування його поведінки?

Щоб зробити крок далі, клас MailChimpRecipient реалізує інтерфейс, який також буде реалізований іншими класами. Ідея полягає у використанні фабрики для передачі різних типів об’єктів одержувачів списку розсилки до мого коду, які всі роблять те саме, хоча і з використанням різних постачальників списків розсилки. Оскільки мої інтеграційні тести перевіряють цей інтерфейс, як щодо його використання для всіх класів, які реалізують інтерфейс? Тоді, в майбутньому, якщо я сконструюю новий клас, який буде використовуватися безперервно, я можу запустити той же тест інтеграції перед тим, як вставити його в проект.

Це звучить розумно? Одиничні тести перевіряють внутрішні об'єкти, тести на інтеграцію впевнені, що він поводиться так, як рекламується?


4
Я думаю, у вас занадто багато логіки у вашому тесті. Ви запускаєте багато коду, поки не зробите твердження. Ви, мабуть, спершу хочете перевірити видалення одержувача. Але це не відповідає на ваше запитання, а лише коментар.
хакре

1
Добре, ви повинні скористатися setUpфункцією, щоб встановити підстави для запуску ваших тестів. Якщо введення не визначено, добре ви не можете перевірити. Вхід повинен бути точним, суворим і завжди однаковим. Якщо попередня умова тесту не виконується, замість цього пропустіть тест. Потім проаналізуйте, чому це пропускає, і якщо вам потрібно додати додаткові тести та / або setUpце зроблено не правильно.
хакре

1
Крім того, не встановлюйте значення тестування жорсткого коду всередині власного тесту, але зробіть ці учасники класу, щоб вони могли ділитися між тестами (і змінюватись у центральному місці) або використовувати DataProvider(це функція, що пропонує введення як параметри тесту).
хакре

1
Введіть значення того, на що працює ваша тестова функція. Під час тестування додавання одержувача, і ви хочете переконатися, що він уже не існує, вам слід принаймні стверджувати про видалення, якщо воно починається. Інакше попередня умова вашого тесту не гарантована для перевірки.
хакре

1
+1 за гарне запитання, але також проголосував за перехід до програмістів. Здається, саме тут належать питання щодо стратегій тестування
GordonM

Відповіді:


17

Під час тестування коду слід звернути увагу на три області:

  • Тестування сценарію
  • Функціональне тестування
  • Блок тестування

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

За допомогою одиничного тестування ви висміюєте все, що використовує тестований клас, і ви тестуєте його в чистому ізоляції (саме тому важливо переконатися, що всередині вашого класу ви отримаєте всі залежності за допомогою ін'єкції, щоб їх можна було замінити під тестом).

За допомогою тестування одиниць ви перевіряєте всі можливості, тому не тільки «щасливий шлях», але і всі умови помилок.

Якщо ви абсолютно впевнені, що всі ваші підрозділи працюють ізольовано, ви пишете пару тестів (функціональних тестів), щоб переконатися, що підрозділи також працюють у поєднанні. Потім ви пишете тест сценарію, який тестує проводку між усіма функціональними модулями.

Наприклад, припустимо, ви тестуєте автомобіль.

Ви могли зібрати весь автомобіль і як водій перевірити всі можливі умови, але це було б дійсно важко зробити.

Замість цього ви протестуєте невелику частину двигуна з усіма можливостями (тестовий блок)

Потім ви протестуєте весь двигун (окремо від машини), що було б функціональним випробуванням.

Як останнє випробування, ви кладете свій ключ, запускаєте машину і їдете до стоянки. Якщо це працює, то ви знаєте, що всі деталі (акумулятор, паливо, двигун, ..) з'єднані, і оскільки ви перевірили їх ізольовано, ви можете бути впевнені, що вся машина працює правильно.

Тож у вашому випадку ви перевірили всі умови помилок та щасливий шлях у вашому тесті на одиницю, і знаєте, що вам потрібно лише провести ціле тестування з «реальними компонентами», щоб перевірити правильність проводки.

Ще кілька моментів,

  • Уникайте умовної логіки у вашому тесті на одиницю. Якщо вам доведеться прибирати, ваше використання якогось глобального стану та тести можуть раптово впливати один на одного.
  • Не вказуйте жодних даних, які не стосуються тесту. Якби я змінив прізвище чи прізвище, чи не вдалося б випробувати? Мабуть, не тому, що важлива саме адреса електронної пошти, а тому, що ви явно згадуєте її у своєму тесті, я не можу бути впевнений. Спробуйте ознайомитись із шаблоном Builder для складання своїх тестових даних і уточнити, що саме важливо.

Дякую, що підтверджує багато того, що я думав. Просто для уточнення - це НЕ одиничний тест. Я вже написав одиничний тест, який випробовує об'єкт у повній ізоляції та має 100% кодове покриття об'єкта. Це мало бути тестом інтеграції, щоб переконатися, що воно працює, коли я ввожу в нього реальний об'єкт MCAPI. Мені просто потрібно видалити будь-яких одержувачів, які додаються до списку - це все очищення, і воно реалізовано для того, щоб жоден з тестів не впливав на інший. Що б ви запропонували замість цього?

1
Ага! Я зрозумів, що ви вже зробили одиничні тести. Чи слід об’єкт MCAPI відслідковувати одержувачів і чи потрібно проводити очищення? Якщо це проблема "третіх сторін", ви нічого не можете зробити в тесті інтеграції. Якщо ви з іншого боку стежите за списком, вам слід переконатися, що ви уникаєте глобальних даних (і одиночних клавіш), щоб переконатися, що тести не впливають один на одного. У ідеальному світі, прибирання речей, коли тест починається / закінчується, вказує на ваду дизайну, але в реальному світі ви не завжди можете цього уникнути.
Вутер де Корт

1
Я додам, що сценарій тестування, ймовірно, насправді не те, що PHPUnit підходить. Ю, можливо, захоче переглянути якийсь інструмент, який можна запустити у веб-переглядачі, наприклад, Selenium, або на інструмент, який може імітувати браузер, наприклад, jMeter.
GordonM

Дякую, хлопці! Там, звичайно, багато чому навчитися, коли справа доходить до написання хорошого тестового коду, чи не існує. Я замовив собі копію цієї книги: amazon.co.uk/… . Сподіваємось, те, що ви всі сказали, матиме трохи більше сенсу після того, як я прочитав це. @Wouter, я просто видаляю одержувача, оскільки тест призвів до того, що в список буде додано електронну адресу. Я видаляю це так, що цей тест не впливає на список.

1
@LewisBassett Я не розробник Php, але тести xUnit Test ( amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054 ), безумовно, добре прочитаний. Також статті на misko.hevery.com/code-reviewers-guide є справді цікавими.
Wouter de Kort
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.