記一次使用Spring REST Docs + travis + github自動生成API接口文檔的操做步驟(上)

團隊開發中,文檔尤其重要。文檔的存大,大幅的下降了團隊間的無效溝通時間,使得每位成員便可以按本身的計劃開始工做,又能夠快速的獲取到其它隊員的支持。html

優秀的程序員從善於讀文檔開始,優秀的工程師從善於寫文檔開始。

在先後臺的開發中,接口是使先後臺進行關聯的關鍵一環,接口是否合理,清晰直接影響到團隊開發的效率和團隊間配置的心情(程序員每每都是自戀的壞脾氣)。而是否可以提供隨時更新的閱讀性強的文檔,則是先後臺開發中的重要一環。java

本文由0開始,記錄一次在實際項目中使用Spring REST Docs + travis + github自動生成API接口的實際操做過程。git

本文環境:
java:1.8 + maven:3.3 + spring-boot:2.0.3程序員

讀文檔

咱們一直堅信,官方的原文文檔確定是最好的。第一步,咱們來到了spring rest docs官方文檔,並參考其作如下操做:github

加入依賴

找到pom.xml加入如下依賴。IDEA會自動爲咱們導入依賴的包,其它的IDE,可能須要手動導入。web

<dependency> 
    <groupId>org.springframework.restdocs</groupId>
    <artifactId>spring-restdocs-mockmvc</artifactId>
    <version>2.0.1.RELEASE</version>
    <scope>test</scope>
</dependency>

<build>
    <plugins>
        <plugin> 
            <groupId>org.asciidoctor</groupId>
            <artifactId>asciidoctor-maven-plugin</artifactId>
            <version>1.5.3</version>
            <executions>
                <execution>
                    <id>generate-docs</id>
                    <phase>prepare-package</phase> 
                    <goals>
                        <goal>process-asciidoc</goal>
                    </goals>
                    <configuration>
                        <backend>html</backend>
                        <doctype>book</doctype>
                    </configuration>
                </execution>
            </executions>
            <dependencies>
                <dependency> 
                    <groupId>org.springframework.restdocs</groupId>
                    <artifactId>spring-restdocs-asciidoctor</artifactId>
                    <version>2.0.1.RELEASE</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

注意: dependency須要加入到dependencies中。若是你的pom.xml有了build-> plugins,則只須要複製plugin的部分到plugins 中。spring

如下代碼的做用以下:json

  1. Add a dependency on spring-restdocs-mockmvc in the test scope.
  2. Add the Asciidoctor plugin.
  3. Using prepare-package allows the documentation to be included in the package.

4.Add spring-restdocs-asciidoctor as a dependency of the Asciidoctor plugin. This will automatically configure the snippets attribute for use in your .adoc files to point to target/generated-snippets. It will also allow you to use the operation block macro.mvc

胡亂翻譯以下:app

  1. 爲測試域(只在測試時使用)添加了一個依賴。
  2. 添加了一個插件。
  3. 爲了插件正常工做,設置了一個屬性。
  4. 爲Asciidoctor添加了spring-restdocs-asciidoctor依賴。做用也是讓咱們正常使用這個插件。

可能會遇到的小坑:

  1. 粘貼上述代碼時,位置錯了。此時,須要按前面給的注意檢查,是否出現了嵌套錯誤。
  2. 提示spring-restdocs-asciidoctor:2.0.1.RELEASE未找到,這是因爲咱們本機的maven庫的索引太舊引發來。查看官網咱們得知,這個包的引入時間是Apr 4, 2018。此時,須要咱們從新下載maven的目錄。即update maven indices

在進行測試時生成相應的文檔

咱們在測試控制器時,會使用MockMVC來進行模擬數據的發送,這個模擬數據正好成爲了咱們須要展示在API接口部分的樣例。

這樣作的好處很明顯:

  1. 若是邏輯發生變化,咱們必然須要在C層中進行從新測試。從新測試時,就自動對文檔進行了更新。
  2. 咱們不須要再去維護另外一份單獨的API文檔了(好比在WORD中)。
  3. 自動生成的文檔,格式很是的規範,從而避免了人爲維護文檔出現的格式不統1、不規範、忘掉或是故意漏掉一些元素的狀況。

配置測試

好比,我如今有個測試的控制器是: DanWeiControllerTest(歷史緣由,請忽略命名)。爲了能夠統一地對全部的控制器測試進行自動文檔的設置,咱們在這再新建一個抽像類ControllerTest,並使用DanWeiControllerTest來繼續ControllerTest

ControllerTest

package com.mengyunzhi.check_apply_online.controller;

import org.junit.Before;
import org.junit.Rule;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.restdocs.JUnitRestDocumentation;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import javax.transaction.Transactional;

/**
 * 單元測試基類
 * @author panjie
 * www.mengyunzhi.com 河北工業大學夢雲智開發團隊
 */
@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
@AutoConfigureMockMvc
public abstract class ControllerTest {
    protected MockMvc mockMvc;

    @Autowired
    protected WebApplicationContext context;

    @Rule
    public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();

    @Before
    public void setUp() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
                .apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation))
                .build();
    }
}

DanWeiControllerTest進行繼承(未加入自動文檔)

package com.mengyunzhi.check_apply_online.controller;

import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

/**
 * 單位
 * @author panjie
 * www.mengyunzhi.com 河北工業大學夢雲智開發團隊
 */
public class DanWeiControllerTest extends ControllerTest{

    @Test
    public void registerTest() throws Exception {
        String url = "/DanWei/register";
        this.mockMvc.perform(MockMvcRequestBuilders
                .post(url)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content("{}"))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

自動生成文檔

加入自動生成文檔代碼後:

package com.mengyunzhi.check_apply_online.controller;

import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

/**
 * 單位測試
 * @author panjie
 * www.mengyunzhi.com 河北工業大學夢雲智開發團隊
 */
public class DanWeiControllerTest extends ControllerTest{

    @Test
    public void registerTest() throws Exception {
        String url = "/DanWei/register";
        this.mockMvc.perform(MockMvcRequestBuilders
                .post(url)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content("{}"))
                .andExpect(MockMvcResultMatchers.status().isOk())
        .andDo(MockMvcRestDocumentation.document("DanWei_register"));
    }
}

此時,咱們執行本單元測試時,將在target/generated-snippets中生成以下6個以.adoc結尾的文件:

clipboard.png

這6個文件中,記錄了不一樣請求方法的請求/返回信息。

拼接文件

咱們的單元測試請求越多,生成這樣的文件夾也就越多,下面,咱們共同將這些文件進行格式化,並拼接到一個html文件中。

src/main/asciidoc/建立一個任意名稱的.adoc文件,好比,咱們index.adoc。而後,使用.adocinclude語法,將上圖中生成的幾個測試代碼片斷包含進來。

src/main/asciidoc/index.adoc

include::{snippets}/DanWei_register/http-request.adoc[]
include::{snippets}/DanWei_register/request-body.adoc[]
include::{snippets}/DanWei_register/http-response.adoc[]
include::{snippets}/DanWei_register/response-body.adoc[]

生成HTML

當咱們進行package時,就會在target文件夾中生成generated-docs/index.html,點擊便可查看生成的文檔信息。

mvn package

clipboard.png

查看html以下:

clipboard.png

至此,咱們便成功的使用spring rest docs生成了html的API接口文檔。除了基本的功能之外,咱們還能夠對傳入的字段添加說明等。具體的細節,若是有需求,能夠查看Spring官方文檔

總結

咱們按照Spring官方文檔進行了相應的配置;接着在單位測試時,加入了指定生成文檔的目錄代碼,併成功的生成測試的代碼片斷;而後使用AsciiDoc語法,在index.adoc文件中,對測試代碼片斷進行了拼接;最後,使用mvn package在進行項目打包的同時,生成了咱們想的html文件。

不足
但咱們仍然感受這並不夠智能化,咱們在生成代碼片斷後,還須要手動的加入對代碼版本的引入;雖然有了代碼片斷,但對片斷中的請求json數據的解釋並不輕鬆(要參考官方文檔),最主要的是,在C層,咱們進行接收時,要麼是通常的參數,要麼是後臺的實體。咱們更但願可以對參數和實體進行更改時,測試的說明也可以同時更改。

那麼如何可以自動的實現代碼片斷的合併,而且按照參數和實體信息自動生成與後臺代碼高度吻合的API說明呢?

咱們將在下節中,給出闡述。

相關文章
相關標籤/搜索