αααααααααααΎααααααΎαααααααααα αΌααααααααααααααααα·αααΆααααααααααααΆααααΆαααΎαααααΎαααΆαααααααααΈαααααααα·ααΈαα αααα»αααα·ααΆααΆαααα·αααααα ααΆααΆααα·αααΆααααααααααΌαα±ααααΆαααΆαααααΎααααααα»αααΆααααααααααααααααα·α ααΆααααααααΆαααΆαααααααΊααΆααΏαα’αααΈαααα αααα αΆααααααΎαααΆαα½αααΉαααΆαααααΎααααααααα½ααααααα ααΎαααΆαααΈααααα»ααααα»α ααΎαααΆαααΆααααα ααα»α αα multi-threaded autotest αααααααΎαααΆαααΎ Selenoid αα αααα»α build pipeline ααΆαα½αααΉααααΆαααΆααα Allure αα ααΎααααα GitLab α αΎααα ααΈαααα»αααα½αααΆαα§αααααααααααααααααα·αααααααΆααα αααααα»αααααΆαααα’ααΆααα’αΆα ααααΎαααα»αα
ααΎααΎαα αΆααααααΎααα α―ααΆ?
ααΎααααΈα’αα»ααααααΆαααααΎαααααααααααααααααα· αα·ααααα αΌααα½αααΆαα αααα»αααααααααα αΌαααααα ααΎαααααΌαααΆααααααααααααααααααααααα·αααα αααα’αΆα ααααΆααααααΌαααΆαααΆααααααΌαααΆαααααααΎαα ααΆαα§ααααααα· αααα»αα ααααα½αααΆααααααααΆααααα½ααααααΆαααααΆαααΈα autotesting ααααααααααα½ααααααΆααααΆααααααα autotests αα αααα»αααααααααα αΌααααααα αααααΆααααΆαα’αα»αααα ααΎαααΆαααααΎαααΎααα αα αααα·ααααΆααΌα ααΆααααααα
- α αΆαααΆ
- αααΆααα
- αααααααΌα
- αααααα + ααΈ α€,
- ααΆααααΆα,
- α αααΈαα‘αΆαα
α ααα»α’αααΈααΆαααΆαα»ααα·αααααα? Java ααΊααΆααΆααΆααααααα·αααααα»ααα½ααααααΆααααΆαααααΎααααααααααααααααααααα· α αΎααααΆαα·ααααα»αααΆααα’αααα·ααΆαααΆα αααααααΌαααΊααΆαααααααααΆαααΆαααααααα αααααα αααα»αα
αααααααααααααααα ααααΌαααΆαααααααααααΆ αααααΎααααα»αα
α·αααααΎααααααααααΆαααααΎααααααααααααααααααααα·αα
ααΎαααααααααΆααααααΆααααααΆαααααααααΉαααΆαααααΎααααααααααα
ααΆαααααΎααααααααααααα½α
ααΎααααΈβαα·αβαααααΎαβαααβα‘αΎαβαα·α ααΎαβααΆαβααβααΆαβα’αα·ααααβααΈβααααΆααβααααααβαα βααΎ GitHub ααααΎβααΆβααΌαααααΆαβαααααΆααβαααααααα α αΎαβααααα½αβααΆβαααααΆααβαααα½αβααΎαα ααΎαααΆααααααΎαααααΆαααααααΆαααααααΆαααα ααααααΆαα½αααΉαααααΌααααααααααααααΆαααααΎαααααααααααααααααα· αα·αααααΆαααααααΆαα§ααΆα αααααΆαααααΆαα’αα»ααααααΆαααααΎαααααααααααααααααα·αα ααΎααααΌαααααααΎαα αααα»αααΈαα½ααααααΌαααααΌαααΆαααΆα αα·ααααααΎαααΆαααααΎααααααα αααα»αααΆ ααααααααααΆαα ααΉααααααααααααα½αααα ααΎαααΆαααΆαααααααΆαααΆαα αααΆααΆα GitLab-CI αααααΎαααααααα ααΆααααααααα
- ααΆαααααααα αΆαααααααααΆαααααΎαααααααααααααααααα·αααααΆααααααααΆααα’αααααααΆααααααααααΈαα½ααα
- ααΎαααααΎαααΆααα αααα»αααααααααα αΌαα
ααααΌαβα‘αΎαβααΆαβααΆαβααααΎβαααααβαα·α αα½α α αΎαβαα½αααβααααΌαβααΆαβα’αα»ααααβαααα»αβα ααααβαα½αα ααΆαααααΎαααΆααααα½ααααααα ααΎαααααα·ααΈααααΎαααΆαααΈαααΌ GitLab ααΆαααααΉαααΎαααΆααα ααΆαααααΎαααααααΆααααα»ααα α’αΈααΆααααααααΆαααααΆα α αΎαααααΎααααΆααααααΎαααααααΆαααααΆαα
ααΌαααα α ααα½αααααΆαααααΎαααααααααααααααααα·ααΆααααααΆαααΆααααα αααΎα α αΎαααΎαααΆααα·αα’αααΈααΆαααααΎαααΆααα½αααΆααααααααΆ αα ααααααααΆααααααααααα αΆααααααΎαα αααΆαααααααα αα XNUMX ααααα αααα αΆααααααααααααΆαααα α ααααα
- ααΎααα·αα’αΆα αααααααααΆααααΆααΆαααααΎαααααααΆααααααααΆαααα
- ααΆαααααΎααααααααααααΌαααΆαααααΎαααΆαααΆα αααΎαααααΆαααααααΆαα ααΎαααΆαααΈαααΌαααααΆα αα½αααΆαααΆαααα αααα»α CI α
α§ααΆα αααααααΆαααα‘αΎα autotestsα
<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 cores, RAM 8 GB, 1 thread)
αα»ααααααααα·ααααΆαααααΎααααααααααααα½αα
- ααΆααααα½ααααα»αααΆαααα‘αΎααα·αααααΎαααΆα;
- ααΆαααΎαααααΎαααΆααα αααα»α CI ααΊαα·ααα»αααΈααΆαααΎαααααΎαααΆααααα»ααααα»αααα
- ααΆαααααΎααααααα·ααααααΆαααααααααΆαα αα·ααα αα;
- αααααΌαααΆαα’αααααααΆαααααΆααααααΆαα’αααααααααααΆααα
αα»ααα·ααααα·ααααΆαααααΎααααααααααααα½αα
- α αααΆααααααΌαααΆααααΎααααΈαααα αα;
- αααααααΆαααΌαααααΆαααααΎααααα;
- ααΆαααααΎααααΆααααααΆαα’αααααααα·αααΆαααααα·αααααΆα ααΆαααααΎααααΆααααΆααααα»αα
ααΆαααααΎααααααα ααΎαα JVM
αααααΆαααΎααα·αααΆαααα
α·ααααα»αααΆααααΎααΌααα»ααααα·ααΆααααααααα‘αΆααα
αααα’αα»αααααααααααααααΌαααααΆα αα·ααΈααΆααααααααααα»αααΎααααΈααααΎαααΆαααααααααΆααΊ
αααΆαααΈααα Selenoid ααααΌαααΆαααΆααα±ααααααΎαααΆααα
ααΎαααΆαααΈααααααΆα 32 cores αα·α 24 GB RAM α ααααααααααααΌαααΆαααααααα
48 αααααα·ααΈαα»ααα - 1,5 αααααααα‘αΆααααα»ααα½αααααΌααα·ααααα αα 400 ααααΆαααα RAM α ααΆαααααα αααααααΆααααΎαααααααααΌαααΆαααΆαααααααααΈααΈαααααα 40 ααΆααΈα ααΆααααααΎαααααΏαααααΆααααααΆααα½ααααααααΆααααα αΆαααααααΆαα α₯α‘αΌααααααΎαα’αΆα
ααααΎαααΆαααΆαααααΎαααααααααααααααααα·ααααΈααΆααααΆαααΏα 20-30 αα αα αΌααααααΎαααααΆααααΆααΆααααΎαααΆααααααΆαααΏααΆααα
αα»ααα·ααααα·ααααΌααααααααααααΆαααΊααΆαααααΎααααΆαααααααααααααΆαα’αααααααααααΆαα
ααα½αααΌα
αα½ααααααααααα‘αΆααααΆαααΆα‘αα: αα
ααΎ 4 cores αα·α 8 GB αα RAM ααΆαααααΎαααααααΆαααααΎαααΆαααααααααααΆααα·αααΎαααΈ 6 threads α αα»ααα·ααααα·ααΈααΈαα αααααα·ααΈαααα½ααααααΎαααααΆααααααααααΆααααααΆααΈαααΌααΈαα½αα αα·αααΆαα½αααΆααα»ααααΆαααααΌαααΆαααΎαααααΎαααΆαααα
ααααΆαα! αα»αααααα’ααααααααΆαααααΆααα 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
α§ααΆα αααααααΆαααα‘αΎα autotestsα
<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 ααααΌα, RAM 8 GB, 12 αααα)
αααα»α:
- ααΆαααα‘αΎαααΆααααα½α - α’αααααααΆααααααααΌαααΆααααααααααααα·ααΈαααα½αα
- αααααααΆααααα»αααΆαα’αα»ααααααΆαααααΎααααααα½αα ααα½ααααααα»ααααααααΆαααααΆ;
- ααΆααααααΎαααααΏααααααααααΆαααΆαααααΎαααααα’ααα»αα ααααααα αΆαααΈ 1 α
αα»ααα·ααααα·:
- ααααααααααααα·ααααα·ααΆα / αα»αα αααΎαααααΌαααΆαααΆαααΆα;
- ααΆαααααΎααααΆααααααΆαααααααααααΆααααααΈαα½αα;
- αααααα·ααΈαααα½αααΊα α½ααααα α αΎααααααΆαααααααα αΎαα
αα·ααΈααααααα’αααα·αααΆα
αα
α’αΈααΆαααααααΊαα·αααα’αα ααΌα
ααΆααΆαααΆαααααααααααααααααα·αααα½αα―αα ααΆαα·ααα½αα±ααααααΆααααα’αΎααααααααΆααΎαααΆαααΆαααααΎααααα flicky αα½αα
ααα½αα ααΆααααα½ααααααααα
α§ααΆα αααααααΆαααα‘αΎα autotestsα
<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 tools ααΊααααΌααα·αα·αααααΎααααααααααα’αααααααΌαααΆααααααααα (α§ααΆα ααα αα·αα·ααααα null)α ααΎαααΈαααααα α’αααααααΌααααααααααααα·ααΈαααα½α Allure αα
αααα»αα
αααΆαααααααααααΆαα Junit Runner α
α§ααΆα αααααααΆαααα‘αΎα autotestsα
<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 ααααΌα, RAM 8 GB, 24 αααα)
αααα»α:
- ααΆαααααΎααααΆααααααΆαααΆα;
- ααΆαααΆααααααΎαααΈαααααα - αα·αααααΌαααΆαα§αααααααααααααα
- αααααααΆααααα»αααΆαααααΎαααΆαα αααΎαααΆα 6 αααααααα‘αΆααααα»ααα½αααααΌαααααΎαααΆαα
αα»ααα·ααααα·:
- α’αααβααααΌαβααααΆααβααΆβααΌαβααΆααααβααΆαβααααα·ααααα·βα αααΎαβααααα
- ααααα·αα αΌαααΎαα‘αΎαα
αααΆαααΆααα Allure αα ααΎααααα GitLab
αααααΆααβααΈβααααΆαβααΆαβααααα·ααααα·βα αααΎαβαααα ααΎαβα αΆααβααααΎαβα αααΆαβαααβα αααΎαβαααβαααα»αβααΆαβαα·ααΆαβαααΆαααΆαααα αα αααααα ααΎαααααΌααααα αααααΆαααΆαααααΈαα½ααααΆααααα»αα»ααΆααα GitLab αααααΆααααααΆαααααΆ α αΎαααααΆαααΆα ααα ααΆαα·αααΆααααα½ααα α αΎαα αααΆααααααΌαα α αΎαααααα·αααΎααααΆααααΆααααααααααα ααααΎααααΆαααΆααααααααΆαααααα½ααα½ααα ααααα½αααααΉαααααΌαααααΎααααα·ααααα·ααΆαααΌα ααααΆα ααΎαα ααααα½αααΆαααα·αααααα’ααΏαααΆααα»α α αΎαααΎαααΆαααααΎααααααααααΆααα½α - ααααα GitLab α αααααΊααΆαα»αααΆααααααααΆααααααΆαα½ααααααΆααα αααα αααα’αααα αααα»αααααααααΈαααΆααα’αααααα GitLab α α’αα»ααααΆαα±ααα’αααααΆαααααααΆαααα ααααααα·αα·αααααα ααΎαααΆαααΈαααααααα’ααα α αΎαα αΌαααααΎαα½αααΆααΆαααααααααααΆααα
ααΌαααα’ααααααααΆααα’αααααααΆαααΆααα Allure ααααΌαααΆααααα ααΎααααα GitLab α ααααααΈααααααΆααααΆαααααααΆααααΆαααΆααααα ααααα GitLab - αα αααα»α Windows PowerShell (αα»ααααα’αααααααΌαααααΎαααΆα autotests)α
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 αα αααα»ααααααααα autotest Cucumber ααααα α₯α‘αΌααααα ααααΎαααΊααΆααααααα - ααΆαα½α Cucumber 4 ααΆααΆααααα½ααααα»αααΆαα’αα»ααααααΆ αααα ααα»ααααααααΎαα ααα½ααααααααα‘αΆααααα αΆααααααΎααααα»ααααααααΆαααααΆα ααΆαα½αααΉααα·ααΈααΆαααααααααΆαααααΎαααΆαααΆαααααΎαααααααα αααα½αα₯α‘αΌααααααΆαααααΆααα ααΆα’αααΈααααΎαααΆααααααααΆαααΈαααΆαα½αααΉα Selenoid αα·ααα α’αΈααΆαααααα
ααΆαα’αα»ααααααΆααααα αΆαααΆααΆαααααΎαααΆα autotests αα
ααΎ threads α’αα»ααααΆαα±ααα’αααααΆαααααααααΆαααααΎααααΆααααααΆααα
α’αααααααΆααΆαα½αααΉαααααΎαααΆαααα’αααα»αα ααΌα
αααα’αΆα
ααΎαααΎαααΈααααΆα αα ααΆααααααΎααααααααααΆααα·αααΆααα
ααααΆααααααΎαααααΏαααααααααααΆαα
αααα»αααΆαααααΎαααααααααΎαααΆααααααα ααααααΆαααΆααααα ααΎαα’αΆα
ααααααααΆαααααΎαααααααααααααααααα·ααΆα 2 αα
αααα»αααΆααααααΎααααααα·ααΈ αααααΌααααΈααααΆαααααΎαααΆαα‘αΎααα·α 200 αααααα»ααααααααααα αα 5 ααΆααΈα ααΆα’αα»ααααΆαα±ααα’αααααα½αααΆαααα·αααααα’αα ααααΈαα½ααα α αΎαααααα·αααΎα
αΆαααΆα
α ααααΎααΆαααααΆααααααΌα α αΎαααααΎαααααααααααααααααααα
ααααα: www.habr.com