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
すこし踏み込む CancellationToken
htkym
0
320
個人開発基盤をまるごとCloudflareに引っ越して爆速で総合的体験を向上させた話
tinykitten
0
190
Everything will be SERVERLESS — 信じて運用した10年の経験値 / Everything Will be Serverless — Lessons Learned from 10 Years of Operational Experience
seike460
PRO
1
120
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
420
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
180
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
360
Snowflakeで業務アプリを作ろう。 Snowflakeのアプリ機能解説&実践ガイド
ayumu_yamaguchi
1
280
Security issues being discussed on Web Platforms
petamoriken
0
960
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
170
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
180
cdk deploy JawsSonic #MARATHONしながらAWSリソースをデプロイしてみよう
akihisaikeda
2
140
wkhtmltopdfの次どうするか問題2026
willnet
2
1.3k
Featured
See All Featured
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
Balancing Empowerment & Direction
lara
6
1.3k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
What's in a price? How to price your products and services
michaelherold
247
13k
Designing for Performance
lara
611
70k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.3k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
550
Paper Plane (Part 1)
katiecoart
PRO
2
11k
Six Lessons from altMBA
skipperchong
29
4.5k
Typedesign – Prime Four
hannesfritz
42
3.2k
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 руководитель группы автоматизации процессов разработки
и тестирования в Яндексе