记一次使用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说明呢?

咱们将在下节中,给出阐述。

相关文章
相关标签/搜索