jck28-lucio-数据库操作与断言

接口测试响应验证

如何在测试过程中验证接口没有 Bug?

  1. 通过接口响应值
  2. 通过查询数据库信息辅助验证

接口测试数据清理

自动化测试过程中,会产生大量的脏数据,如何处理?

  • 通过 Delete 接口删除
  • 自动化测试使用干净的测试环境,每次自动化测试执行完成之前或之后做数据还原

数据库操作注意事项

直接对数据库做查询之外的操作是非常危险的行为

  • 权限管理严格的公司数据库权限给的非常低
  • 表结构复杂,随便删除数据会影响测试,甚至会导致系统出现异常

接口自动化测试常用的数据库操作

  • Python 技术栈:章节《常用第三方库pymsql》
  • Java 技术栈:《常用标准库:数据库操作-JDBC》

接口自动化测试常用的数据库操作

  1. 连接与配置 2. 查询数据与断言
  • Python 技术栈:章节《常用第三方库pymsql》
  • Java 技术栈:《常用标准库:数据库操作-JDBC》

数据库信息

注意:只有查询权限

数据库封装

创建一个工具类,输入SQL,返回查询结果

mysql mysql-connector-java 8.0.30
public class DatabaseUtils {
    Statement statement;
    Connection conn;
    // 初始化数据库信息
    public DatabaseUtils(String DB_URL, String USER, String PASS) {
        try {
            Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
            statement = conn.createStatement();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    // 根据 sql 返回在数据库查询的信息
    public List<String> getResultStringListBySQL(String sql_query, String columnLabel){
        List<String> resList = new ArrayList<>();
        try {
            ResultSet resultSet = statement.executeQuery(sql_query);
            while (resultSet.next()){
            resList.add(resultSet.getString(columnLabel));
            }
        }catch (SQLException e) {
            e.printStackTrace();
        }
        return resList;
    }
}

数据库结合断言优化

  1. 查询 litemall 数据库返回的数据
  2. 辅助完成断言
public class DatabaseTest {
    static final String DB_URL = "jdbc:mysql://litemall.hogwarts.ceshiren.com:13306/litemall?useSSL=false";
    static final String USER = "test";
    static final String PASS = "test123456";
    static final String QUERY = "select * from litemall_cart where user_id=1 and deleted=0";
    @Test
    void getDataBySql()  {
        // 初始化数据库工具类
        DatabaseUtils databaseUtils = new DatabaseUtils(DB_URL, USER, PASS);
        // 提取查询结果中所有的goods_name
        List<String> dataResult = databaseUtils.getResultStringListBySQL(QUERY, "goods_name");
        // 断言数据库数据是否包含hogwarts
        assertTrue(dataResult.contains("hogwarts"));
    }
    }

数据库封装-优化(选修)

  • 问题: 数据库查询的信息,不一定所有的信息返回的类型都是String,封装的工具类不够通用
  • 解决方案:优化工具类,把查询到的所有数据集转换成一个json结构体,使用JsonPath把对应的信息获取到。
<dependency>
    <groupId>org.jooq</groupId>
    <artifactId>jooq</artifactId>
    <version>3.11.11</version>
</dependency>
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.6.0</version>
    <scope>test</scope>
</dependency>
public class DatabaseUtils {
    Statement statement;
    Connection conn;

    public DatabaseUtils(String DB_URL, String USER, String PASS) {
        try {
            Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
            statement = conn.createStatement();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public String getResultSetBySQL(String sql_query) {
        // 格式转换将ResultSet 转换为 标准的json格式,方便完成断言。
        try {
            ResultSet resultSet = statement.executeQuery(sql_query);
            // 获取所有
            ResultSetMetaData md = resultSet.getMetaData();
            int numCols = md.getColumnCount();
            // 获取所有的数据表列名
            List<String> colNames = new ArrayList<>();
            for (int i = 1; i <= numCols; i++) {
                String name = md.getColumnName(i);
                colNames.add(name);
            }
            // 返回一个json结构的查询结果
            return DSL.using(conn)
                    .fetch(resultSet)
                    .map(new RecordMapper() {
                        @Override
                        public JSONObject map(Record r) {
                            JSONObject obj = new JSONObject();
                            colNames.forEach(cn -> obj.put(cn, r.get(cn)));
                            return obj;
                        }
                    }).toString();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        // 如果异常,return 空 json,不影响后续逻辑执行
        return "{}";
    }
}