За да тествате система, изолирайте страничните ефекти

Премахването на странични ефекти е един от най-добрите начини за изграждане на тестван код

Снимката на боксов мач между двама мъже бойци. Лицата им са извън рамката. Боецът вляво е изпратил лявата кука на боеца в дясната. Боецът вдясно е облечен в червено късо с малък символ на Съветския съюз.

Nock е известна библиотека, написана на JavaScript, полезна за заяждане на мрежови заявки. Той връща статичен отговор за тестовете, така че те да могат да се изпълняват, дори ако HTTP сървърът не е наличен.

Въпреки това, това е и миризма.

Резултатното свързване между източника на данни и изпитваната система е цена, която може да повлияе на рефакторинг на кода и поддръжка.

Ето защо.

Да приемем, че има сървър, който връща списък с публикации и функция, която консумира отговора от този сървър, за да създаде списък със заглавия на публикациите. Тестът за функцията използва Nock за прекъсване на отговора от сървъра:

Диаграма, която показва блок вляво с надпис

Кодът има прилично покритие. Има обаче някои проблеми с него.

Ако направите промени в типа съдържание на отговора, трябва да промените тестовете, дори ако поведението на кода остава същото:

Същото важи, ако направите промени в URL адреса, заглавките или параметрите, които Нок затруднява. Трябва да промените тестовете, дори ако поведението на системата остава същото:

Функцията "създаване на списък с публикации" е системата под тест (SUT). Данните от HTTP обаждането са източникът на данни.

Можете да проектирате кода така, че източникът на данни да има общ интерфейс, който да се свързва към SUT. В този случай можете да упражнявате логиката, без да е необходимо прекалено много настройка.

Диаграма, която показва блок вляво с надпис „списък на заглавията на публикациите.“ Едната стрелка сочи към блок с надпис „Източник на данни в паметта“. Другата стрелка сочи към блок с надпис „HTTP Server Data Източник

За тестова среда можете да поставите „Източник на данни в паметта“. За производството можете да използвате „Източник на данни на HTTP сървъра“.

„Общият интерфейс“ в предишната JSFiddle е методът „намери заглавие на публикациите“. Независимо от това как изграждате интерфейса, имате контрол върху всички обаждащи се. Следователно промените са директни. Мартин Фаулър нарича „непубликуван интерфейс“.

От друга страна, ако сървърът наруши договора на своя Публикуван интерфейс, да кажем, че класният атрибут се променя от пост-заглавие в заглавие на статията, трябва само да промените реализацията на източника на данни. Не е нужно да правите промени навсякъде.

Нещото, което е важно да се тества и да има ранна обратна връзка, е на тестове срещу поведението, а не на данните. Ето защо е изключително важно да се проектира кодът, за да се намали количеството усилия, необходими за промени в логиката. В този случай логиката е преобразуването на входа от Източника на данни в списъка с непореден HTML код.

С новия дизайн сте отделили източника на данни от изпитваната система. Следователно, можете да премахнете Nock.

Новият дизайн също намалява работата, необходима за добавяне на ново правило в системата без копиране / поставяне:

И все пак „HTTP Server Source Source“ има някаква непроверена логика в частната функция „query posts title from html“.

За да проверите това, можете да повторите същия модел. Избутайте страничните ефекти и направете механизма „get request“ да се включи в „HTTP Server Source“. По този начин все още можете да тествате кода, без да имате нужда от Nock:

Тъй като вече имате тестове, за да потвърдите, че „списъкът на заглавията на публикациите“ работи с „Източник на данни в паметта“, можете да решите да тествате източника на данни изолирано, за да сте сигурни, че той връща правилния резултат:

Изтласкахте напълно страничния ефект от логиката. В този случай истинската функция „заявка за заявка“ е страничният ефект. Сега можете да използвате Nock, за да покриете това.

Въпреки това, като се има предвид, че логиката вътре в заявката за получаване е тривиална и Нок има значителни разходи, има смисъл да има малък брой тестове за интеграция, които могат да упражнят цялото приложение, включително страничния ефект. Можете да използвате Nock, за да избегнете връзката с жив сървър, и все пак да използвате HTTP заявки, за да проверите дали приложението връща разумен отговор, когато всички парчета се поберат заедно.

Nock е полезно да прекъснете връзката в HTTP слоя и да осигурите статичен отговор. Използвайте го обаче умерено. За всеки тест, който мъчите, увеличавате значително свързване и разходи за промяна.

Ако не се използва пестеливо, Nock може да създаде Nock Hell.

Проблемът, който искате да решите, е да намалите броя на грешките и цената на промяната. Ако промените структурата на кода без промени в поведението, тестовете не трябва да се нарушават. Ако го направят, значи не сте успели да напишете полезни тестове.

Вашата цел трябва да бъде да подобрите качеството на тестовото покритие до логиката, от която се интересувате, и да постигнете ранна обратна връзка. Всичко това, без да се засяга способността Ви да префабрикувате кода.

Изолирайте страничните ефекти и ограничете използването на инструменти като Nock до границите на приложението.

Това трябва да ви даде достатъчно увереност да правите промени и да не нарушавате нещата.

Присъединете се към борбата, натиснете страничните ефекти и след това ... Изключете го.

Благодаря за четенето. Ако имате някаква обратна връзка, свържете се с мен в Twitter, Facebook или Github.

Благодаря на Eduardo Slompo и Guilherme J. Tramontina за проницателната обратна връзка към този пост.