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
180
[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
100
Your tests will ask you to repeat. Scallable Immutable Selenium Infrastructure.
lanwen
1
380
[RU] Codegeneration as way to help test automation engeneers
lanwen
0
95
Juseppe
lanwen
1
620
[RU] GIMME your first Autotest!
lanwen
1
430
SPb Jenkins Meetup #0 Как начать писать плагин для Jenkins? И когда этого не делать?
lanwen
3
750
Other Decks in Programming
See All in Programming
2026/02/04 AIキャラクター人格の実装論 口 調の模倣から、コンテキスト制御による 『思想』と『行動』の創発へ
sr2mg4
0
520
humanlayerのブログから学ぶ、良いCLAUDE.mdの書き方
tsukamoto1783
0
200
生成AIを使ったコードレビューで定性的に品質カバー
chiilog
1
300
24時間止められないシステムを守る-医療ITにおけるランサムウェア対策の実際
koukimiura
2
170
2026年 エンジニアリング自己学習法
yumechi
0
150
Automatic Grammar Agreementと Markdown Extended Attributes について
kishikawakatsumi
0
210
Python’s True Superpower
hynek
0
180
朝日新聞のデジタル版を支えるGoバックエンド ー価値ある情報をいち早く確実にお届けするために
junkiishida
1
180
CSC307 Lecture 06
javiergs
PRO
0
700
「ブロックテーマでは再現できない」は本当か?
inc2734
0
1.1k
atmaCup #23でAIコーディングを活用した話
ml_bear
3
590
[KNOTS 2026登壇資料]AIで拡張‧交差する プロダクト開発のプロセス および携わるメンバーの役割
hisatake
0
330
Featured
See All Featured
Ethics towards AI in product and experience design
skipperchong
2
210
A Tale of Four Properties
chriscoyier
162
24k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Testing 201, or: Great Expectations
jmmastey
46
8.1k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
1
300
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
200
YesSQL, Process and Tooling at Scale
rocio
174
15k
How to make the Groovebox
asonas
2
2k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
62
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
170
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
230
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 руководитель группы автоматизации процессов разработки
и тестирования в Яндексе