Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
[RU] Codegeneration in Java as way to solve aut...
Search
Merkushev Kirill
June 04, 2017
Programming
210
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
[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
More Decks by Merkushev Kirill
See All by Merkushev Kirill
Проект на Java и библиотеке Reactor - а как же тесты?
lanwen
0
120
Your tests will ask you to repeat. Scallable Immutable Selenium Infrastructure.
lanwen
1
420
[RU] Codegeneration as way to help test automation engeneers
lanwen
0
120
Juseppe
lanwen
1
670
[RU] GIMME your first Autotest!
lanwen
1
450
SPb Jenkins Meetup #0 Как начать писать плагин для Jenkins? И когда этого не делать?
lanwen
3
790
Other Decks in Programming
See All in Programming
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
550
Turning Architecture into Unit Tests in the AI Era (NSSpain XIV)
steliosf
PRO
1
130
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
190
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
1
2.2k
Workers Cache を知る
syumai
0
340
Everything will be SERVERLESS — 信じて運用した10年の経験値 / Everything Will be Serverless — Lessons Learned from 10 Years of Operational Experience
seike460
PRO
1
780
パーソナライズPodcastを作った話
repunit11
0
120
setup-vp GitLab対応の裏側
naokihaba
0
150
仕様駆動開発による爆速プロダクト開発 / Bakusoku Spec Driven Development
kobakei
0
200
AWS CDKのカスタムリソースでContinuum(旧Security Agent)を実装した話 | Implementing Continuum (formerly Security Agent) via AWS CDK Custom Resource
akihisaikeda
2
140
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
360
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.5k
Featured
See All Featured
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.5k
A designer walks into a library…
pauljervisheath
211
25k
Build your cross-platform service in a week with App Engine
jlugia
234
19k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
440
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Odyssey Design
rkendrick25
PRO
2
860
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
490
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
480
Crafting Experiences
bethany
1
370
Automating Front-end Workflow
addyosmani
1369
210k
The Curious Case for Waylosing
cassininazir
1
560
Writing Fast Ruby
sferik
630
63k
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 руководитель группы автоматизации процессов разработки
и тестирования в Яндексе