Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
[RU] Codegeneration as way to help test automat...
Search
Merkushev Kirill
March 15, 2017
Programming
0
85
[RU] Codegeneration as way to help test automation engeneers
Slides from Wrike's automation meetup
Merkushev Kirill
March 15, 2017
Tweet
Share
More Decks by Merkushev Kirill
See All by Merkushev Kirill
Проект на Java и библиотеке Reactor - а как же тесты?
lanwen
0
100
Your tests will ask you to repeat. Scallable Immutable Selenium Infrastructure.
lanwen
1
360
[RU] Codegeneration in Java as way to solve autotest problems
lanwen
0
180
Juseppe
lanwen
1
600
[RU] GIMME your first Autotest!
lanwen
1
410
SPb Jenkins Meetup #0 Как начать писать плагин для Jenkins? И когда этого не делать?
lanwen
3
710
Other Decks in Programming
See All in Programming
Developer Joy - The New Paradigm
hollycummins
1
330
CSC509 Lecture 08
javiergs
PRO
0
230
3年ぶりにコードを書いた元CTOが Claude Codeと30分でMVPを作った話
maikokojima
0
610
One Enishi After Another
snoozer05
PRO
0
150
CSC509 Lecture 07
javiergs
PRO
0
240
Catch Up: Go Style Guide Update
andpad
0
240
Writing Better Go: Lessons from 10 Code Reviews
konradreiche
3
5.5k
CSC305 Lecture 10
javiergs
PRO
0
220
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
120
その面倒な作業、「Dart」にやらせませんか? Flutter開発者のための業務効率化
yordgenome03
1
140
なぜGoのジェネリクスはこの形なのか? - Featherweight Goが明かす設計の核心
qualiarts
0
230
NixOS + Kubernetesで構築する自宅サーバーのすべて
ichi_h3
0
1.1k
Featured
See All Featured
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
285
14k
Designing for humans not robots
tammielis
254
26k
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.6k
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
990
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
127
54k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Six Lessons from altMBA
skipperchong
29
4k
Typedesign – Prime Four
hannesfritz
42
2.8k
Into the Great Unknown - MozCon
thekraken
40
2.1k
Transcript
Кодогенерация Меркушев Кирилл как способ решения проблем автоматизатора руководитель группы
автоматизации процессов разработки и тестирования в Яндексе
2 Что искать Куда копать Как копать
3 Что искать Куда копать Как копать
4 Задача: Написать ряд классов для передачи данных public class
UserMeta { private String lang; private String login; }
5 <plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifact> </plugin> JAXB
6 <xs:complexType name="UserMeta"> <xs:sequence> <xs:element name="lang" type="xs:string"/> <xs:element name="login" type="xs:string"/>
</xs:sequence> </xs:complexType> public class UserMeta implements Serializable { private String lang; private String login; // 150+ строк }
7 <plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifact> <configuration> <args> <arg>-Xxew</arg> <arg>-Xfluent-api</arg> </args> </configuration>
//. . . JAXB Магия расширений
8 with-методы (fluent-builder) new UserMeta() .withLogin("Gandalf") .withLang("Syndarin") Immutable Builders toString/hashCode/equals
. . . x100500
9 Задача: Поменять тип поля во множестве классов public class
Meta { private long plannedDateTime; } public class Meta { private ZonedDateTime plannedDateTime; }
10 «Биндинги» <jaxb:globalBindings> <xjc:serializable uid="271283517"/> <jaxb:javaType name="java.time.ZonedDateTime" xmlType="xs:dateTime" parseMethod="Adapter.parse" printMethod="Adapter.print"/>
</jaxb:globalBindings> @XmlJavaTypeAdapter(Adapter1 .class) @XmlSchemaType(name = "dateTime") protected ZonedDateTime plannedDateTime; <xs:element name="plannedDateTime" type="xs:dateTime"/> +
11 <plugin> <groupId>org.jsonschema2pojo</groupId> <artifactId>jsonschema2pojo-maven-plugin</artifactId> </plugin> Jsonschema2pojo joelittlejohn/jsonschema2pojo
12 { "bounce": { "final-recipient": "<email>", "status": "<code>", "type": "failed"
} } blog.qatools.ru/maven/json2pojo
13 Задача: Во множестве объектов проверить значения полей
14 По матчеру assertThat( someOwner, both(withEmail(containsString(«@»))).and(withUid(is(uid)) ); в каждую семью
для email для uid java.lang.AssertionError: Expected: email a string containing "mylogin" but: email was null
15 <dependency> <groupId>ru.yandex.qatools.processors</groupId> <artifactId>feature-matcher-generator</artifactId> <scope>provided</scope> </dependency> yandex-qatools/hamcrest-pojo-matcher-generator
16 Задача: Выполнять HTTP запросы для тестов
17 HttpClient client = new DefaultHttpClient(); HttpPost post = new
HttpPost("http://restUrl"); List nameValuePairs = new ArrayList(1); nameValuePairs.add(new BasicNameValuePair("name", «value")); post.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = client.execute(post); BufferedReader rd = new BufferedReader( new InputStreamReader(response.getEntity().getContent()) ); // . . .
18 rest-assured.io when().get("/info/{uid}", 5) .then().statusCode(200);
19 String value = when().get("/info/{uid}", 5) .setBasePath(«…») .spec(specification) .body(object) .param(«q»,
«1») .param(«q2», «2») .param(«q3», «3») .then().statusCode(200).extract().asString();
20 Rest-Assured RAML Codegen <plugin> <groupId>ru.lanwen.raml</groupId> <artifactId>rarc-maven-plugin</artifactId> <executions> <execution> <goals>
<goal>generate-client</goal> </goals> <configuration> <basePackage>ru.lanwen.raml.test</basePackage> </configuration> </execution> </executions> </plugin> qameta/rarc
21 #%RAML 0.8 title: Example baseUri: https://api.example.com /info: is: [authorized-by-token]
get: displayName: fetch description: Fetch list queryParameters: uid: ApiExample.example(exampleConfig()) .rpcApi() .info().withUid("1") .fetch(identity()).prettyPeek();
22 Что искать Куда копать Как копать
23 353 3048 4060 бины матчеры 1800 102 клиент LoC
xml raml Необольшой проект
24 Java - Go - Python - Java xml, json
- протокол
25 автоматизация - не только в тестах
26 Что искать Куда копать Как копать
27 Пишет код Стартует процесс
28 Пишет код Императивно Декларативно
29 Пишет код Императивно Декларативно square/javapoet jknack/handlebars.java
30 package com.example.helloworld; public final class HelloWorld { public static
void main(String[] args) { System.out.println("Hello, World!"); } }
31 MethodSpec main = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(void.class) .addParameter(String[].class, "args")
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") .build(); TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addMethod(main) .build(); square/javapoet
32 jknack/handlebars.java package {{package_name}}; public final class {{class_name}} { {{#methods}}
public static void {{name}}({{arg_type}} arg) { System.out.println("Hello, World!"); } {{/methods}} }
33 Императивно Декларативно Сложные отношения в коде Когда: Важна читаемость
результата Много логики в процессе генерации
34 Императивно Декларативно Сложные отношения в коде Когда: Важна читаемость
результата Много логики в процессе генерации Когда: Исходник - плоская модель Нужно быстро
35 Стартует процесс Annotation Processors Расширения билд-системы maven, gradle core
java
36 @SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes({«fqpn.AnnoClassName»}) public class MatcherFactoryGenerator extends AbstractProcessor { }
resources/META-INF/services/javax.annotation.processing.Processor 1 Процессор аннотаций FQCN
37 2 Процессор аннотаций @Override public boolean process(Set<? extends TypeElement>
annotations, RoundEnvironment roundEnv) { for (TypeElement annotation : annotations) { roundEnv.getElementsAnnotatedWith(annotation) .stream() .filter(isEntryWithParentPackageElement()) .map(Proc::asCode) .map(ClassSpecDescription::asJavaFile) .forEach(write(processingEnv)); } return false; } Обработка
38 Тестируемся E2E unit-тесты Отдельный модуль google/compile-testing
39 Тестируемся unit-тесты google/compile-testing Compilation compilation = javac() .withProcessors(new MyAnnotationProcessor())
.compile(JavaFileObjects.forResource(«HelloWorld.java»)); assertThat(compilation).succeeded(); assertThat(compilation) .generatedSourceFile("GeneratedHelloWorld") .hasSourceEquivalentTo(JavaFileObjects.forResource("GeneratedHelloWorld.java"));
40 1 Maven plugin @Mojo(name = "generate-client", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
@Execute(goal = "generate-client") public class RestAssuredClientGenerateMojo extends AbstractMojo { } bit.ly/mvn-plugin-dev
41 2 Maven plugin @Parameter(required = true, readonly = true,
defaultValue = "${project}") private MavenProject project; @Override public void execute() throws MojoExecutionException, MojoFailureException { new Codegen().generate(); project.addCompileSourceRoot(outputDir); } bit.ly/mvn-plugin-dev Магия генерации
42 Что искать Куда копать Как копать
43 Спасибо Меркушев Кирилл lanwen руководитель группы автоматизации процессов разработки
и тестирования в Яндексе