缘由

在做接口测试参数化方案的时候,已经在心里准备做这个服务来的

希望达到的目的

  1. 锻炼自己的能力--毕竟需要一个人做前后台什么的
  2. 提高接口测试脚本的可维护性

结构图

在 browser 里面编辑设计用例,测试套等,提交到 spring 服务端,然后入库
在 browser 里面执行任务时,由服务端读取用例,并调用 jenkins 服务,触发执行,完成后再调服务端存储结果
调试用例时,将结果存到 redis 中,方便上下文依赖的用例调试

基础

数据库

页面设计

针对的产品

我们是一家跨境电商公司,产品是类似淘宝的 app,所以主要是服务端的接口,供移动端调用。
平时大家也会抓包,然后在 postman 中改改数据测下接口的

简介

做的比较简单,目前也只完成了项目管理,用例新增,主要使用:

之前已经做好了库表设计

目前做好的部分

协议支持

  1. http --目前公司都这个啊,别的应该也没什么问题

pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jolly</groupId>
    <artifactId>mobile-test-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>mobile-test-service</name>
    <description>Mobile Test Service for Jolly</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <!--<version>1.5.9.RELEASE</version>-->
        <version>2.0.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <hadoop.version>2.3.2</hadoop.version>
        <java.version>1.8</java.version>
        <fastjson.version>1.2.40</fastjson.version>
        <druid.version>1.1.5</druid.version>

        <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
        <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20171018</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>

        <!--<dependency>-->
            <!--<groupId>com.alibaba</groupId>-->
            <!--<artifactId>druid</artifactId>-->
            <!--<version>${druid.version}</version>-->
        <!--</dependency>-->

        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-jdbc</artifactId>
            <version>${hadoop.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.httpcomponents</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.eclipse.jetty.aggregate</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.eclipse.jetty.orbit</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.mortbay.jetty</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.cloudera</groupId>
            <artifactId>hive-jdbc</artifactId>
            <version>2.5</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/libs/HiveJDBC4.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hive-service-cli</artifactId>
            <version>1.7.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/libs/TCLIServiceClient.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hive-ql</artifactId>
            <version>1.7.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/libs/ql.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

    </dependencies>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork><!-- 如果没有该项配置,devtools不会起作用,即应用不会restart -->
                </configuration>
            </plugin>

        </plugins>

        <resources>
            <resource>
                <directory>${project.basedir}/lib</directory>
                <targetPath>BOOT-INF/lib/</targetPath>
                <includes>
                    <include>**/*.jar</include>
                </includes>
            </resource>
        </resources>

    </build>

</project>

Bean

Mapper

Controller


由于页面不多就几个,所以总的分了两个类,一个处理页面请求,一个处理异步请求

sql connect

package com.jolly.mobiletestservice.configs;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.sql.SQLException;

@Configuration
@MapperScan(basePackages = {"com.jolly.mobiletestservice.mapper.autotestserver"}, sqlSessionTemplateRef = "autoTestServerSessionTemplateMysql")
public class AutoTestServerConnectConfig {

    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.mysql.autotestserver")
    public DataSourceProperties autoTestServerDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean(name = "autoTestServerDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.mysql.autotestserver")
    @Primary
    public DataSource testDataSource() {
        return autoTestServerDataSourceProperties().initializeDataSourceBuilder().build();
    }

    @Bean(name = "autoTestServerSqlSessionFactory")
    @Primary
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("autoTestServerDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }

    @Bean(name = "autoTestServerTransactionManager")
    @Primary
    public DataSourceTransactionManager testTransactionManager(@Qualifier("autoTestServerDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "autoTestServerSessionTemplateMysql")
    @Primary
    public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("autoTestServerSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

因为升级到 spring boot 2,数据库连接有变化,看了下官方文档,挺靠谱的

swagger 2

package com.jolly.mobiletestservice;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Swagger2 {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.jolly.mobiletestservice.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Spring Boot中使用Swagger2构建RESTful APIs")
                .description("移动端测试服务")
//                .termsOfServiceUrl("http://blog.didispace.com/")
                .contact(new Contact("clark", "https://testerhome.com/carl", "clark@jollycorp.com"))
                .version("1.0")
                .build();
    }

}

index

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/header :: header-js-css"></head>

<body class="nav-md">
<div class="container body">
    <div class="main_container">
        <div th:replace="fragments/left :: left"></div>

        <!-- top navigation -->
        <div th:replace="fragments/top :: top"></div>
        <!-- /top navigation -->

        <!-- page content -->
        <div class="right_col" role="main">
            <div class="container">
            </div>
        </div>
        <!-- /page content -->

        <!-- footer content -->
        <div th:replace="fragments/footer :: footer"></div>
        <!-- /footer content -->
    </div>
</div>

<div th:replace="fragments/header :: header-js"></div>

</body>
</html>

可以看到页面分了几块,left 一块,就是左边的手风琴,top 一块,就是有用户名的一块,footer 一块,然后引入的 js 和 css 各一块,
所以修改后面设计或修改的时候,就主要是对 page content 里面增加内容

用例新增


让用户上传一个 har 文件,然后服务端提取出需要的数据并按 json 格式展示,
用户修改下用例描述什么的,或需要增加断言的,可以调试并提交
可能比一个框一个框的写要快一些

感想

一堆基础的堆叠,一堆百度必应搜索,然后就出来了

后续计划

持续思考中

参考

开源计划

要等基本完成吧,大概还得一个月左右


↙↙↙阅读原文可查看相关链接,并与作者交流