Внедрете, мащабирайте: опита от използването на автотестове във VTB

Нашето подразделение създава напълно автоматични конвейери за въвеждане на нови версии на приложения в производствената среда. Разбира се, това изисква автоматизирани функционални тестове. Под разрезът е история за това как, започвайки с тестване в една нишка на локална машина, стигнахме до многопоточно стартиране на Selenoid автоматични тестове в конвейера за изграждане с доклад на Allure на страниците на GitLab и в резултат на това ние има страхотен инструмент за автоматизация, който бъдещите потребители могат да използват.

Внедрете, мащабирайте: опита от използването на автотестове във VTB

Откъде започнахме

За да внедрим автоматичните тестове и да ги интегрираме в тръбопровода, се нуждаехме от рамка за автоматизация, която може гъвкаво да се променя според нашите нужди. В идеалния случай исках да получа единен стандарт за машината за автотест, адаптиран за вграждане на автотестове в конвейера. За изпълнение сме избрали следните технологии:

  • Java,
  • Мейвън,
  • селен,
  • Краставица+JUNIT 4,
  • привлекателност,
  • gitlab.

Внедрете, мащабирайте: опита от използването на автотестове във VTB

Защо точно този комплект? Java е един от най-популярните езици за автотестове и освен това всички членове на екипа го знаят. Селенът е очевидното решение. Краставицата, наред с други неща, трябваше да повиши доверието в резултатите от автотестовете от отделите, участващи в ръчното тестване.

Тестове с една нишка

За да не преоткриваме колелото, ние взехме разработки от различни хранилища на GitHub като основа на рамката и ги адаптирахме за себе си. Създадохме хранилище за основната библиотека с ядрото на рамката за автотест и хранилище със златен пример за внедряване на автотестове в нашето ядро. Всеки екип трябваше да вземе Gold изображение и да разработи тестове в него, като го адаптира към своя проект. Внедрено в GitLab-CI банка, на която конфигурирахме:

  • ежедневно стартиране на всички писмени автотестове за всеки проект;
  • работи в конвейера за изграждане.

Отначало имаше малко тестове и те вървяха в един поток. Стартирането с една нишка на GitLab Windows runner беше добре за нас: тестовете натовариха тестовия стенд много малко и почти не използваха ресурси.

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

  • не можахме да се уверим, че тестовете са стабилни;
  • тестовете, които се изпълняват няколко пъти подред на локалната машина, понякога се сриват в CI.

Пример за настройка на автоматични тестове:

<plugins>
	
<plugin>
    	
<groupId>org.apache.maven.plugins</groupId>
    	
<artifactId>maven-surefire-plugin</artifactId>
    	
<version>2.20</version>
    	
<configuration>
        	
<skipTests>${skipTests}</skipTests>
        	
<testFailureIgnore>false</testFailureIgnore>
        	
<argLine>
            	
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
            	
-Dcucumber.options="--tags ${TAGS} --plugin io.qameta.allure.cucumber2jvm.AllureCucumber2Jvm --plugin pretty"
        	
</argLine>
    	
</configuration>
	
    <dependencies>
        	
<dependency>
            	
<groupId>org.aspectj</groupId>
            	
<artifactId>aspectjweaver</artifactId>
            	
<version>${aspectj.version}</version>
        	
</dependency>
    	
</dependencies>
	
</plugin>
	
<plugin>
    	
<groupId>io.qameta.allure</groupId>
    	
<artifactId>allure-maven</artifactId>
    	
<version>2.9</version>
	
</plugin>
</plugins>

 Внедрете, мащабирайте: опита от използването на автотестове във VTB
Пример за доклад на Allure

 Внедрете, мащабирайте: опита от използването на автотестове във VTB
Натоварване на програмата по време на тестове (8 ядра, 8 GB RAM, 1 нишка)
 
Предимства на еднонишковите тестове:

  • лесен за настройка и стартиране;
  • стартиранията в CI практически не се различават от локалните стартирания;
  • тестовете не си влияят взаимно;
  • минимални изисквания за ресурси за бегача.

Недостатъци на еднонишковите тестове:

  • отнема много време за завършване;
  • дълго стабилизиране на тестовете;
  • неефективно използване на ресурсите на бегача, изключително ниско използване.

Тестове на JVM разклонения

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

Selenoid сървърът е издигнат на машина с 32 ядра и 24 GB RAM. Ограничението беше поставено на 48 браузъра - 1,5 нишки на ядро ​​и около 400 MB RAM. В резултат времето на теста беше намалено от три часа на 40 минути. Ускоряването на изпълнението помогна за решаването на проблема със стабилността: сега можехме бързо да стартираме нови автотестове 20-30 пъти, докато се уверим, че работят стабилно.
Първият недостатък на решението беше високото използване на ресурсите на бегачите с малък брой паралелни нишки: на 4 ядра и 8 GB RAM тестовете работеха стабилно в не повече от 6 нишки. Вторият минус: плъгинът генерира класове за изпълнение за всеки сценарий, без значение колко от тях се изпълняват.

Важно! Не предавайте маркирана променлива в argLine, например така:

<argLine>-Dcucumber.options="--tags ${TAGS} --plugin io.qameta.allure.cucumber2jvm.AllureCucumber2Jvm --plugin pretty"</argLine>
…
Mvn –DTAGS="@smoke"

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

Правилно хвърлете променлива с таг в тагове в настройките на плъгина, вижте примера по-долу. При други методи, които сме тествали, има проблеми при свързването на плъгина Allure.

Пример за изпълнение за 6 кратки теста с неправилна настройка:

[INFO] Total time: 03:17 min

Пример за времето за изпълнение на теста, ако директно предадете маркера на mvn... –Dcucumber.options:

[INFO] Total time: 44.467 s

Пример за настройка на автоматични тестове:

<profiles>
	
<profile>
    	
<id>parallel</id>
    	
<build>
        	
<plugins>
            	
<plugin>
                	
<groupId>com.github.temyers</groupId>
                	
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
                	
<version>5.0.0</version>
                	
<executions>
                    	
<execution>
                        	
<id>generateRunners</id>
                        	
<phase>generate-test-sources</phase>
                        	
<goals>
                            	
<goal>generateRunners</goal>
                        	
</goals>
                        	
<configuration>
                	
            <tags>
                            	
<tag>${TAGS}</tag>
                            	
</tags>
                            	
<glue>
                                	
<package>stepdefs</package>
                            	
</glue>
                        	
</configuration>
     	
               </execution>
                	
</executions>
    	
        </plugin>
            	
<plugin>
                	
<groupId>org.apache.maven.plugins</groupId>
                	
<artifactId>maven-surefire-plugin</artifactId>
        	
        <version>2.21.0</version>
                	
<configuration>
                    	
<forkCount>12</forkCount>
                    	
<reuseForks>false</reuseForks>
                    	
<includes>**/*IT.class</includes>
                   	
 <testFailureIgnore>false</testFailureIgnore>
                    	
<!--suppress UnresolvedMavenProperty -->
                    	
<argLine>
  	
 -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" -Dcucumber.options="--plugin io.qameta.allure.cucumber2jvm.AllureCucumber2Jvm TagPFAllureReporter --plugin pretty"
                    	
</argLine>
                	
</configuration>
                	
<dependencies>
                    	
<dependency>
                        	
<groupId>org.aspectj</groupId>
                        	
<artifactId>aspectjweaver</artifactId>
                        	
<version>${aspectj.version}</version>
                 	
   </dependency>
                	
</dependencies>
         	
   </plugin>
        	
</plugins>
    	
</build>
	
</profile>

Внедрете, мащабирайте: опита от използването на автотестове във VTB
Пример за доклад на Allure (най-нестабилен тест, 4 повторения)

Внедрете, мащабирайте: опита от използването на автотестове във VTBНатоварване на Runner по време на тестове (8 ядра, 8 GB RAM, 12 нишки)
 
плюсове:

  • лесна настройка - просто трябва да добавите плъгин;
  • възможността за едновременно провеждане на голям брой тестове;
  • ускоряване на тестовата стабилизация поради т.1. 

против:

  • необходими са множество ОС/контейнери;
  • висока консумация на ресурси на вилка;
  • Плъгинът е отхвърлен и вече не се поддържа. 

Как да победим нестабилността 

Тестовите стендове не са перфектни, както и самите автотестове. Не е изненадващо, че сега имаме редица нестабилни тестове. Дойде на помощ плъгин maven surefire, който извън кутията поддържа рестартиране на неуспешни тестове. Трябва да актуализирате версията на плъгина поне до 2.21 и да напишете един ред с броя на рестартирането в pom файла или да го предадете като аргумент на Maven.

Пример за настройка на автоматични тестове:

   	
<plugin>
        	
<groupId>org.apache.maven.plugins</groupId>
  	
      <artifactId>maven-surefire-plugin</artifactId>
        	
<version>2.21.0</version>
        	
<configuration>
           	
….
            	
<rerunFailingTestsCount>2</rerunFailingTestsCount>
            	
….
            	
</configuration>
</plugin>

Или при стартиране: mvn ... -Dsurefire.rerunFailingTestsCount=2 ...
Като алтернатива задайте опциите на Maven за скрипта PowerShell (PS1):

  
Set-Item Env:MAVEN_OPTS "-Dfile.encoding=UTF-8 -Dsurefire.rerunFailingTestsCount=2"

плюсове:

  • няма нужда да губите време за анализиране на нестабилен тест, когато се срине;
  • проблемите със стабилността на тестовия стенд могат да бъдат изгладени.

против:

  • можете да пропуснете плаващи дефекти;
  • времето за работа се увеличава.

Паралелни тестове с библиотека Cucumber 4

Броят на тестовете нарастваше всеки ден. Отново се замислихме за ускоряване на бяганията. Освен това исках да вградя възможно най-много тестове в конвейера за асемблиране на приложението. Критичният фактор беше твърде дългото генериране на бегачи при паралелно изпълнение с помощта на плъгина Maven.

По това време Cucumber 4 вече беше пуснат, така че решихме да пренапишем ядрото за тази версия. В бележките към изданието ни беше обещано паралелно стартиране на ниво нишка. Теоретично това трябваше да бъде:

  • значително ускоряване на изпълнението на автотестовете чрез увеличаване на броя на нишките;
  • елиминирайте загубата на време за генериране на бегачи за всеки автотест.

Оказа се, че не е толкова трудно да се оптимизира рамката за многопоточни автотестове. Cucumber 4 изпълнява всеки отделен тест в специална нишка от началото до края, така че някои общи статични неща бяха просто преобразувани в ThreadLocal променливи. 
Основното нещо, когато конвертирате с помощта на Idea refactoring, е да проверите местата, където променливата е сравнена (например проверка за нула). Освен това трябва да поставите плъгина Allure в анотацията на класа Junit Runner.

Пример за настройка на автоматични тестове:

 
<profile>
	
<id>parallel</id>
	
<build>
    	
<plugins>
        	
<plugin>
            	
<groupId>org.apache.maven.plugins</groupId>
 	
           <artifactId>maven-surefire-plugin</artifactId>
            	
<version>3.0.0-M3</version>
   	
         <configuration>
                	
<useFile>false</useFile>
                	
<testFailureIgnore>false</testFailureIgnore>
        	
        <parallel>methods</parallel>
                	
<threadCount>6</threadCount>
                	
<perCoreThreadCount>true</perCoreThreadCount>
                	
<argLine>
                    	
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                	
</argLine>
            	
</configuration>
            	
<dependencies>
                	
<dependency>
                    	
<groupId>org.aspectj</groupId>
   	
                 <artifactId>aspectjweaver</artifactId>
                    	
<version>${aspectj.version}</version>
                	
</dependency>
            	
</dependencies>
        	
</plugin>
    	
</plugins>
	
</build>
</profile>

Внедрете, мащабирайте: опита от използването на автотестове във VTBПример за доклад на Allure (най-нестабилен тест, 5 повторения)

Внедрете, мащабирайте: опита от използването на автотестове във VTBНатоварване на Runner по време на тестове (8 ядра, 8 GB RAM, 24 нишки)

плюсове:

  • ниска консумация на ресурси;
  • родна поддръжка от Cucumber - не са необходими допълнителни инструменти;
  • възможност за изпълнение на повече от 6 нишки на процесорно ядро.

против:

  • трябва да се уверите, че кодът поддържа многопоточно изпълнение;
  • прагът за влизане се увеличава.

Доклади на Allure в страниците на GitLab

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

Всички екранни снимки с доклади на Allure са направени в страниците на GitLab. Скрипт за разполагане на отчет на страници на GitLab - на Windows PowerShell (преди това трябва да стартирате автоматични тестове):

New-Item -ItemType directory -Path $testresulthistory | Out-Null

try {Invoke-WebRequest -Uri $hst -OutFile $outputhst}
Catch{echo "fail copy history"}
try {Invoke-WebRequest -Uri $hsttrend -OutFile $outputhsttrnd}
Catch{echo "fail copy history trend"}

mvn allure:report
#mvn assembly:single -PzipAllureReport
xcopy $buildlocationtargetsiteallure-maven-plugin* $buildlocationpublic /s /i /Y

В резултат на което 

Така че, ако сте мислили дали имате нужда от Thread safe код в рамката за автотест на Cucumber, сега отговорът е очевиден - с Cucumber 4 той е лесен за внедряване, като по този начин значително се увеличава броят на нишките, изпълнявани едновременно. При този метод на провеждане на тестове въпросът вече е за производителността на машината със Selenoid и тестовия стенд.

Практиката показва, че провеждането на автоматични тестове на нишки ви позволява да минимизирате потреблението на ресурси с най-добра производителност. Както може да се види от графиките, двукратното увеличение на нишките не води до подобно ускорение при преминаване на тестове за производителност. Въпреки това успяхме да добавим повече от 2 автоматизирани теста към компилацията на приложението, които дори с 200 повторения се изпълняват за около 5 минути. Това ви позволява да получите бърза обратна връзка от тях и, ако е необходимо, да направите промени и да повторите процедурата отново.

Източник: www.habr.com

Добавяне на нов коментар