其他测试框架 接口自动化思路

米阳MeYoung · 2015年05月25日 · 最后由 zap 回复于 2019年07月22日 · 3447 次阅读

写在开头: 技术渣做接口自动化,大神们请轻喷!多提提优化方案和问题点。

以前做接口测试一直通过 postman 和 soapUI 来做,Postman 是 Chrome 的一个插件 Case 多了不好管理,同时执行起来麻烦,得一个一个去点击执行,平时做调试可以用用真正用来做接口自动化不合适。
SoapUI(改名叫 Ready! API)是个不错的工具,同时支持了 soap 类型和 rest 类型的接口,而且还支持安全,性能等测试,当然它是个商业工具,高级功能都是需要收费的,想那啥也是可以的,但是工具提供了方便同样可扩展性差了点,而且我经常遇到莫名其妙的工具问题,也许是因为我用的是那啥版本,稳定性差吧。
也是有人直接用 Jmeter 或者 loadrunner 来做接口自动化的,当然也是行的当用例管理上也是较为麻烦,有个框架 robot framework,关键字驱动来做接口也是一朋友一再推荐的做法,可惜我对 python 不熟悉,尽管上手容易我还是放弃。
现在我改用这么一套思路在做,因为目前我的接口协议都是 http 的,我就干脆直接用 java 的 HttpClient,然后接口返回是 json 格式,我就引入了 json-lib 来方便解析获取,同样因为需要跟数据库交互所以又引入了 MyBatis,同时用例还是沿用 TestNG ,为了更方便管理接口(地址,路径,参数等等)又通过 excel 来管理接口,通过 excel 来驱动测试。 这样下来整个项目就涉及了 httpclient+json+mybaits+testng+poi(excel)+log4j 等框架包。

在这过程做了一些封装一些主要代码如下:
对 httpclient 封装,只要把接口的完整请求传进来如果请求正常,就会 return 的接口返回的 json:

public static JSON getAPI(URI uri) throws URISyntaxException, IOException {

        CloseableHttpClient httpclient = HttpClients.createDefault();

        try {
            httpget = new HttpGet(uri);
            log.info("执行API请求" + httpget.getRequestLine());
            ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
                public String handleResponse(
                        final HttpResponse response) throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        return entity != null ? EntityUtils.toString(entity) : null;
                    } else {
                        log.error("请求错误,状态码为:"+response.getStatusLine().getStatusCode());
                        throw new ClientProtocolException("意外的状态返回: " + status);
                    }
                }
            };
            String responseBody = httpclient.execute(httpget, responseHandler);
            JSONObject dataObject = JSONObject.fromObject(responseBody);
            return dataObject;
        } finally {
            httpclient.close();
        }

    }     

那请求可以发起了,接口 URL 怎么来? 刚说通过 excel 来管理接口了,例如我新建了下面这么个文件:

TID 用来标识我需要读取哪行数据,TName 仅仅做说明这个接口是什么接口,Method 来表示接口是什么类型,根据不同类型做调用不同的 httpclient 封装方法,然后后面就是去拼接接口的 URL:
拼接 URL 的关键代码如下:


 /**
     * 请求链接拼接
     *
     * @param tid        哪一行的excel数据
     * @param parameters 参数
     * @return uri
     */
    public static URI returnURI(String tid, String... parameters) {
        String path = System.getProperty("user.dir") + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + "excel" + File.separator + "api.xls";
        ExcelEngine.filepath = path;
        ExcelEngine.sheetname = "api";
        // 从excel 拿数据
        List apiData = getApiData(tid);
        String getorpost = ((String) apiData.get(2)).toLowerCase();
//        System.out.println(getorpost);
        String scheme = (String) apiData.get(3);
        String apiHost = (String) apiData.get(4);
        String apiPath = (String) apiData.get(5);
        // URI 拼接
        StringBuffer stringBuffer = new StringBuffer(scheme + "://" + apiHost + apiPath + "?");
        HashMap<String, String> hashmap = new HashMap();
        int p = 0;
        while (p < parameters.length) {
            hashmap.put((String) apiData.get(p + 6), parameters[p]);
            p = p + 1;
        }
        hashmap.put("autoKey", String.valueOf(Parameters.timeStamp_Long()));
//        int i = hashmap.size();
//        System.out.println("map 大小" + i);
        int num = 0;
//        System.out.println("map 里面的值" + hashmap.entrySet());
        for (HashMap.Entry<String, String> entry : hashmap.entrySet()) {
            num++;
            if (num == hashmap.size()) {
                stringBuffer.append(entry.getKey() + "=" + entry.getValue());
            } else {
                stringBuffer.append(entry.getKey() + "=" + entry.getValue() + "&");
            }
        }
        String url = stringBuffer.toString();
        URI uri = URI.create(url);
        return uri;
    }


现在接口的 URL 拼接完成了,请求也发起了,也可以拿到返回的 json 数据了,最后就得对返回的数据做校验了,这里我是重新封装了下 TestNG 提供的 Assert 类为 TaquAssert 类,其实没做多大改变加了几个方法而已,下面是一个完整的登陆例子:

public class LoginTest {
    static LoggerControler log = LoggerControler.getLogger(LoginTest.class);
    // accounts 表
    AccountsTest accountsTest = new AccountsTest();

    String tid = "v1_Account_login";

    @Test
    public void loginSuccess() {
        // 发起api请求
        JSONObject json = ApiEngine.taquAPI(tid, "username", "password");
        // 打印出json
        log.info(json);

        // 通过api获取该用户的account_id,然后查询Accounts表
        String account_id = json.getJSONObject("info").getJSONObject("data").getString("account_id");
        Accounts accounts = accountsTest.byAccount_id(Integer.valueOf(account_id));

        // 校验返回的 状态是不是 success.
        String response_status = json.getString("response_status");
        TaquAssert.assertEquals("校验response_status", "success", response_status);

        // 从数据库获取用户名和接口返回的用户名做对比检查是否一致
        String account_name_sql = accounts.getAccount_name();
        String account_name_api = json.getJSONObject("info").getJSONObject("data").getString("nickname");
        TaquAssert.assertEquals("校验account_name", account_name_api, account_name_sql);

    }
}

后期还会把这块放到 Jenkins 环境去运行,之前把 Jenkins 环境搞坏了,苦逼还得去重搭建😱 😭

OK 以上就是目前做接口自动化的大概思路,这其中肯定还有非常多需要去做优化的, 望各大神提提优化意见和方案,小弟不胜感激。

共收到 14 条回复 时间 点赞

Robotframework 足够,用 ride, 不需要你会 python。

@xuxu 帅哥,看到你的答复,正好最近回去写接口,RF 只提供了一部分库吧,如果是自定义报文,还有不少第三方库的使用,怎么弄呢?
比如我这边文件访问需要测 SAMBA,客户端实现需要第三方库支持,感觉类似的一些功能,RF 很多没法用啊。反正我是都自己封了一遍,就是还得再整一套流程输出报告比较坑。求经验~

python+requests,简直是接口自动化神器。话说 java 你都会了,python 这么简单。

#3 楼 @sunrise 再简单也得花几天时间,java 心里比较有底,py 对我来说是新武器,心里没底。

我和你的方案基本一致

#5 楼 @ganyunxiao 你也在用 mybatis 么,感觉这个用起来还是很繁琐,得建好几个类还得 xml 配置等等,你有啥优化方案没。

  1. 你的数据现在都是静态的,而有些 case 需要动态数据,可以用反射动态生成数据。
  2. 用 excel 管理不太利于共享,如果能和公司里用的 case 管理工具集成最好了。
  3. 可以考虑把返回的报文解析然后 set 到定义好的类中,然后比较两个类。
  4. 加入 setup 和 teardown。
  5. 用 junit 的 reporting。

#7 楼 @flint 非常感谢。

  1. 你说这这个数据是指 excel 里头的数据么? 我后期是考虑通过开发编写的 api 文档(web 版本),直接从他那拿到数据自动写入到 excel 文件,但是目前主要问题,api 文档维护得不够。
  2. excel 对多人合作确实不利,不好管理。但是目前公司并没有一套 case 管理平台,case 都是用 excel 放 svn 上管理。 3,4. 第三,四点可以详细说明下么?作用是干嘛?方便解决啥问题?非常感谢。
  3. 目前有在用 testng 自带的 reporting。 再次非常非常感谢。

#8 楼 @shijin880921

  1. 比如现在你要发送当天的日期,你就不能在 excel 里 hard code,但是你可以自己制定一个函数格式比如 ##get_date## 你在解析这个字段的时候替换成当天的日期。
  2. 其实你们可以考虑搭一个 bugfree,免费的。
  3. 现在如果你需要比较报文里的多个字段,那么你就需要写多个 assert,这样就会使 case 显得很凌乱,而且代码不能复用。但是如果你把你的业务逻辑和测试逻辑抽象出不同的对象,然后分别创建对应的类,然后把返回的报文依据格式 set 进对象里面。在你的 case 中就是比较两个对象,很清楚。而且你所创建的类还可以复用到其他类型的自动化中,因为整个系统的对象肯定是相同的,这样减少了你维护不同类型的用例的成本。
  4. 为了保证测试用例的独立性,最好使用干净的环境,创建所需要的数据,然后进行测试,测试完成后把环境还原。这样可以排除历史数据或者垃圾数据带来的问题。

#9 楼 @flint 谢谢,有些可以适当引入。

@sunrise requests 针对 https post 请求报错 method GET 不被允许,有遇到过吗

米阳MeYoung 回复

我个人也认为,对于测试来说用 mybatils 的 xml 配置 来对表做增删改查,是有点繁重,可以利用 mybatis 来封装一下增删改查,4 个方法对外,我就是封装了一下,这样就不用每个测试都要去知道 mybatis 怎么用

悠然 回复

嗯嗯 我这几年前做法了。 很早就不这么玩了。

你好楼主,我这现在还是用你这种思路,请教下:你们现在还在用这种设计方法嘛?大致聊聊呗,多谢了 大佬!😍 😍

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册