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

Flash Talk: Documenting APIs with Spring REST Docs

Flash Talk: Documenting APIs with Spring REST Docs

Introduction to Spring REST Docs as a tool for test-driven approach to documentation.

Tomasz Kopczynski

February 21, 2017
Tweet

More Decks by Tomasz Kopczynski

Other Decks in Technology

Transcript

  1. ABOUT ME ▸ Tomasz Kopczyński (@t_kopczynski) ▸ Software developer at

    Sparkbit (@_sparkbit_) ▸ Open source contributor (Docker, Apache Camel, Spring REST Docs)
  2. I ALWAYS VALIDATE MY DOCUMENTATION AFTER EVERY CHANGE IN THE

    CODEBASE, I JUST LIKE DOING THAT. nobody, never
  3. INACCURATE DOCUMENTATION CAN LEAD TO… ▸ feeling that you project

    is abandoned ▸ users feeling lost when they don’t know how to use your software ▸ anger when executing documented actions but getting undocumented results ▸ waste of time when introducing a new developer to the project
  4. INTEGRATION TESTS TO THE RESCUE! ▸ API documentation ▸ Generate

    your request/response snippets while running your test suite ▸ Creating snippets from real calls has 100% accuracy guaranteed ▸ Rules: ▸ Fail the test when trying to document a non-existent parameter ▸ Fail the test when omitting a parameter in the documentation
  5. SPRING REST DOCS ▸ Calling HTTP endpoints: ▸ Spring MockMvc

    ▸ REST Assured ▸ Snippets: ▸ Asciidoctor ▸ Markdown
  6. SPRING REST DOCS TEST WITH MOCKMVC @Test public void responseCodeTest()

    throws Exception { this.mockMvc.perform( get("/cms/status") .accept(MediaType.APPLICATION_JSON) ) .andExpect(status().isOk()) .andDo( document("status") ); }
  7. SPRING REST DOCS TEST WITH MOCKMVC @Test public void responseCodeTest()

    throws Exception { this.mockMvc.perform( get("/cms/status") .accept(MediaType.APPLICATION_JSON) ) .andExpect(status().isOk()) .andDo( document("status") ); } Spring REST Docs entrypoint
  8. POM.XML CONFIGURATION - DEPENDENCIES <dependency> <groupId>org.springframework.restdocs</groupId> <artifactId>spring-restdocs-mockmvc</artifactId> <scope>test</scope> </dependency> <dependency>

    <groupId>org.springframework.restdocs</groupId> <artifactId>spring-restdocs-restassured</artifactId> <scope>test</scope> </dependency>
  9. POM.XML CONFIGURATION - ASCIIDOCTOR <plugin> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctor-maven-plugin</artifactId> <version>1.5.2</version> <executions> <execution>

    <id>generate-docs</id> <phase>prepare-package</phase> <goals> <goal>process-asciidoc</goal> </goals> <configuration> <backend>html</backend> <doctype>book</doctype> <attributes> <snippets>${snippetsDirectory}</snippets> </attributes> </configuration> </execution> </executions> </plugin>
  10. DOCUMENTING REQUEST PARAMS @Test public void retrieveDocumentTest() throws Exception {

    this.mockMvc.perform(get("/cms/document/{id}", 1L)) .andExpect(status().isOk()) .andDo(document("retrieveDocument", pathParameters( parameterWithName("id").description("Document's id") ) )); } ./cms/document/{id} |=== |Parameter|Description |`id` |Document's id |===
  11. DOCUMENTING RESPONSE FIELDS @Test public void retrieveDocumentTest() throws Exception {

    this.mockMvc.perform(get("/cms/document/{id}", 1L)) .andExpect(status().isOk()) .andDo(document("retrieveDocument", responseFields( fieldWithPath("author").description("Document's author"), fieldWithPath("title").description("Document's title") ) )); } |=== |Path|Type|Description |`author` |`String` |Document's author |`title` |`String` |Document's title |===
  12. DOCUMENTING A REQUEST ‣ curl: [source,bash] ---- $ curl 'http://localhost:8080/cms/document'

    -i -X POST -H 'Content-Type: application/json' -d '{"author":"Jack Tester","title":"Testing REST APIs"}' —— ‣ HTTP: [source,http,options="nowrap"] ---- POST /cms/document HTTP/1.1 Content-Type: application/json Host: localhost:8080 Content-Length: 52 {"author":"Jack Tester","title":"Testing REST APIs"} ----
  13. FORMATTING DOCUMENTATION IN ASCIIDOCTOR = CMS API documentation :doctype: book

    :icons: font :toc: == Retrieve a document by ID Request parameters: include::{snippets}/retrieveDocument/path-parameters.adoc[] curl request: include::{snippets}/retrieveDocument/curl-request.adoc[] HTTP response: include::{snippets}/retrieveDocument/http-response.adoc[] Response fields: include::{snippets}/retrieveDocument/response-fields.adoc[]
  14. WHAT’S COMING IN 1.2.0 ▸ Documenting request and response bodies

    and their subsections ▸ Additional snippets for documenting request and response structure ▸ Providing a default output directory for snippets based on the build tool ▸ Custom Asciidoctor macro that includes all snippets for a particular operation in one command