接口自动化测试框架(基于jmeter)

接口测试可以分为两部分:

一是线上接口(生产环境)自动化测试,需要自动定时执行,每5分钟自动执行一次,相当于每5分钟就检查一遍线上的接口是否正常,有异常能够及时发现,不至于影响用户使用。

二是测试环境的接口自动化测试,测试时机可以是1、功能开发完成并提测,检查一边测试环境的所有接口是否正常,有异常则需要解决后再正式介入测试。2、测试完成上线发版前,检查一边测试环境的所有接口是否正常,有异常则需要解决后再上线发版。

jmeter是Apache的一个用java写成,用来做接口测试和压力测试的工具,有gui界面,因为是纯java的,所以可以跨平台使用(只要有java环境就可以),jmeter已经把做接口测试的各种方法封装的很完善稳定,所以我们可以直接用来做接口自动化测试,不需要自己再去封装各种请求、断言、结果处理等等方法。相当于把jmeter的脚本当作接口测试用例管理工具,在脚本里面把要测试的接口、断言都写好。

基于jmeter做接口自动化框架包括以下几个部分:

jmeter+jenkins+github+钉钉机器人+tomcat+shell脚本+java程序

包含了这些功能后,几乎大部分都可以自动化,手工需要做的事情就只有第三步:写接口用例并推送到github

步骤大致是这样:用jmeter写接口—推送到GitHub—jenkins定时自动执行测试(从GitHub拉取最新脚本—执行shell脚本—执行java代码,处理统计结果,发送报告)

以下是框架具体步骤:

一、多人协作就需要github来管理,在github新建仓库,用于存放jmx脚本

二、每个测试人员需要下载sourcetree,在本地新建本地仓库,并关联github远程仓库

三、将各自写好的jmx脚本放到本地仓库,提交并推送到github

四、在服务器上部署jenkins

1、配置git源代码管理,如果远程仓库是私有类型的,则需要配置证书或账号密码(每次构建测试时,jenkins都会检查远程仓库是否有更新脚本,有更新就拉最新的脚本来测试,这样也方便修改被测脚本)

2、设置定时自动构建,下面是每天的8点到23点,每5分钟构建一次

3、设置超时管理,为了不影响下一次构建

4、配置要执行的shell脚本

5、配置构建失败通知钉钉

 

五、在服务器配置tomcat环境(如果是win服务器,最好用服务的形式安装tomcat)

------linux配置tomcat环境-----

1、下载Core下的zip包,解压到linux的目录

2、到bin目录下给catalina.sh和startup.sh赋予chmod 777权限,或者给全部sh文件赋予最高权限chmod 777 *.sh

3、sh startup.sh启动,在浏览器中输入http://10.10.10.115:8080/出现tomcat页面表示启动成功

注意:如果访问不成功,如果我们想在本机中检测是否已经成功部署,那么我们必须关掉Linux中的防火墙或者开放8080端口,我在这里采用开放端口的方法。

4、用指令sh shutdown.sh停止tomcat的运行,继续进行后续操作

5、查看防火墙是否开启:systemctl status firewalld

未开启:Active: inactive (dead)

已开启:Active: active (running)

在CentOS 7或RHEL 7或Fedora中防火墙由firewalld来管理:https://blog.csdn.net/ViJayThresh/article/details/81284007

开启防火墙:systemctl start firewalld

关闭防火墙:systemctl stop firewalld

执行开机禁用防火墙自启命令  : systemctl disable firewalld.service

开放端口号:firewall-cmd --permanent --zone=public --add-port=8080/tcp(只能在防火墙开启的情况下开放端口)

6、将要查看的文件放到webapps/ROOT/re.html这里,浏览器直接访问http://10.10.10.115:8080/re.html就可以看到了

------windows配置tomcat环境-----

1、下载安装程序

 

2、双击exe文件安装-选择jre目录-选择tomcat安装目录-选择端口(默认8080可修改)

在tomcat/bin目录双击startup.bat启动服务

或者

双击Tomcat9w.exe-start

 

 

3、不用配置环境变量,但是需要关闭win防火墙

https://jingyan.baidu.com/article/17bd8e52083ce685ab2bb839.html(win关闭防火墙的方法)

六、在服务器配置jmeter环境

需要两个jmeter环境,jmeter1用来收集jtl结果和生成报告,不需要改参数。jmeter2需要收集xml日志,把jmeter/bin/user.properties文件在结尾新增参数

jmeter.save.saveservice.output_format=xml

jmeter.save.saveservice.response_data=true

jmeter.save.saveservice.samplerData=true

jmeter.save.saveservice.requestHeaders=true

jmeter.save.saveservice.url=true

jmeter.save.saveservice.responseHeaders=true

 

七、shell脚本,包括以下几个步骤

删除上次的测试结果

在tomcat目录中新建index文件夹,用于存放本次测试结果

挨个执行jmx脚本(每个脚本需要执行两次,第一次收集jtl结果和生成报告,第二次收集xml日志,将报告、xml日志文件放到tomcat的目录下)

执行java程序

八、java程序(框架核心),把写好的java代码打成一个可执行jar包,让shell来调用,需要包含以下功能

1、用时间戳重命名index文件夹,保证每次的结果目录不会覆盖

2、把xml日志文件cope到index下面

3、统计fail接口数量

4、收集fail接口的信息

5、将信息写成html页面报告,并放到tomcat目录下,同时用同一个时间戳生成报告的url

6、将测试结果的简要信息、报告的url、日志的url,调用钉钉机器人,发送到钉钉群,并且艾特相关接口负责人,以下是相关代码

依赖:
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.58</version>
</dependency>

代码:
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;

class DingDingTools {
    private String WEBHOOK_TOKEN;
    DingDingTools(String token) {
        WEBHOOK_TOKEN = token;
    }
    private void send(String textMsg) throws IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(WEBHOOK_TOKEN);
        httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
        StringEntity se = new StringEntity(textMsg, "utf-8");
        httpPost.setEntity(se);
        CloseableHttpResponse response = httpClient.execute(httpPost);
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            String result = EntityUtils.toString(response.getEntity(), "utf-8");
            System.out.println("发送钉钉消息成功 " + result);
        } else {
            System.out.println("发送钉钉消息失败");
        }
        // 关闭
        httpClient.close();
        response.close();
    }

    //发送text格式的消息
    void text(String mag, String[] atMobile, boolean isAtAll) throws IOException {
        JSONObject object = new JSONObject();
        JSONObject object_text = new JSONObject();
        JSONObject object_at = new JSONObject();
        object_text.put("content",mag);
        object_at.put("atMobiles",atMobile);
        object.put("msgtype","text");
        object.put("text",object_text);
        object.put("at",object_at);
        object.put("isAtAll",isAtAll);
        send(String.valueOf(object));
    }

    //发送link格式的消息
    void link(String title, String text, String messageUrl, String picUrl) throws IOException {
        JSONObject object = new JSONObject();
        JSONObject object_link = new JSONObject();
        object_link.put("text", text);
        object_link.put("title", title);
        object_link.put("picUrl", picUrl);
        object_link.put("messageUrl", messageUrl);
        object.put("msgtype", "link");
        object.put("link", object_link);
        send(String.valueOf(object));

    }

    //发送markdown格式的消息
    void markdown(String title, String text, String atMobile, boolean isAtAll) throws IOException {
        JSONObject object = new JSONObject();
        JSONObject object_markdown = new JSONObject();
        JSONObject object_at = new JSONObject();
        object_markdown.put("title", title);
        object_markdown.put("text", text);
        object_at.put("atMobiles", atMobile);
        object_at.put("isAtAll", isAtAll);
        object.put("msgtype", "markdown");
        object.put("markdown", object_markdown);
        object.put("at", object_at);
        send(String.valueOf(object));
    }

    //整体跳转ActionCard类型
    void actionCard(String title, String text, String singleTitle, String singleURL, int btnOrientation, int hideAvatar) throws IOException {
        JSONObject object = new JSONObject();
        JSONObject object_actionCard = new JSONObject();
        object_actionCard.put("title",title);
        object_actionCard.put("text",text);
        object_actionCard.put("hideAvatar",hideAvatar);
        object_actionCard.put("btnOrientation",btnOrientation);
        object_actionCard.put("singleTitle",singleTitle);
        object_actionCard.put("singleURL",singleURL);
        object.put("actionCard",object_actionCard);
        object.put("msgtype","actionCard");
        send(String.valueOf(object));

    }

    //独立跳转ActionCard类型
    void actionCard1(String title, String text, String btnsTitle1, String btnsTitle2, String actionURL1, String actionURL2, int btnOrientation, int hideAvatar) throws IOException {
        JSONObject object = new JSONObject();
        JSONObject object_actionCard1 = new JSONObject();
        JSONObject object_btns1 = new JSONObject();
        JSONObject object_btns2 = new JSONObject();
        object_btns1.put("title",btnsTitle1);
        object_btns1.put("actionURL",actionURL1);
        object_btns2.put("title",btnsTitle2);
        object_btns2.put("actionURL",actionURL2);
        object_actionCard1.put("title",title);
        object_actionCard1.put("text",text);
        object_actionCard1.put("hideAvatar",hideAvatar);
        object_actionCard1.put("btnOrientation",btnOrientation);
        object_actionCard1.put("btns","["+object_btns1+","+object_btns2+"]");
        object.put("actionCard",object_actionCard1);
        object.put("msgtype","actionCard");
        send(String.valueOf(object));

    }

    //FeedCard类型
    void feedCard(String title1, String messageURL1, String picURL1, String title2, String messageURL2, String picURL2) throws IOException {
        JSONObject object = new JSONObject();
        JSONObject object_feedCard = new JSONObject();
        JSONObject object_link1 = new JSONObject();
        JSONObject object_link2 = new JSONObject();
        object_link1.put("title",title1);
        object_link1.put("messageURL",messageURL1);
        object_link1.put("picURL",picURL1);
        object_link2.put("title",title2);
        object_link2.put("messageURL",messageURL2);
        object_link2.put("picURL",picURL2);
        object_feedCard.put("links","["+object_link1+","+object_link2+"]");
        object.put("feedCard",object_feedCard);
        object.put("msgtype","feedCard");
        send(String.valueOf(object));
    }
}

7、将测试报告发邮件给相关人员,以下是相关代码

依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-email</artifactId>
    <version>1.5</version>
</dependency>
代码:
import org.apache.commons.mail.EmailAttachment;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.MultiPartEmail;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class CommonsMail {
    public static void mail(String[] to, String[] cc, String[] path) throws EmailException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");// 定义时间格式
        String time = sdf.format(new Date());// 获取当前时间

        MultiPartEmail multiPartEmail = new MultiPartEmail();
        multiPartEmail.setHostName("smtp.qiye.163.com");//邮件服务器地址
        multiPartEmail.setAuthentication(Constants.sender, Constants.senderPassword);//发送邮件服务器账户密码
        multiPartEmail.setCharset("UTF-8");//发送邮件的字符编码
        //可不加
        multiPartEmail.setSSLOnConnect(false);//开启SSL加密,可不加
        multiPartEmail.setStartTLSEnabled(false);//开启TLS加密,可不加
        multiPartEmail.setSmtpPort(25);//端口可以不设置,默认25
        multiPartEmail.setDebug(false);//调试模式
        //发送邮件的地址
        multiPartEmail.setFrom(Constants.sender);
        multiPartEmail.setSubject("线上接口自动化测试报告");//主题
        multiPartEmail.setMsg("附件为 "+time+" 线上接口测试报告");//正文
        for (String toList : to) {
            if (toList != null && toList.trim().length() > 0) {
                multiPartEmail.addTo(toList);//接收邮件地址
            }
        }
        for (String ccList : cc) {
            if (ccList != null && ccList.trim().length() > 0) {
                multiPartEmail.addCc(ccList);//抄送人地址
            }
        }
        for (String pathList : path) {
            if (pathList != null && pathList.trim().length() > 0) {
                EmailAttachment attachment = new EmailAttachment();//创建附件的对象
                attachment.setPath(pathList);//设置附件内容
                attachment.setName("");// 邮件发送出去时附件名
                multiPartEmail.attach(attachment);//添加附件
            }
        }
        multiPartEmail.send();
        System.out.println("邮件发送成功!\n" + "收件人:\n" + Arrays.toString(Constants.TOLIST1) + "\n" + "抄送人:\n" + Arrays.toString(Constants.CCLIST1));

    }
}

///钉钉通知消息效果

测试报告的url页面

日志url页面

点击全部接口跳转的url报告(fail的接口需要标红)

 

 

 

  • 14
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萌翻天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值