前些日子公司打算开发一个集成各种管理功能的大平台,让我负责测试相关服务的开发。首次重任,着实让我这阵子忙成了狗。上周终于立项完成了,本周正式进入开发阶段,大致需求如下:

  • 测试账号管理
  • 公共数据管理
  • 测试用例管理
  • 测试用例集合管理
  • 测试用例运行结果报告

大概这五大块功能,由于很多之前学过一点的springboot的只是也忘记的差不多了,提前复习了一下。果然发现很多知识点学的时候不精通,有些深一点的难点,以前都没有考虑到。

幸好我提前准备了,不然10天真就不一定能弄完。本身平台是Python开发的,有单独的前端工程师。开发用的moco功能也是前端mockJS做的,然后后端做兼容处理。测试服务也得去解析这个mockJS的数据,以前没咋接触过,心里有点慌。

公共数据管理是测试用例中需要一些公共参数和公共header里面的简单参数,这个比较简单,数据完全是我处理和存储,所以先准备开发了。下面分享一些这方面的需求和技术实现。

需求原型图

接口的mock文档

充电内容

这个基本功能的开发比较简单,其中一个如何存储公共数据,本来我设计的整个公共数据作为一个json对象,可惜被否了,因为这块的公共数据会被导入到接口的参数和Header中,要与mockJS的数据格式一致,所以存储成一个array的形式,每一行取textvaluetype默认都是string类型,所以这里不用传了。这里遇到一个问题:接口请求映射对象属性设置如下:

class PubDataBean extends AbstractBean {

    private static final long serialVersionUID = 8754205931721071606L;

    int id

    @Range(min = 1L, max = 5L, message = "环境设置错误")
    int envId

    @Min(value = 1L)
    int uid

    @NotNull(message = "公共数据不能为空")
    @Size(min = 1, message = "数据长度错误")
    List<PubDataDetailBean> list

    @Length(min = 1, max = 16, message = "名字长度错误")
    String name

}

用于存放公共数据的属性list的类型是List<PubDataDetailBean> list,如何把非基础数据类型对象和数据库中的字段对应起来,这里我充了一会儿电,发现了解决的办法:自定义一个BaseTypeHandler即可,把泛型具体化一下即可,这里常用的到mysql类型转化类还有一个JSonobjecttypehandler,一并分享了:

ListPubDetailHandler

package com.okay.family.common.typehandler;

import com.alibaba.fastjson.JSON;
import com.okay.family.common.basedata.OkayConstant;
import com.okay.family.common.bean.pubdata.PubDataDetailBean;
import com.okay.family.fun.config.Constant;
import com.okay.family.fun.utils.Join;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@MappedTypes(com.okay.family.common.bean.pubdata.PubDataDetailBean.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ListPubDetailHandler extends BaseTypeHandler<List<PubDataDetailBean>> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<PubDataDetailBean> parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, Join.join(parameter, OkayConstant.MYSQL_SEPARATE));
    }

    @Override
    public List<PubDataDetailBean> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String str = rs.getString(columnName);
        if (null != str) {
            List<String> beans = Arrays.asList(str.split(OkayConstant.MYSQL_SEPARATE));
            return beans.stream().map(x -> JSON.parseObject(x, PubDataDetailBean.class)).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public List<PubDataDetailBean> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String str = rs.getString(columnIndex);
        if (null != str) {
            List<String> beans = Arrays.asList(str.split(Constant.PART));
            return beans.stream().map(x -> JSON.parseObject(x, PubDataDetailBean.class)).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public List<PubDataDetailBean> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String str = cs.getString(columnIndex);
        if (null != str) {
            List<String> beans = Arrays.asList(str.split(Constant.PART));
            return beans.stream().map(x -> JSON.parseObject(x, PubDataDetailBean.class)).collect(Collectors.toList());
        }
        return null;
    }


}

JsonHandler

package com.okay.family.common.typehandler;

import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @description 用以mysql中json格式的字段,进行转换的自定义转换器,转换为实体类的JSONObject属性
 */
@MappedTypes(JSONObject.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class JsonHandler extends BaseTypeHandler<JSONObject> {

    /**
     * 设置非空参数
     *
     * @param ps
     * @param i
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, String.valueOf(parameter.toJSONString()));
    }

    /**
     * 根据列名,获取可以为空的结果
     *
     * @param rs
     * @param columnName
     * @return
     * @throws SQLException
     */
    @Override
    public JSONObject getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String sqlJson = rs.getString(columnName);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }

    /**
     * 根据列索引,获取可以为空的结果
     *
     * @param rs
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @Override
    public JSONObject getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String sqlJson = rs.getString(columnIndex);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }

    @Override
    public JSONObject getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String sqlJson = cs.getString(columnIndex);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }


}

mapper.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.okay.family.mapper.PubDataMapper">

    <sql id="table">
        qa_pub_data
    </sql>

    <resultMap id="entityMap" type="com.alibaba.fastjson.JSONObject">
        <!-- 实体类的json字段,typeHandler指定自定义的typeHandler -->
        <result column="list" property="pubdata" typeHandler="com.okay.family.common.typehandler.JsonHandler"/>
    </resultMap>

    <resultMap type="com.okay.family.common.bean.pubdata.PubDataBean" id="PubDataBean">
        <result property="id" column="id"/>
        <result property="uid" column="uid"/>
        <result property="envId" column="envId"/>
        <result property="name" column="name"/>
        <result property="list" column="list" typeHandler="com.okay.family.common.typehandler.ListPubDetailHandler"/>
    </resultMap>

    <select id="getAllDatas" parameterType="java.lang.Integer" resultMap="PubDataBean">
        select * from
        <include refid="table"/>
        where uid = #{0}
    </select>

    <select id="getDatasByEnv" resultMap="PubDataBean">
        select * from
        <include refid="table"/>
        where uid = #{arg0} and envId = #{arg1}
    </select>

    <update id="updateDataAttribute" parameterType="com.okay.family.common.bean.pubdata.EditPubBean">
        UPDATE
        <include refid="table"/>
        SET
        name=#{name}
        WHERE id=#{id} and uid = #{uid}
    </update>


    <update id="saveData" parameterType="com.okay.family.common.bean.pubdata.SavePubDataBean">
        UPDATE
        <include refid="table"/>
        SET
        list=#{list,jdbcType=OTHER,typeHandler=com.okay.family.common.typehandler.ListPubDetailHandler}
        WHERE id=#{id} AND uid=#{uid}
    </update>


    <insert id="add" useGeneratedKeys="true" keyProperty="id" parameterType="com.okay.family.common.bean.pubdata.EditPubBean">
        INSERT INTO
        <include refid="table"/>
        (uid,name,envId)
        VALUES
        (#{uid},#{name},#{envId})
    </insert>

    <delete id="delData" parameterType="com.okay.family.common.bean.pubdata.EditPubBean">
        delete from
        <include refid="table"/>
        where id = #{id} and uid = #{uid}
    </delete>

</mapper>

当然还有一些不足和待优化的地方,以后继续改进吧。