TDD Mock підтвердження дзвінків - це анти-шаблон?


11

Я займаюся TDD вже рік, відчуваю себе досить добре, люблю свої тестові набори та все. Однак я помітив, що останнім часом я багато робив знущання з перевірки дзвінків. Наприклад, у мене буде служба, в яку буде введено репозиторій - у своєму тесті на одиницю я передав би макет із сховища і переконався, що він викликався в рамках методу, який я тестую. Потім я перевірив би правильність результатів (в іншому тесті). Це, безумовно, "відчуває себе неправильним, оскільки мої одиничні тести тепер дуже поєднані з деталями реалізації. Я чув, що вам слід перевірити "поведінку", однак у багатьох ситуаціях це ... Емм - не можливо? Якщо у вас єvoidнаприклад, ви зазвичай тестуєте побічні ефекти. Я маю на увазі, що легко йти вперед і показати кілька простих код-кодів, де це можна продемонструвати, але в IMHO це не дуже добре відображається в реальних програмах, про які ми пишемо. Це те, що я роблю неправильно? Чи такий тип тестування є антидіаграмою? Я буду вдячний за вашу думку з цього приводу, я все ще трохи новачок, коли мова йде про TDD.


2
Коротка відповідь: так. На цю тему вже є дещо цікаві запитання. Ваші одиничні тести не повинні бути крихкими і сильно залежати від вашої реалізації. Ось чому випробування вищого рівня призначені для (інтеграції тощо). Тут: programmers.stackexchange.com/questions/198453 / ...
Kemoda

@Kemoda Буду вдячний, якщо ви можете зв’язати мене з дискусією чи іншим матеріалом з цього приводу, я дуже хотів би вдосконалити свої методи.
Димитър Димитров

1
у вас є це, наприклад , programmers.stackexchange.com/questions/198453 / ... я буду шукати інші посилання пізніше
Kemoda

Відповіді:


8

Ну, ви повинні намагатися перевірити входи та виходи. Ви повинні перевіряти зовнішню видимість поведінки. "Обіцянки" або "контракт", які дає ваш клас.

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

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


2

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

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

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


"Отже, але що робити, якщо використання реальних реалізацій у тесті дорого (наприклад, тому що для них потрібні ресурси, які складні для налаштування)? Мені в цьому випадку потрібно використовувати макети, правда?"

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

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


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

2

Мої думки стосуються: «сукупних послуг».

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

Є три, неексклюзивні, інші способи цього:

  1. Подовжте тести, які ви маєте для кожної окремої служби, щоб вона перевіряла поведінку вищого рівня. Наприклад, якщо ви потрапляєте на базу даних пам'яті у вашому блоці тестів служби, підніміть її на рівень, щоб ви протестували послугу на фактичний db. Службовий рівень знаходиться вище дерева абстракції, як і ваш тест.

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

  3. Використовуйте якусь рефлексію чи динамічну мову, щоб зробити те саме. Наприклад, у Java може бути можливий використання гровій інтерфейсу, який передає дзвінок безпосередньо.

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

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