TDD - Зовні в та проти


53

Яка різниця між створенням програми Outside In проти побудови її Inside Out за допомогою TDD?

Це книги, які я читав про тестування TDD та модулів:
Тестова розробка: за прикладом розробки
тестових програм: Практичний посібник: Практичний посібник
Рішення в реальному світі для розробки високоякісних рам PHP та програм для
тестових програм у Microsoft.
Шаблони тестів NET xUnit: Тестовий код Refactoring
Мистецтво тестування одиниць: із прикладами в .Net
Зростаюче об’єктно-орієнтоване програмне забезпечення, керуючись тестами ---> Це було дуже важко зрозуміти, оскільки JAVA не є моєю основною мовою :)

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

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

Однак я натрапив на абзац у тестах xUnit Test Patterns, який обговорював способи наближення людей до TDD. Є дві школи Зовнішньою та Внутрішньою .

На жаль, книга в цьому питанні не розглядає більше. Я хочу знати, яка головна відмінність між цими двома випадками.
Коли я повинен використовувати кожен з них?
Початківцю TDD, кого легше зрозуміти?
Які недоліки кожного методу?
Чи є матеріали, які конкретно обговорюють цю тему?


Два підходи описані на веб-сайті тестових шаблонів XUnit : xunitpatterns.com/Philosophy%20Of%20Test%20Automation.html . Дивно, що їх немає в книзі.
guillaume31

Відповіді:


45

Inside-Out та Outside-In є досить рідкісними термінами, частіше я чув / читав про класичну школу та лондонську школу .

  • Inside-Out (Класична школа, знизу вгору ): ви починаєте з рівня компонентів / класів (всередині) і додаєте тести до вимог. У міру розвитку коду (за рахунок рефакторингу) з'являються нові колабораціоністи, взаємодії та інші компоненти. TDD керує дизайном повністю.

  • Зовнішній Вхід (лондонська школа, зверху вниз або "макетний TDD", як це називав би Мартін Фаулер): ви знаєте про взаємодію та співпрацівників наперед (особливо тих, хто на верхньому рівні) і починаєте там (верхній рівень), глузуючи необхідні залежності. З кожним готовим компонентом ви переходите до раніше знущаються співпрацівників і знову починаєте з TDD там, створюючи реальні реалізації (які, хоч і використовувалися, раніше не були потрібні завдяки абстракціям ). Зауважте, що зовнішній підхід добре відповідає принципу YAGNI .

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

Що б ви не використовували, частіше за все це ситуативно.

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


2
Цікаво. Як ви дійшли висновку, що назовні в TDD є "макетний" TDD? Я дуже віддаю перевагу зовнішньому мисленню та дизайну і, таким чином, тестуючи (див. Softwareonastring.com/2015/01/10/… ), але стаття Фоулера твердо переносить мене з Фаулером у табір класицистів. Хоча мокіст завжди може використовувати підхід іззовні, ви не можете його перевернути і сказати, що дизайн та тестування ззовні - це макет TDD. Зовнішній вигляд може бути і дуже багато практикується і класицистичними TDD-ерами.
Мар'ян Венема

@jimmy_keen - Якщо ви в будь-який момент замінюєте макети в тестах вищого рівня на пізніші створені фактичні реалізації? Або ви залишаєте їх як глузуючі залежності, а потім здійснюєте весь виробничий код як інтеграційний тест?
thehowler

1
Я не погоджуюся, що Classic / Mockist та Inside-Out / Outside-In пов'язані між собою. Вони ортогональні. Ви можете використовувати Inside-Out / Outside-In з будь-яким.
Даніель Каплан

Погодьтесь із Даніелем. Ви уподібнюєте дві різні таксономії. Хоча зовнішній розвиток часто асоціюється з лондонською (макетською) школою, це не завжди так.
guillaume31

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

15

Короткий відповідь: Як завжди, це залежатиме від ваших переваг кодування та командного підходу.

Кодування всередині - це чудово, адже у вас завжди щось працює. Мінус полягає в тому, що це не обов'язково допомагає вам дістатися до кардинально іншого місця. Складніше намітити курс таким чином. Аналогічно, написання коду на вулиці має і мінус, не обов'язково мати перевагу швидкого ітеративного розвитку, і не обов'язково бачити всі можливості та закономірності, які можуть виникати в глибині структури коду.

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

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


8

До цього списку слід додати спритні принципи, шаблони та практики у C # . Я не знаю, чому він врешті торкнувся "в C #". Книги зовсім не є мовою, і єдина причина, що вона не отримала 5 зірок на амазонці - це люди, розчаровані в C # -ness його прикладів.

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

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

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


7

Як я бачу, концепція розвитку поза межами дійсно поширюється на 2 рівні. Джерард Мецарос коротко описує їх як "зовнішній дизайн " та " кодування зовні-зсередини-зсередини ".

  • Перший рівень - це організаційний та процесний рівень. Зовнішня конструкція мається на увазі на відміну від верху вниз (водоспад / тейлорист) і знизу вгору. При підході ззовні ми орієнтуємося на перспективу кінцевого користувача. Ми починаємо з тестів історії, ATDD або BDD тестів і переходимо "всередину", виводячи технічні тести та код. Тому зовнішній дизайн - це те, що ви робите в спритному контексті. Ден Норт чудово розмовляє про підходи BDD, зверху вниз, знизу вгору та назовні.

  • Другий рівень є технічним і пов'язаний з прикладними шарами. Зовнішнє кодування в основному означає починати від користувальницького інтерфейсу і переходити всередину до центрального рівня (як правило, бізнес / доменний шар). Він мається на увазі на відміну від кодування всередину, яке починається з центрального шару і останнього кодування зовнішніх шарів.

Таким чином, ви можете мати зовнішній дизайн з кодуванням ззовні або зсередини.

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

Іншими словами, TDD в стилі мокцизму або класицизму є IMO - ортогональним питанням кодування "зовні-в / зсередини". Ви можете ідеально використовувати макет-стиль разом із підходом зсередини. Причина цього полягає в тому, що макетно-класицистичний стиль - це залежність від коду, тоді як кодування ззовні / зсередини - з прикладними шарами .

Ще одна важлива річ у тому, що залежності існують не лише у різних шарах, вони також існують між об'єктами в одному шарі. Наприклад, ви можете почати з одного об’єкта у вашому центральному бізнес-шарі (підхід "всередину") та використовувати макети для ізоляції об'єкта від інших об'єктів бізнес-рівня, з якими він спілкується. Це трапляється багато з IoC - абстракції, від яких залежить ваш об'єкт, часто оголошуються в одному шарі, але конкретні реалізації знаходяться в іншому шарі.

Роберт "Дядько Боб" Мартін коротко згадує про кодування зсередини і про те, як це не обов'язково суперечить розв'язаній архітектурі у своєму дописі " Чиста архітектура ".

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