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

[RU] Codegeneration as way to help test automation engeneers

[RU] Codegeneration as way to help test automation engeneers

Slides from Wrike's automation meetup

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 Магия генерации