Якими повинні бути деталізовані тести на TDD?


18

Під час навчання TDD, заснованого на випадку медичного програмного забезпечення, ми реалізуємо наступну історію: "Коли користувач натискає кнопку" Зберегти ", система повинна додати пацієнта, додати пристрій і додати записи даних про пристрій".

Кінцева реалізація буде виглядати приблизно так:

if (_importDialog.Show() == ImportDialogResult.SaveButtonIsPressed)
{
   AddPatient();
   AddDevice();
   AddDeviceDataRecords();
}

У нас є два способи її реалізації:

  1. Три випробування, де кожен підтверджує один метод (AddPatient, AddDevice, AddDeviceDataRecords), називався
  2. Був викликаний один тест, який підтверджує всі три методи

У першому випадку, якщо трапиться щось не так, якщо умова застереження, всі три тести не зможуть. Але у другому випадку, якщо тест не вдасться, ми не впевнені, що саме не так. Який спосіб ви б віддали перевагу.

Відповіді:


8

Але у другому випадку, якщо тест не вдасться, ми не впевнені, що саме не так.

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

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

Зауважте також, що в будь-якому випадку вам також слід мати окремі одиничні тести, щоб переконатися, що кожен з окремих методів робить те, що належить зробити.


Чи не вважаєте ви розумним з часом поєднати ці три тести в один?
SiberianGuy

@Idsa, може бути розумним рішенням, хоча на практиці я рідко набридаю таким способом рефакторингу. Потім я знову працюю зі застарілим кодом, де пріоритети різні: ми зосереджуємось на збільшенні тестового покриття існуючого коду та збереженні зростаючої кількості одиничних тестів.
Péter Török

30

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

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

  • додає AddPatient пацієнта (тобто викликає відповідні функції бази даних)?
  • додає додаток AddDevice пристрій?
  • додає записи AddDeviceDataRecords?
  • виконує основну функцію, що не змінюється, у вашому прикладі виклику AddPatient, AddDevice та AddDeviceFunctions

Unittests призначені для розробників , тому вони отримують впевненість, що їх код технічно правильний

Тести приймання повинні перевірити комбіновану функціональність з точки зору користувача. Вони повинні моделюватися уздовж користувацьких історій та бути на максимально високому рівні. Отже, вам не доведеться перевіряти, чи викликаються функції, але чи досягнута користь, видима для користувача :

коли користувач вводить дані, натискає кнопку "ОК" і ...

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

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

Щоб відповісти на ваше запитання "що б ви віддали перевагу": яка для вас більша проблема зараз, помилки та регресія (=> більше одиниць тестів) або розуміння та формалізація великої картини (=> більше тестів на прийняття)


13

У нас є два способи її реалізації:

Це помилково.

Три випробування, де кожен підтверджує один метод (AddPatient, AddDevice, AddDeviceDataRecords), називався

Ви повинні зробити це, щоб переконатися, що воно працює.

Був викликаний один тест, який підтверджує всі три методи

Ви також повинні зробити це, щоб переконатися, що API працює.

Клас - як одиниця - повинен бути повністю перевірений. Кожен метод.

Ви можете почати з тесту, який охоплює всі три методи, але це не дуже розкаже.

якщо тест не вдасться, ми не впевнені, що саме не так.

Правильно. Ось чому ви протестуєте всі методи.

Ви повинні перевірити загальнодоступний інтерфейс. Оскільки в цьому класі є три додаткові речі (навіть якщо вони поєднані одним методом через історію користувача), ви повинні перевірити всі чотири речі. Три низькорівневі та один комплект.


2

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

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

  1. VerifyPatientQualification
  2. EnsureDoctorExistence
  3. ПеревіркаІсторія страхування
  4. Переконайтесь, що порожні

Ми також можемо написати тест одиниці для кожної з цих функцій.


2

Одне просте правило, яке я дотримувався, - це називати тест, щоб він точно описував тест. Якщо назва тесту стає занадто складною, це знак того, що тест, можливо, робить занадто багато. Так, наприклад, іменування тесту для виконання того, що ви пропонуєте у варіанті 2, може виглядати як PatientIsAddedDeviceIsAddedAndDeviceDataRecordsWhenSaved, що набагато складніше, ніж три окремих тесту PatientIsAddedWhenSaved, DeviceIsAddedWhenSaved, DataRecordsWhenSaved. Я також вважаю, що уроки, які можна отримати з BDD, є досить цікавими, коли кожен тест є дійсно репрезентативною єдиною вимогою, яку можна було б описати природною мовою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.