Перспектива:
Тож давайте зробимо крок назад і запитаємо, в чому TDD намагається нам допомогти. TDD намагається допомогти нам визначити, чи правильний наш код чи ні. І правильно, я маю на увазі "чи відповідає код вимогам бізнесу?" Точка продажу полягає в тому, що ми знаємо, що в майбутньому потрібні будуть зміни, і ми хочемо переконатися, що наш код залишається правильним після внесення цих змін.
Я піднімаю цю перспективу, тому що думаю, що легко загубитися в деталях і втратити з поля зору те, що ми намагаємось досягти.
Принципи - SAP:
Хоча я не є експертом в області TDD, я думаю, що ви пропускаєте частину того, що намагається навчати Принцип єдиного твердження (SAP). SAP можна відновлювати як "перевірити одну за одною". Але TOTAT не скочує язик так легко, як SAP.
Тестування однієї речі одночасно означає, що ви зосереджуєтесь на одному випадку; одна стежка; одна гранична умова; один випадок помилки; один незалежно один тест. І ідеєю, що рухається за цим, ви повинні знати, що вийшло з ладу тестового випадку, щоб ви могли швидше вирішити проблему. Якщо ви перевірите кілька умов (тобто більше, ніж одне) в рамках тесту, і тест не вдасться, то у вас є набагато більше роботи. Спочатку ви повинні визначити, який із кількох випадків не вдався, а потім з'ясувати, чому цей випадок не вдався.
Якщо ви перевіряєте одну за одною, обсяг пошуку значно менший, а дефект виявляється швидше. Майте на увазі, що "тестування однієї речі за часом" не обов'язково виключає перегляд декількох результатів процесу одночасно. Наприклад, під час тестування "відомого хорошого шляху" я можу розраховувати побачити конкретне, отримане значення foo
, а також інше значення в, bar
і я можу перевірити це foo != bar
як частину свого тесту. Головне - логічно групувати вихідні перевірки на основі тестуваного випадку.
Принципи - PMP:
Так само, я думаю, ви трохи не вистачаєте про те, чого має навчити нас Принцип приватних методів (PMP). PMP закликає нас ставитися до системи як до чорної скриньки. Для заданого входу слід отримати заданий вихід. Вам байдуже, як чорний ящик генерує вихід. Ви дбаєте лише про те, щоб ваші результати вирівнювалися з вашими вхідними даними.
PMP - це справді хороша перспектива для перегляду аспектів API вашого коду. Це також може допомогти вам розширити те, що вам доведеться перевірити. Визначте точки інтерфейсу та переконайтесь, що вони відповідають умовам своїх договорів. Вам не потрібно дбати про те, як задіювані інтерфейси (так само приватні) виконують свою роботу. Вам просто потрібно переконатися, що вони зробили те, що мали зробити.
Застосований TDD ( для вас )
Тож ваша ситуація створює трохи зморшок поза звичайним застосуванням. Методи вашої програми є надзвичайними, тому їх вихід залежить не тільки від введення даних, але й того, що було зроблено раніше. Я впевнений, що я повинен <insert some lecture>
тут говорити про те, що держава жахлива і бла-бла, але це насправді не допомагає вирішити вашу проблему.
Я припускаю, що у вас є якась таблиця діаграм стану, яка показує різні потенційні стани і що потрібно зробити, щоб викликати перехід. Якщо ви цього не зробите, вам це знадобиться, оскільки це допоможе висловити бізнес-вимоги до цієї системи.
Тести: По-перше, ви збираєтеся закінчити набір тестів, які вводять зміни в стан. В ідеалі у вас будуть тести, які здійснюють повний спектр змін стану, які можуть статися, але я можу побачити кілька сценаріїв, де вам, можливо, не потрібно буде пройти цю повну міру.
Далі вам потрібно створити тести для перевірки обробки даних. Деякі з цих тестів стану будуть повторно використані, коли ви створюєте тести обробки даних. Наприклад, припустимо, у вас є метод, Foo()
який має різні результати, засновані на а Init
та State1
станах. Ви хочете використовувати свій ChangeFooToState1
тест як етап налаштування, щоб перевірити вихід, коли " Foo()
знаходиться State1
".
За цим підходом є деякі наслідки, які я хочу зазначити. Спойлер, тут я розлючую пуристів
По-перше, ви повинні прийняти, що ви використовуєте щось як тест в одній ситуації та налаштування в іншій ситуації. З одного боку, це здається прямим порушенням SAP. Але якщо ви логічно уявляєте ChangeFooToState1
, що маєте дві цілі, то ви все ще зустрічаєтеся з духом того, чого навчає нас SAP. Коли вам потрібно переконатися в Foo()
змінах стану, ви використовуєте ChangeFooToState1
як тест. І коли потрібно перевірити Foo()
висновок " ", коли State1
", то ви використовуєте його ChangeFooToState1
як налаштування.
Другий пункт - це те, що з практичної точки зору, ви не збираєтеся хотіти повністю рандомізованого тестування одиниць для вашої системи. Вам слід запустити всі тести на зміну стану перед запуском тестів перевірки виводу. SAP - це своєрідний керівний принцип, що стоїть за цим замовленням. Щоб сказати, що має бути очевидним - ви не можете використовувати щось як налаштування, якщо воно не вдасться до тесту.
Поєднання разом:
Використовуючи діаграму стану, ви генеруєте тести для покриття переходів. Знову ж, використовуючи свою діаграму, ви генеруєте тести для покриття всіх випадків обробки даних введення / виводу, керованих станом.
Якщо ви дотримуєтесь цього підходу, bloated, complicated, long, and difficult to write
тести повинні бути трохи простішими в управлінні. Загалом вони повинні бути меншими, і вони повинні бути більш короткими (тобто менш складними). Слід зазначити, що тести також є більш відокремленими або модульними.
Зараз я не кажу, що процес буде повністю безболісний, оскільки написання хороших тестів вимагає певних зусиль. А деякі з них все ще будуть складними, оскільки ви відображаєте другий параметр (стан) протягом досить багатьох ваших випадків. І як осторонь, має бути трохи очевидніше, чому система без громадянства простіше створити тести. Але якщо ви адаптуєте цей підхід до своєї програми, ви повинні виявити, що ви можете довести, що ваша програма працює правильно.