JTechLog - Ода за тестове за интеграция
22 март 2020 г.
Проведено на 17 октомври 2019 г., Training360 Проверете шумът зад срещата на разработчиците. В това изнесох лекция, озаглавена Трудности при интеграционните тестове (на Java), въпреки че по-скоро обсъдих положителните страни на интеграционните тестове.
Внимание! Следващият пост съдържа елементи, които могат да нарушат вашето спокойствие. Целта ми е да подчертая, че понякога се налага да поставяме под съмнение основни твърдения и елементи като тестовата пирамида. Следователно в публикацията може да срещнете изместване на акцентите, от вас се изисква да се справите с това на място.

В публикацията ще мина през тестовата пирамида и концепциите и дори моите резерви към нея. След това ще разгледам алтернативен подход, който е особено приложим за микроуслугите. Междувременно ще дам и примери за тестване на просто приложение Spring Boot. Примерният проект е достъпен на GitHub.
Тестова пирамида
Тестовата пирамида е въведена от Майк Кон в книгата си „Успех с Agile“, за да визуализира как да поставите различни нива на тестване.
На най-ниското ниво са модулните тестове, които тестват най-малката единица от даден програмен език, в случая на обектно-ориентираните езици това е ниво на класа. На средно ниво са тестовете за интеграция, които вече тестват сътрудничеството на отделите. И накрая, най-високото ниво са тестовете End-to-end, с които тестваме цялото приложение в дадена среда, интегрирано с техните зависимости. Освен това това не е част от грабнатата функционалност, а цялостен бизнес процес от началото до края.
Формата на тестовата пирамида произтича от факта, че от основата тестовете работят с все по-голям обхват, те са все по-интензивни за поддържане и изпълнение и затова си струва да пишете все по-малко от тях движещи се нагоре.
За съжаление, това вече поражда няколко въпроса у мен. От една страна, понятията не са ясно дефинирани, всички останали означават различни. Вече не е напълно ясно как се наричат части от дадено приложение. Класовете са на най-ниското ниво, можем да се съгласим за това, но кои са по-високите нива? Те се наричат модули (напр. Книга за архитектура на приложения на Java, OSGi), компоненти (например книга за чиста архитектура, която е много противоположна на напр. Spring Framework/Java EE, където компонентът е боб), приставки и т.н. Дори за приложението се използват различни имена, като система, услуга и т.н. Книгата Clean Architecture и микроуслугите наричат приложението услуга и това ме обърква, тъй като Spring Framework също извиква боб в слоя бизнес логика в тристепенна архитектура. Ще използвам класа (и да, в този случай интерфейсите, изброяванията, анотациите и т.н.), модула, имената на приложенията.
При модулното тестване е ясно, че външните зависимости трябва да се подиграват. Да, но клас може да използва много елементи в библиотеката на класове Java SE, като. низът, списъкът и т.н. Това външни зависимости ли са? Очевидно не, така че можем да кажем, че не се подиграваме с тях. Какво ще кажете за това в случай на външни библиотеки, които прилагат подобни структури от данни като напр. колекциите Guava или Apache Commons? А какво да кажем за нашите подобни собствени класове, стойностни обекти? Ами външните зависимости като напр. да регистрирате SLF4J? Може ли да се извика единичен тест при стартиране на контейнер, напр. пролетната рамка или част от нея? (Тестът на Spring Framework е, когато тествате компонент, но стартирате определени Springes устройства, по-малък контейнер.) Къде да начертаете границата?
В случая на теста за интеграция, може би въпросът е по-малък, тъй като на практика за всеки тест, който включва повече от един клас, можем да изтеглим маркера на теста за интеграция. Има малко объркване в името, че тестовете, при които интегрираме няколко приложения и изследваме тяхното взаимодействие, също се наричат интеграционни тестове.
Има и немалко въпроси относно тестовете E2E. Включва ли само тестове на повърхността? Или API тестове могат да бъдат включени тук, когато друг интерфейс на приложението, напр. Обръщаме се към уеб услугата REST. Може ли да се нарече тест E2E, ако тестваме само една подфункция през интерфейса? Тестваме в пълна изолация от други приложения, или точката E2E означава да се интегрира с други приложения?
В допълнение се появяват такива понятия като сервизен тест, тест на компоненти, системен тест, какво означават те?
Мисля, че от това вече става ясно, че основният проблем в тази област е, че няма добра, достатъчно точна терминология, други разбират едни и същи понятия по различен начин. Освен това разпространението на архитектурата на микроуслугите обърка това малко повече и терминологията, която така или иначе не беше разработена, не можеше да се адаптира към новите методи.
Автоматизираното тестване и свързаните с него инструменти (сбруя на тялото) са толкова важни, че трябва да бъдат част от архитектурата и по този начин да бъдат проектирани. Всички общи архитектури споменават това, като. шестоъгълна архитектура, лукова архитектура и чиста архитектура. Въпреки това все още виждам, че тестването се извършва напълно независимо от много, на много места от отделен екип, който дори не получава подкрепа, за да си свърши работата.
Съмнения относно модулното тестване
В примерите ще покажа приложение (което също се откроява като микроуслуга), което е тристепенно приложение Spring Boot, което следи данните за града. Не внедрих интерфейса на JavaScript, той е достъпен в REST API. Под базата данни H2. Знаете координатите на даден град. Използвайки алгоритъма Haversine, той изчислява и връща разстоянието си от Будапеща. Той също така връща температурата, измерена в града, с помощта на външна услуга (Time).
Мисля, че всички знаем обещанията за модулно тестване. За по-нататъшно обсъждане обаче си струва да се проучат два подхода към модулното тестване:
- Въз основа на състоянието: получаваме очаквания изход за съответния вход
- Базирано на поведение: работи с правилните класове по правилния начин: разглеждаме подиграваните зависимости, за да видим дали те са били поканени правилно
В наши дни обаче започва да се появява и критика към модулното тестване. Първо и най-важно, ако следваме модела на създаване на отделен тестов клас за всеки клас и поне един тестов метод за всеки публичен метод, тестовете ни ще бъдат фино гранулирани и ако искаме да направим по-голям рефакторинг, това е много тестови случаи. ще бъдат засегнати, което ще доведе до проблема с крехкия тест. Всъщност този метод се използва за тестване на подробности за изпълнението.