Укараняй, маштабуй: досвед ужывання аўтатэстаў у ЗГБ

Наша падраздзяленне стварае цалкам аўтаматычныя пайплайны для вываду новых версій прыкладанняў у прод-асяроддзе. Зразумела, для гэтага патрабуюцца аўтаматызаваныя функцыянальныя выпрабаванні. Пад катам - гісторыя пра тое, як, пачаўшы з тэставання ў адзін струмень на лакальнай машыне, мы дайшлі да шматструменнага запуску аўтатэстаў на Selenoid у пайплайне зборкі з Allure-справаздачай на GitLab pages і ў выніку атрымалі крутую прыладу для аўтаматызацыі, які змогуць выкарыстаць будучыя каманды.

Укараняй, маштабуй: досвед ужывання аўтатэстаў у ЗГБ

З чаго мы пачыналі

Каб рэалізаваць аўтатэсты і ўбудаваць іх у пайплайн, нам патрабаваўся фрэймворк для аўтаматызацыі, які можна гнутка мяняць пад нашы патрэбы. У ідэале жадалася атрымаць адзіны стандарт для рухавічка аўтатэставання, прыстасаваны пад убудаванне аўтатэстаў у пайплайн. Для рэалізацыі мы абралі наступныя тэхналогіі:

  • Java,
  • Мэйвен,
  • селен,
  • Cucumber+JUNIT 4,
  • Allure,
  • GitLab.

Укараняй, маштабуй: досвед ужывання аўтатэстаў у ЗГБ

Чаму менавіта такі набор? Java - адна з самых папулярных моў для аўтатэстаў, да таго ж ім валодаюць усе члены каманды. Selenium відавочнае рашэнне. Cucumber жа, апроч іншага, павінен быў падвысіць давер да вынікаў аўтатэстаў са боку падраздзяленняў, якія займаюцца ручным тэставаннем.

Аднаструменевыя тэсты

Каб не вынаходзіць ровар, за аснову фрэймворка мы ўзялі напрацоўкі з розных рэпазітароў на GitHub і адаптавалі іх пад сябе. Стварылі рэпазітар для галоўнай бібліятэкі з ядром фрэймворка аўтатэстаў і рэпазітар з Gold-прыкладам рэалізацыі аўтатэстаў на нашым ядры. Кожная каманда павінна была браць Gold-выява і распрацоўваць у ім тэсты, адаптуючы пад свой праект. Разгарнулі ў слоіку GitLab-CI, на якім наладзілі:

  • штодзённыя запускі ўсіх напісаных аўтатэстаў па кожным праекце;
  • запускі ў пайплайне зборкі.

Спачатку тэстаў было мала, і яны ішлі ў адну плынь. Аднаструменевы запуск на Windows-раннеры GitLab нас суцэль уладкоўваў: тэсты вельмі малаважна нагружалі тэставы стэнд і амаль не ўтылізавалі рэсурсы.

З часам аўтатэстаў рабілася ўсё больш, і мы задумаліся над іх паралельным запускам, калі поўны прагон пачаў займаць каля трох гадзін. З'явіліся і іншыя праблемы:

  • мы не маглі пераканацца ў тым, што тэсты стабільныя;
  • тэсты, якія праходзілі па некалькі прагонаў запар на лакальнай машыне, часам падалі ў 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>

 Укараняй, маштабуй: досвед ужывання аўтатэстаў у ЗГБ
Прыклад Allure-справаздачы

 Укараняй, маштабуй: досвед ужывання аўтатэстаў у ЗГБ
Нагрузка на раннэр падчас тэстаў (8 ядраў, 8 ГБ АЗП, 1 струмень)
 
Плюсы аднаструменных тэстаў:

  • лёгка наладзіць і запусціць;
  • запускі ў CI практычна не адрозніваюцца ад лакальных запускаў;
  • тэсты не афектаць адзін аднаго;
  • мінімальныя патрабаванні да рэсурсаў раннера.

Мінусы аднаструменных тэстаў:

  • вельмі доўга выконваюцца;
  • доўгая стабілізацыя тэстаў;
  • неэфектыўнае выкарыстанне рэсурсаў раннера, вельмі нізкая ўтылізацыя.

Тэсты на форках JVM

Паколькі пры рэалізацыі базавага фрэймворка мы не паклапаціліся аб thread-safe кодзе, самым відавочным спосабам раўналежнага запуску стаў cucumber-jvm-parallel-plugin для Maven. Убудова лёгка наладзіць, але для карэктнай раўналежнай працы аўтатэсты трэба запускаць у асобных браўзэрах. Рабіць няма чаго, прыйшлося выкарыстоўваць Selenoid.

Selenoid-сервер паднялі на машыне з 32 ядрамі і 24 ГБ АЗП. Ліміт усталявалі ў 48 браўзэраў - 1,5 патоку на ядро ​​і каля 400 МБ АЗП. У выніку час тэстаў скараціўся з трох гадзін да 40 хвілін. Паскарэнне прагонаў дапамагло вырашыць праблему стабілізацыі: зараз мы маглі хутка праганяць новыя аўтатэсты 20-30 раз, пакуль не пераканаемся, што яны выконваюцца стабільна.
Першым недахопам рашэння стала высокая ўтылізацыя рэсурсаў раннераў пры невялікай колькасці раўналежных струменяў: на 4 ядрах і 8 ГБ АЗП тэсты працавалі стабільна не больш за ў 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>

Укараняй, маштабуй: досвед ужывання аўтатэстаў у ЗГБ
Прыклад Allure-справаздачы (самы нестабільны тэст, 4 реран)

Укараняй, маштабуй: досвед ужывання аўтатэстаў у ЗГБНагрузка раннера падчас тэстаў (8 ядраў, 8 ГБ АЗП, 12 патокаў)
 
Плюсы:

  • простая налада - трэба толькі дадаць плягін;
  • магчымасць адначасовага выканання вялікай колькасці тэстаў;
  • паскарэнне стабілізацыі тэстаў дзякуючы п.1. 

Мінусы:

  • патрабуецца некалькі АС / кантэйнераў;
  • высокае спажыванне рэсурсаў на кожны форк;
  • убудова састарэлы і больш не падтрымліваецца. 

Як перамагчы нестабільнасць 

Тэставыя стэнды не ідэальныя, як і самі аўтатэсты. Нядзіўна, што ў нас з'явілася некаторая колькасць flacky-тэстаў. На дапамогу прыйшоў maven surefire plugin, Які са скрынкі падтрымлівае перазапуск якія падалі тэстаў. Трэба абнавіць версію плагіна мінімум да 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, таму мы вырашылі перапісаць ядро ​​пад гэтую версію. У release notes нам абяцалі паралельны запуск на ўзроўні трэдаў. Тэарэтычна гэта павінна было:

  • значна паскорыць прагон аўтатэстаў за рахунак павелічэння колькасці струменяў;
  • выключыць страту часу на генерацыю раннераў для кожнага аўтатэста.

Аптымізаваць фрэймворк для шматструменных аўтатэстаў аказалася не так складана. Cucumber 4 праганяе кожны асобны тэст у вылучаным струмені ад пачатку і да канца, таму некаторыя агульныя static-рэчы былі проста пераўтвораны ў ThreadLocal-зменныя. 
Галоўнае пры канвертацыі сродкамі рэфактарынгу Idea – праверыць месцы, у якіх адбывалася параўнанне зменнай (напрыклад, праверка на null). Акрамя таго, трэба вынесці 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>

Укараняй, маштабуй: досвед ужывання аўтатэстаў у ЗГБПрыклад Allure-справаздачы (самы нестабільны тэст, 5 рэранаў)

Укараняй, маштабуй: досвед ужывання аўтатэстаў у ЗГБНагрузка раннера падчас тэстаў (8 ядраў, 8 ГБ АЗП, 24 патокі)

Плюсы:

  • нізкае спажыванне рэсурсаў;
  • натыўная падтрымка ад Cucumber - не патрэбныя дадатковыя прылады;
  • магчымасць запуску больш за 6 патокаў на ядро ​​працэсара.

Мінусы:

  • трэба сачыць за тым, каб код падтрымліваў шматструменнае выкананне;
  • павялічваецца парог уваходжання.

Allure-справаздачы ў GitLab pages

Пасля ўкаранення шматструменнага запуску мы сталі марнаваць на аналіз справаздач значна больш часу. На той момант нам даводзілася выкладваць кожную справаздачу як артэфакт у GitLab, потым спампоўваць яе, распакоўваць. Гэта ня вельмі зручна і доўга. А калі нехта яшчэ хоча паглядзець справаздачу ў сябе, то яму трэба будзе зрабіць тыя ж аперацыі. Нам хацелася атрымліваць фідбэк хутчэй, і выхад знайшоўся - GitLab pages. Гэты убудаваная функцыя, якая даступная са скрынкі ва ўсіх апошніх версіях GitLab. Дазваляе дэплоіць статычныя сайты ў сябе на серверы і атрымліваць да іх доступ па прамой спасылцы.

Усе скрыншоты з Allure-справаздачамі зроблены ў GitLab pages. Скрыпт для дэплою справаздачы на ​​GitLab pages - на 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 рэранамі выконваюцца прыкладна за 24 хвіліны. Гэта дазваляе атрымліваць ад іх хуткі фідбэк, а пры неабходнасці - уносіць праўкі і паўтараць працэдуру зноў.

Крыніца: habr.com

Дадаць каментар