接口自動化測試框架(基於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的接口需要標紅)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章