Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[RU] Codegeneration as way to help test automat...

[RU] Codegeneration as way to help test automation engeneers

Slides from Wrike's automation meetup

Avatar for Merkushev Kirill

Merkushev Kirill

March 15, 2017
Tweet

More Decks by Merkushev Kirill

Other Decks in Programming

Transcript

  1. 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+ строк
 }

  2. 9 Задача: Поменять тип поля во множестве классов public class

    Meta { private long plannedDateTime; }
 public class Meta { private ZonedDateTime plannedDateTime; }

  3. 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"/> +
  4. 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
  5. 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()) ); // . . .
  6. 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();
  7. 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
  8. 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();
  9. 23 353 3048 4060 бины матчеры 1800 102 клиент LoC

    xml raml Необольшой проект
  10. 30 package com.example.helloworld; public final class HelloWorld { public static

    void main(String[] args) { System.out.println("Hello, World!"); } }
  11. 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
  12. 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}} }
  13. 34 Императивно Декларативно Сложные отношения в коде Когда: Важна читаемость

    результата Много логики в процессе генерации Когда: Исходник - плоская модель Нужно быстро
  14. 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; } Обработка
  15. 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"));
  16. 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
  17. 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 Магия генерации