Що таке глузування? .
Що таке глузування? .
Відповіді:
Пролог: Якщо ви подивитесь на макет іменника у словнику, ви побачите, що одне з означень цього слова є чимось зробленим як наслідування .
Знущання в основному застосовуються при тестуванні одиниць. Об'єкт, що тестується, може мати залежність від інших (складних) об'єктів. Для ізоляції поведінки об'єкта ви хочете замінити інші об'єкти макетами, що імітують поведінку реальних об'єктів. Це корисно, якщо реальні об’єкти не доцільно включати в одиничний тест.
Коротше кажучи, глузування - це створення об’єктів, що імітують поведінку реальних об'єктів.
Часом ви можете розрізняти глузування на відміну від заглушки . З цього приводу може виникнути незгода, але моє визначення заглушки - це «мінімально» змодельований об’єкт. Заглушка реалізує достатньо поведінки, щоб дозволити досліджуваному об'єкту виконати тест.
Макет - це як заглушка, але тест також перевірить, що тестуваний об'єкт викликає макет, як очікувалося. Частина тесту - це перевірка правильності використання макета.
Щоб навести приклад: Ви можете заглушити базу даних, застосувавши просту структуру пам'яті для зберігання записів. Об'єкт, що перевіряється, може потім читати і записувати записи в заглушку бази даних, щоб дозволити йому виконати тест. Це може перевірити деяку поведінку об'єкта, не пов’язаного з базою даних, і заглушка бази даних буде включена лише для того, щоб тест запустився.
Якщо ви хочете перевірити, чи перевіряється об'єкт записує певні дані в базу даних, вам доведеться знущатися над базою даних. Потім ваш тест включав би твердження про те, що було написано в макет бази даних.
Інші відповіді пояснюють, що таке глузування. Дозвольте мені ознайомитися з вами на різних прикладах . І повірте, насправді це набагато простіше, ніж ти думаєш.
tl; dr Це екземпляр оригінального класу. У нього вводяться інші дані, щоб уникнути тестування деталей, що вводяться, і зосередитись лише на тестуванні деталей реалізації класу / функцій.
Простий приклад:
class Foo {
func add (num1: Int, num2: Int) -> Int { // Line A
return num1 + num2 // Line B
}
}
let unit = Foo() // unit under test
assertEqual(unit.add(1,5),6)
Як бачите, я не тестую LineA, тобто я не перевіряю вхідні параметри. Я не перевіряю, чи є num1, num2 цілим числом. Я не маю жодних тверджень проти цього.
Я лише перевіряю, чи дано LineB (моя реалізація ) глузливі значення 1
і 5
чи працює так, як я очікував.
Очевидно, що в реальному слові це може стати набагато складнішим. Параметри можуть бути спеціальним об'єктом, таким як Person, Address, або деталі реалізації можуть бути більше ніж одиничні +
. Але логіка тестування була б однаковою.
Припустимо, ви будуєте машину, яка визначає тип та фірмову назву електронних пристроїв для безпеки аеропорту. Машина робить це, обробляючи побачене своєю камерою.
Тепер ваш менеджер заходить у двері і просить вас перевірити його.
Тоді ви, як розробник, можете або принести 1000 реальних об'єктів, як-от MacBook Pro, Google Nexus, банан, iPad і т.д. перед ним і протестувати і перевірити, чи все працює.
Але ви також можете використовувати знущаються предмети, як ідентичний MacBook Pro (без реальних внутрішніх частин) або пластиковий банан перед ним. Ви можете врятувати себе від інвестицій у 1000 справжніх ноутбуків та гниючих бананів.
Справа в тому, що ви не намагаєтеся перевірити, чи банан підроблений чи ні. Ні тестування, чи ноутбук підроблений чи ні. Все , що ви робите, тестування , якщо ваша машина , коли він бачить банан було б сказати , not an electronic device
і для MacBook Pro було б сказати: Laptop, Apple
. Для машини результат її виявлення повинен бути однаковим для підробленої / глубокої електроніки та реальної електроніки
Логіка, згадана вище, застосовується і для тестування одиниць фактичного коду. Тобто функція повинна працювати однаково з реальними значеннями, які ви отримуєте від реального введення (та взаємодій) або знущаютьсязначення, які ви вводите під час одиничного тестування. І так само, як ви врятуєте себе від використання справжнього банана чи MacBook, за допомогою тестування одиниць (і глузування), ви заощадите себе від необхідності робити щось, що змушує ваш сервер повертати код статусу 500, 403, 200 тощо (примусовий ваш сервер запускає 500 лише тоді, коли сервер не працює, тоді як 200 - коли сервер працює. Важко запустити 100 тестів, орієнтованих на мережу, якщо вам доведеться постійно чекати 10 секунд між переключенням сервера вгору і вниз). Тож замість цього ви вводите / знущаєтесь з відповіді з кодом статусу 500, 200, 403 тощо та випробовуєте свій пристрій / функцію за допомогою введеного / глубокого значення.
Скажімо, ви пишете додаток для iOS та маєте мережеві дзвінки. Ваше завдання - перевірити свою програму. Щоб перевірити / визначити, чи працюють мережеві дзвінки, як очікувалося, НЕ ВАША ВІДПОВІДАЛЬНІСТЬ. Це ще одна відповідальність (команда сервера) перевірити це. Ви повинні усунути цю (мережеву) залежність і все ж продовжувати тестувати весь код, який працює навколо нього.
Мережевий дзвінок може повертати різні коди стану 404, 500, 200, 303 тощо з відповіддю JSON.
Ваш додаток, мабуть, працює для всіх (у разі помилок, ваш додаток повинен видалити очікувану помилку). Що ви робите з глузуванням, ви створюєте "уявні - подібні до реальних" мережеві відповіді (наприклад, код 200 з файлом JSON) і перевіряєте свій код, не "здійснюючи реальний дзвінок у мережі та не чекаючи відповіді вашої мережі". Ви вручну жорсткий код / повертаєте мережеву відповідь на ВСІ види мережевих відповідей і бачите, чи працює ваш додаток, як ви очікували. (ви ніколи не припускаєте / не тестуєте 200 з неправильними даними, тому що це не ваша відповідальність. Ваша відповідальність полягає в тому, щоб перевірити ваш додаток правильним 200, або у випадку 400, 500 ви перевірите, чи ваш додаток видає правильну помилку)
Це створення уявного — схожого на реальне - відоме як глузування.
Для цього ви не можете використовувати свій оригінальний код (у вихідному коді немає попередньо вставлених відповідей, правда?). Ви повинні додати щось до нього, ввести / вставити ті фіктивні дані, які зазвичай не потрібні (або частина вашого класу).
Таким чином, ви створюєте екземпляр оригінального класу і додаєте що завгодно (тут мережевий HTTPResponse, дані АБО у разі відмови, ви передаєте потрібну errorString, HTTPResponse), яка вам потрібна, а потім перевіряєте знущається клас.
Коротше кажучи, глузування - це спростити та обмежити тестування, а також змусити вас годувати те, від чого залежить клас. У цьому прикладі ви уникаєте тестування самих мережевих дзвінків і замість цього перевіряєте, чи працює ваш додаток так, як ви очікуєте, з ін'єкційними виходами / відповідями - глузуючи з класів
Потрібно сказати, що ви перевіряєте кожну мережеву відповідь окремо.
Тепер питання, яке я завжди мав на увазі, було: договори / кінцеві пункти і в основному відповідь JSON моїх API постійно оновлюються. Як я можу написати одиничні тести, які враховують це?
Щоб детальніше зупинитися на цьому: скажімо, модель потребує імені ключа / поля username
. Ви перевіряєте це, і ваш тест проходить. Через 2 тижні бекенд змінює ім'я ключа на id
. Ваші тести все ще проходять. правильно? чи ні?
Це відповідальність розробника бекенда за оновлення макетів. Чи повинно бути частиною нашої угоди про те, що вони надають оновлені макети?
Відповідь на вищезазначене питання полягає в тому, що: тестові одиниці + ваш процес розробки як розробника на стороні клієнта повинен / захопить застарілий насмішок. Якщо ви запитаєте мене як? добре відповідь:
Наше фактичне додаток не зможе (або не вийде з ладу, але не матиме бажаної поведінки) без використання оновлених API ... отже, якщо це не вдасться ... ми внесемо зміни в наш код розробки. Що знову ж таки призводить до того, що наші тести провалюються .... що нам доведеться виправити. (Насправді, якщо ми хочемо виконати процес TDD правильно, ми не повинні писати жодного коду про поле, якщо ми не пишемо тест для нього ... і побачимо, що він не працює, а потім перейти і написати фактичний код розробки для нього.)
Це все означає, що бекенду не потрібно говорити: «Ей, ми оновили макети» ... це врешті-решт відбувається через розробку / налагодження вашого коду. ّ Тому що це все є частиною процесу розробки! Хоча якщо бекенд надає вам насмішку у відповідь, тоді це простіше.
Моя суть у цьому полягає в тому, що (якщо ви не в змозі автоматизувати отримання оновлених насмішкованих відповідей API), потрібна деяка взаємодія між людьми, тобто ручне оновлення JSON та проведення коротких зустрічей, щоб переконатися, що їх значення актуальні, стануть частиною вашого процесу
Цей розділ був написаний завдяки слабкій дискусії в нашій групі зустрічей CocoaHead
Лише для розробників iOS:
Дуже хороший приклад глузування - це практичні протокольні розмови Наташі Муращев . Просто перейдіть до хвилини 18:30, хоча слайди можуть не синхронізуватися з фактичним відео video
Мені дуже подобається ця частина із стенограми:
Оскільки це тестування ... ми хочемо переконатися, що
get
функція зGettable
виклику викликається, тому що вона може повернутися і функція теоретично може призначити масив продуктів харчування з будь-якого місця . Нам потрібно переконатися, що воно називається;
В Інтернеті є багато відповідей на ТА та хороших дописів про глузування. Одне з місць, яке ви можете почати шукати - це повідомлення Мартіна Фаулера Mocks Ant't Stubs, де він обговорює багато ідей знущань.
В одному абзаці - глузування - це одна особлива методика, яка дозволяє перевірити одиницю коду, не залежачи від залежностей. Загалом, те, що відрізняє глузування від інших методів, полягає в тому, що макетні об'єкти, які використовуються для заміни кодових залежностей, дозволять встановити очікування - макетний об’єкт буде знати, як це означає, щоб викликати ваш код і як відповісти.
У вашому оригінальному запитанні згадувався TypeMock, тому я залишив свою відповідь на це нижче:
TypeMock - це назва комерційного глузування .
Він пропонує всі функції вільних глузливих фреймворків, як RhinoMocks і Moq, а також деякі більш потужні варіанти.
Незалежно від того, чи потрібен вам TypeMock, дуже дискусійно - ви можете робити більшість глузливих, які ви коли-небудь хотіли, за допомогою безкоштовних насмішкувальних бібліотек, і багато хто стверджує, що здібності, пропоновані TypeMock, часто відводять вас від добре закріпленого дизайну.
Як сказано в іншій відповіді, "TypeMocking" насправді не є визначеним поняттям, але його можна вважати типом глузування, який пропонує TypeMock, використовуючи CLR-профілер для перехоплення .Net дзвінків під час виконання, надаючи набагато більшу можливість підробляти об'єкти (не вимоги наприклад, потрібні інтерфейси або віртуальні методи).
Макет - це метод / об’єкт, який моделює поведінку реального методу / об’єкта контрольованими способами. Об'єкти макету використовуються при тестуванні одиниць.
Часто метод під тестом викликає інші зовнішні служби або методи, що знаходяться в ньому. Вони називаються залежностями. Після того, як знущалися, залежності поводяться так, як ми їх визначили.
Оскільки залежності контролюються знущами, ми можемо легко перевірити поведінку методу, який ми закодували. Це модульне тестування.
Мета глузування типів - розрізати залежності, щоб виділити тест на конкретну одиницю. Заглушки - це прості сурогати, тоді як макети - це сурогати, які можуть перевірити використання. Знущальна рамка - це інструмент, який допоможе вам генерувати заглушки та макети.
EDIT : Оскільки в оригінальній редакції згадується "тип глузування", у мене склалося враження, що це стосується TypeMock. На мій досвід, загальний термін - це просто "глузуючий". Будь ласка, нехтуйте наведеною нижче інформацією спеціально щодо TypeMock.
TypeMock Isolator відрізняється від більшості інших глузливих фреймворків тим, що він працює на моєму модифікуванні IL під час польоту. Це дозволяє йому глумати типи та випадки, з яких більшість інших фреймворків не можуть знущатися. Щоб знущатися над цими типами / екземплярами з іншими рамками, ви повинні надати власні абстракції та знущатися над ними.
TypeMock пропонує велику гнучкість за рахунок чистого середовища виконання. Як побічний ефект від того, як TypeMock досягає своїх результатів, іноді ви отримаєте дуже дивні результати при використанні TypeMock.
Я думаю, що використання глузуючої рамки ізолятора TypeMock було б TypeMocking.
Це інструмент, який генерує макети для використання в одиничних тестах, без необхідності писати свій код з урахуванням IoC.
Якщо ваш макет передбачає мережевий запит, інша альтернатива - це мати справжній тестовий сервер, на який потрібно звернутись. Ви можете використовувати цю послугу для створення запиту та відповіді для вашого тестування. http://testerurl.com/