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 in Java as way to solve aut...
Search
Merkushev Kirill
June 04, 2017
Programming
0
170
[RU] Codegeneration in Java as way to solve autotest problems
It was presented on Heisenbug 2017 (June) in Saint-Petersburg
Merkushev Kirill
June 04, 2017
Tweet
Share
More Decks by Merkushev Kirill
See All by Merkushev Kirill
Проект на Java и библиотеке Reactor - а как же тесты?
lanwen
0
94
Your tests will ask you to repeat. Scallable Immutable Selenium Infrastructure.
lanwen
1
340
[RU] Codegeneration as way to help test automation engeneers
lanwen
0
78
Juseppe
lanwen
1
550
[RU] GIMME your first Autotest!
lanwen
1
410
SPb Jenkins Meetup #0 Как начать писать плагин для Jenkins? И когда этого не делать?
lanwen
3
640
Other Decks in Programming
See All in Programming
Pythonでもちょっとリッチな見た目のアプリを設計してみる
ueponx
1
570
AWS Organizations で実現する、 マルチ AWS アカウントのルートユーザー管理からの脱却
atpons
0
150
Open source software: how to live long and go far
gaelvaroquaux
0
640
Flutter × Firebase Genkit で加速する生成 AI アプリ開発
coborinai
0
160
プログラミング言語学習のススメ / why-do-i-learn-programming-language
yashi8484
0
130
Conform を推す - Advocating for Conform
mizoguchicoji
3
690
Multi Step Form, Decentralized Autonomous Organization
pumpkiinbell
1
750
Amazon Bedrock Multi Agentsを試してきた
tm2
1
290
Pulsar2 を雰囲気で使ってみよう
anoken
0
240
社内フレームワークとその依存性解決 / in-house framework and its dependency management
vvakame
1
560
SwiftUIで単方向アーキテクチャを導入して得られた成果
takuyaosawa
0
270
GoとPHPのインターフェイスの違い
shimabox
2
190
Featured
See All Featured
Building an army of robots
kneath
303
45k
Visualization
eitanlees
146
15k
Done Done
chrislema
182
16k
A Modern Web Designer's Workflow
chriscoyier
693
190k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
33
2.8k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
175
51k
Why Our Code Smells
bkeepers
PRO
336
57k
Git: the NoSQL Database
bkeepers
PRO
427
64k
Navigating Team Friction
lara
183
15k
Reflections from 52 weeks, 52 projects
jeffersonlam
348
20k
Build The Right Thing And Hit Your Dates
maggiecrowley
34
2.5k
Transcript
Кодогенерация Кирилл Меркушев руководитель группы автоматизации процессов разработки и тестирования
в Яндексе
2 50%
3 Программировать Читать Сопровождать 50%
4 Поменяли шаблон = переписали сотни строк
5 Кодогенерация - это просто и очень полезно
6 5 причин попробовать
7 5 причин попробовать 2 способа сделать больше
8 5 причин попробовать 2 способа сделать больше Откуда дети
исходники
9 5 причин попробовать 2 способа сделать больше Откуда дети
исходники Процессор аннотаций
10 5 причин попробовать 2 способа сделать больше Откуда дети
исходники Процессор аннотаций Мавен плагин
11 * * для привлечения внимания Тестируем приложение «Полетели» lanwen/heisenbug17
- POST /ticket/ - GET /tickets/{uuid}
12 $ cloc Java 366
13 $ cloc 50459 (600 files) Яндекс Паспорт (500+ эндпоинтов,
400 объектов) 20730 (220 files) До После Java
14 Project Lombok projectlombok.org 1 Зависимость @Data аннотация
15 Project Lombok 1 … projectlombok.org
16 Project Lombok 1 Зависимость @Data аннотация IDE plugin projectlombok.org
17 Jsonschema2pojo 2 Plugin сборки Json joelittlejohn/jsonschema2pojo
18 { "flights": [{ "number": "<num>", "airline": "<code>", "departure": {}
}] } blog.qatools.ru/maven/json2pojo
19 Jsonschema2pojo 2 joelittlejohn/jsonschema2pojo …
20 Json-schema!
21 Json-schema! XSD (XML Schema)
22 JAXB/XJC 3 Plugin сборки XSD (XML Schema)
23 <plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifact> <configuration> <args> <arg>-Xxew</arg> <arg>-Xfluent-api</arg> </args> </configuration>
//. . . JAXB (демо)
24 <plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifact> <configuration> <args> <arg>-Xxew</arg> <arg>-Xfluent-api</arg> </args> </configuration>
//. . . JAXB (демо) Магия расширений
25 with-методы (fluent-builder) new UserMeta() .withLogin("Gandalf") .withLang("Syndarin") Immutable Builders toString/hashCode/equals
. . . x100500
26 Hamcrest Matchers 4 Конфиг Зависимость yandex-qatools/hamcrest-pojo-matcher-generator
27 По матчеру assertThat( someOwner, both(withEmail(containsString(«@»))) .and(withUid(is(uid)) ); в каждую
семью для email для uid java.lang.AssertionError: Expected: email a string containing «@» but: email was null полная свобода
28
29
30 rest-assured.io when().get("/info/{uid}", 5) .then().statusCode(200);
31 RARC 5 Plugin сборки RAML спецификация qameta/rarc
32 #%RAML 0.8 title: Tickets baseUri: https://api.example.com /ticket: /{uuid}: get:
displayName: fetch
33 #%RAML 0.8 title: Tickets baseUri: https://api.example.com /ticket: /{uuid}: get:
displayName: fetch ApiTickets.tickets(ticketsConfig()) .ticket() .uuid().withUuid("1") .fetch(identity()).prettyPeek();
34 #%RAML 0.8 title: Tickets baseUri: https://api.example.com /ticket: /{uuid}: get:
displayName: fetch ApiTickets.tickets(ticketsConfig()) .ticket() .uuid().withUuid("1") .fetch(identity()).prettyPeek();
35 #%RAML 0.8 title: Tickets baseUri: https://api.example.com /ticket: /{uuid}: get:
displayName: fetch ApiTickets.tickets(ticketsConfig()) .ticket() .uuid().withUuid("1") .fetch(identity()).prettyPeek();
36 #%RAML 0.8 title: Tickets baseUri: https://api.example.com /ticket: /{uuid}: get:
displayName: fetch ApiTickets.tickets(ticketsConfig()) .ticket() .uuid().withUuid("1") .fetch(identity()).prettyPeek();
37 $ cloc Java 16 XSD 56 72 366 vs
38 Подводные камни
39 Почему не kotlin/groovy/ scala/go … ?
40 Почему не kotlin/ groovy/scala/go … ? Нельзя!
41 Почему не kotlin/ groovy/scala/go … ? Нельзя! Уже есть
схема
42 Почему не kotlin/ groovy/scala/go … ? Нельзя! Уже есть
схема Кодогенерация - не только про бины
43 Почему не kotlin/ groovy/scala/go … ? Нельзя! Уже есть
схема Кодогенерация - не только про бины lanwen/heisenbug17
44 Тонкая настройка?
45 <xs:element name="plannedDateTime" type="xs:dateTime"/> Схема «Биндинги»
46 «Биндинги» Wat? Схема <xs:element name="plannedDateTime" type="xs:dateTime"/>
47 «Биндинги» @XmlJavaTypeAdapter(Adapter1 .class) @XmlSchemaType(name = "dateTime") protected ZonedDateTime plannedDateTime;
<xs:element name="plannedDateTime" type="xs:dateTime"/> Схема Результат
48 «Биндинги» <jaxb:globalBindings> ... <jaxb:javaType name="java.time.ZonedDateTime" xmlType="xs:dateTime" parseMethod="Adapter.parse" printMethod="Adapter.print"/> </jaxb:globalBindings>
bindings.xjb
49 Программирование на xml/json/yaml?
50 Программирование на xml/json/yaml? Нет логики
51 Программирование на xml/json/yaml? Нет логики Протокол (доки, микросервисы)
52 Программирование на xml/json/yaml? Нет логики Протокол (доки, микросервисы) Как
список покупок
53 Кодогенерация - это просто и очень полезно
54 2 Задачи
55 2 2 + Задачи Решения
56 2 2 + + 2 Задачи Решения Слайда
57 Тестовые методы списком констант public final class TestMethodConsts {
psf String TEST_METHOD_shouldCreate = "ru.lanwen.heisenbug.EticketResourceTest#shouldCreate"; } КОНСТАНТА = "полный.референс#метода"
58 Генерация кода Написание исходников
59 Генерация кода Написание исходников 1
60 Написание исходников StringBuilder 1
61 Написание исходников StringBuilder square/javapoet jknack/handlebars.java 1
62 public final class TestMethodConsts { public static final String
TEST_METHOD_shouldCreate = "ru.lanwen.heisenbug.ETest#shouldCreate"; }
63 square/javapoet FieldSpec.builder( ClassName.get(String.class), key, PUBLIC, STATIC, FINAL ).initializer("$S", value)
.build()
64 square/javapoet FieldSpec.builder( ClassName.get(String.class), key, PUBLIC, STATIC, FINAL ).initializer("$S", value)
.build() Поле
65 square/javapoet FieldSpec.builder( ClassName.get(String.class), key, PUBLIC, STATIC, FINAL ).initializer("$S", value)
.build() Тип, имя и модификаторы
66 square/javapoet FieldSpec.builder( ClassName.get(String.class), key, PUBLIC, STATIC, FINAL ).initializer("$S", value)
.build() Значение
67 jknack/handlebars.java template.apply( Context.newContext() .data("package", pkg) .data("class", className) .data("consts", consts.entrySet()),
writer );
68 Только модель template.apply( Context.newContext() .data("package", pkg) .data("class", className) .data("consts",
consts.entrySet()), writer ); jknack/handlebars.java
69 Генерация кода Написание исходников 1 2
70 Кодогенерация Sed, bash 2
71 Кодогенерация Sed, bash 2 Annotation Processing Maven, Gradle
72 abstract class AbstractProcessor { } Процессор аннотаций
73 MatcherFactoryGenerator extends AbstractProcessor Процессор аннотаций
74 @SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes({"your.awesome.Annotation"}) public class MatcherFactoryGenerator extends AbstractProcessor { }
Процессор аннотаций
75 @SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes({"your.awesome.Annotation"}) public class MatcherFactoryGenerator extends AbstractProcessor { }
resources/META-INF/services/ javax.annotation.processing.Processor Процессор аннотаций FQCN
76 Тесты! E2E unit-тесты Отдельный модуль google/compile-testing
77 Compilation compilation = javac() .withProcessors(new MyAnnotationProcessor()) .compile(JavaFileObjects.forResource("HelloWorld.java")); assertThat(compilation).succeeded(); Тесты!
unit-тесты google/compile-testing
78 public final class Project { public static final String
VERSION = "1.0.0"; } Версия проекта константой
79 Maven plugin public class AbstractMojo { } bit.ly/mvn-plugin-dev
80 Maven plugin RestClientGenerateMojo extends AbstractMojo { } bit.ly/mvn-plugin-dev
81 Maven plugin @Mojo( name = "generate-client", defaultPhase = LifecyclePhase.GENERATE_SOURCES
) @Execute(goal = "generate-client") public class RestClientGenerateMojo extends AbstractMojo { } bit.ly/mvn-plugin-dev
82 @Parameter( required = true, readonly = true, defaultValue =
"${project}" ) private MavenProject project; Знания мавена Maven plugin bit.ly/mvn-plugin-dev
83 . . . private MavenProject project; @Override public void
execute() { new Codegen().generate(); project.addCompileSourceRoot(outputDir); } Магия генерации Maven plugin bit.ly/mvn-plugin-dev
84 Кодогенерируй!
85 Итого
86 Огромное количество готовых инструментов lanwen/heisenbug17 Project Lombok 1 Jsonschema2pojo
2 JAXB/XJC 3 Hamcrest Matchers 4 RARC 5
87 Огромное количество готовых инструментов lanwen/heisenbug17 Есть слабые стороны, при
большой выгоде
88 Огромное количество готовых инструментов lanwen/heisenbug17 Хватит это терпеть писать
toString/equals вручную! Есть слабые стороны, при большой выгоде
89 Спасибо Меркушев Кирилл lanwen руководитель группы автоматизации процессов разработки
и тестирования в Яндексе