根據接口文檔中的入參,生成自動化測試用例中的異常測試用例,包含用例描述,用例數據


 不想當將軍的小兵,不是好的小兵;不想做開發的測試,不是好的測試;

不管你信不信,我是信了...

一直以來,內心總有些迷茫的時候,迷茫的是作為測試既然要學那么多編程,為什么不直接去干開發呢?

看了這句話,才發現自己鑽進了牛角尖,沒有站在更高的高度來思考測試這個崗位,而僅僅是作為一個測試員,或者說是抱着急功近利的心態在想問題,從而忽略了測試的本質。

測試的本質是盡可能的發現軟件的缺陷,更高級的應該是用更少的時間,更少的人員來找出更多的缺陷。那么不管更好的測試流程,更高效的測試方法,更好的測試工具,這些都應該是我們追求的東西。

流程,方法,工具,這三者中我認為更重要的應該是方法,最難提升的也是方法。

編碼啊工具之類的可以用到哪些提升哪些,

說到底,不管是開發中的編碼,還是測試中的編碼,都是很初級的工作,都不是這個職業鏈中的高端,高端應該是對設計對方法的研究與創新,甚至引發自己所處職業的一種潮流。

做好測試不是靠編程,而是靠的是嚴禁的作風,慎密的邏輯思維,適合的測試流程。從用戶角度,到系統角度,到黑產角度,既保證給普通用戶很好的用戶體驗,也保證系統運行平順流暢,也保證不能應為hacker的攻擊而功虧一簣

 

 

進入正題,最近在研究API接口中,異常測試用例的自動化問題,這邊考慮的自動化,是通過接口說明文檔,自動生成用例描述,用例的入參數據,用例的斷言數據,當然測試的級別不是最高的,可以設置為2左右

比如一個注冊接口,異常的測試用例,是不是需要判斷,每一個必傳入參是否傳入,那這邊就有2N條測試用例

1.請求傳入的必傳參數var1未傳,驗證返回var1....

2. 請求傳入的必傳參數var1傳入的為空字符串(String類型)/null(..), 驗證返回var1.....

異常測試用例還需要判斷入參的長度,是不是又有了

3. 請求傳入的參數var1超過最大長度限制,驗證返回var1

有些入參有要求,比如用list,異常測試用例又有了 

4.請求傳入的參數Var1不是xx類型,驗證返回

入參最好還需要判斷是否將入參首位的空格去掉,異常測試用例又有了 

5. 請求傳入的入參首尾含有空格,驗證存入DB中不含空格【要求代碼對入參的首尾空格做trim()操作】

對接口的異常測試用例,彌漫着滿滿的套路氣息,每次都進行編寫測試用例,創建測試用例數據和斷言等操作,入參多的時候,還是很費時間的,不利於提升工作效率。

更好的辦法是:編寫代碼,自動生成測試用例描述,組裝測試用例的數據,自動生成斷言等

以前,我們一直用Jmeter創建的腳本來自動生成上述內容,

Jmeter生成jmx腳本,腳本中指定了入參個數、類型,長度等,之后生成用例描述,用例數據和斷言

好處就是復用方便,更改下url直接測試

缺點就是,不利於動態生成用例,入參變化多了之后要重新創建新的腳本

還有一個缺點就是low,你若是說你用Jmeter做接口自動化測試的,大廠中廠都會嫌棄你low,因為人家是用Python做的,Java做的。

【low不low!!who cares?!!不是一樣能完成任務嗎,不一樣能持續化集成並發送測試報告嗎?你們一個組就100多號測試,也不就是完成這寫接口的自動化測試嗎,我們剛上手的實習生分分鍾都能講API測試用到飛】

感覺中國人,很喜歡用工具和方式來judge others,我們兄弟公司的人,大多是麻省理工學院的,api測試自動化還是用postman實現的呢,ui測試也只不過是protractor+jasmine等,人家不是low,夠用就好,有時候已經不提倡測試,直接leader 做code review

 

現在動態實現接口異常測試用例的生成,用一個簡單的例子

 我們常見的接口說明文檔,是不是長這樣?

 

我頁面還沒開發完,大意就是講入參,和比天性,類型,最大長度,等信息填入表中。

 

CREATE TABLE [DBO].[QA_APIVAR](
	[APIVAR_ID] [INT] IDENTITY(1,1) NOT NULL PRIMARY KEY,
	[API_ID] [INT] NOT NULL, 
	[APIVAR_NAME] [VARCHAR](100) NULL,
	[APIVAR_INPUTFLAG] [BIT] NOT NULL DEFAULT 1,
	[APIVAR_INPUTDATATYPE] [VARCHAR](100) NULL,
	[APIVAR_INPUTDATATYPEID] INT NOT NULL,
       [APIVAR_INPUTLENGTH] INT NOT NULL,
	[APIVAR_INPUTSCOPE] [VARCHAR](100) NULL, 
	[APIVAR_INPUTNOTE] [VARCHAR](200) NULL, 
	[APIVAR_DELETED_FLAG] [BIT] NOT NULL DEFAULT 0,
	[APIVAR_CREATEDT] DATETIME NOT NULL,
	[APIVAR_UPDATEDT] DATETIME NOT NULL
)

 

 

 代碼單元測試部分,判斷必傳入參的未傳,生成測試用例描述,測試數據body【這邊以json格式為sample】,斷言暫未寫

package com.example.demo.api;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;
import java.util.Random;


@Controller
public class ApiVar2Case {


    String ALLCHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    @Autowired
    private ApiVarService apiVarService;


    @Autowired
    private ApiCaseService apiCaseService;

    @RequestMapping("/CheckMustVar")
    //根據必傳參數,依次生成"請求傳入的xx參數未傳,驗證返回"
    public void CheckMustVar() {
        List<ApiVarBean> list = apiVarService.CheckMustVar(1);
        System.out.println(list);
        System.out.println(list.size());
        int max = 0;
        String body = null;
        for (int i = 0; i < list.size(); i++) {
            String var = list.get(i).getVal();
            var = "請求中未傳入" + var + "驗證返回" + var + "~~更多斷言";
            System.out.println(var);
            StringBuffer sb = new StringBuffer();
            body = "{ \n";
            for (int j = 0; j < list.size(); j++) {

                if (list.get(i).getVal() != list.get(j).getVal()) {
                    Random random = new Random();
                    max = list.get(j).getInputLenght();
                    sb = new StringBuffer("");
                    for (int k = 0; k < max; k++) {

                        sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
                    }

                    body = body + "\"" + list.get(j).getVal() + "\":\"" + sb + "\", \n";


                }
            }
            body = body.substring(0, (body.length() - 3)) + " \n }";
            System.out.println(body);
            ApiCaseBean apiCaseBean = new ApiCaseBean();
            apiCaseBean.setApiCase_taskid(1);
            apiCaseBean.setApiCase_name(var);
            apiCaseBean.setApiCase_body(body);
            apiCaseBean.setApiCase_asseertion(null);
            apiCaseBean.setApiCase_priorityid(3);

            int count = apiCaseService.save(apiCaseBean);
            System.out.println(count);
        }
    }

    //根據必傳參數,依次生成"請求傳入的XX參數為空字符串"
    @RequestMapping("/CheckMustVarEmpty")
    public void CheckMustVarEmpty() {
        List<ApiVarBean> list = apiVarService.CheckMustVar(1);
        int max = 0;
        String body = null;
        for (int i = 0; i < list.size(); i++) {
            String var = list.get(i).getVal();
            var = "請求中傳入" + var + "為空字符串驗證返回" + var + "~~更多斷言";
            System.out.println(var);
            StringBuffer sb = new StringBuffer();
            body = "{ \n";
            for (int j = 0; j < list.size(); j++) {

                if (list.get(i).getVal() != list.get(j).getVal()) {
                    Random random = new Random();
                    max = list.get(j).getInputLenght();
                    sb = new StringBuffer("");
                    for (int k = 0; k < max; k++) {

                        sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
                    }

                    body = body + "\"" + list.get(j).getVal() + "\":\"" + sb + "\", \n";


                } else {
                    body = body + "\"" + list.get(j).getVal() + "\":\"" + "\", \n";
                }
            }
            body = body.substring(0, (body.length() - 3)) + " \n }";
            ApiCaseBean apiCaseBean = new ApiCaseBean();
            apiCaseBean.setApiCase_taskid(1);
            apiCaseBean.setApiCase_name(var);
            apiCaseBean.setApiCase_body(body);
            apiCaseBean.setApiCase_asseertion(null);
            apiCaseBean.setApiCase_priorityid(3);

            int count = apiCaseService.save(apiCaseBean);
            System.out.println(count);
        }
    }


    //根據接口中參數,依次生成"請求傳入的XX參數為最大長度+1,即超過最大長度"
    @RequestMapping("/CheckVarOverLength")
    public void CheckVarOverLength() {
        List<ApiVarBean> list = apiVarService.CheckMustVar(1);
        int max = 0;
        String body = null;
        for (int i = 0; i < list.size(); i++) {
            String var = list.get(i).getVal();
            int length = list.get(i).getInputLenght();
            var = "請求中傳入" + var + "的長度為" + length + "實際傳入的長度為" + (length + 1) + "驗證返回" + var + "~~更多斷言";
            System.out.println(var);
            StringBuffer sb = new StringBuffer();
            body = "{ \n";
            for (int j = 0; j < list.size(); j++) {
                Random random = new Random();
                max = list.get(j).getInputLenght();
                sb = new StringBuffer("");
                if (list.get(i).getVal() != list.get(j).getVal()) {
                    for (int k = 0; k < max; k++) {
                        sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
                    }
                } else {
                    for (int k = 0; k <= max; k++) {
                        sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
                    }
                }
                body = body + "\"" + list.get(j).getVal() + "\":\"" + sb + "\", \n";
            }
            body = body.substring(0, (body.length() - 3)) + " \n }";
            ApiCaseBean apiCaseBean = new ApiCaseBean();
            apiCaseBean.setApiCase_taskid(1);
            apiCaseBean.setApiCase_name(var);
            apiCaseBean.setApiCase_body(body);
            apiCaseBean.setApiCase_asseertion(null);
            apiCaseBean.setApiCase_priorityid(3);

            int count = apiCaseService.save(apiCaseBean);
            System.out.println(count);
        }

    }


}

  

 

 
        

以下是生成的數據,我當然可以用個對象來接收,並存到數據庫中去

 

[ApiCaseBean{num=1, val='name', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=5, InputNote='null'}, ApiCaseBean{num=2, val='ID', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=5, InputNote='null'}, ApiCaseBean{num=3, val='mobile', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=5, InputNote='null'}, ApiCaseBean{num=6, val='apple', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=6, InputNote='null'}, ApiCaseBean{num=7, val='orange', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=6, InputNote='null'}, ApiCaseBean{num=8, val='pear', InputFlag=1, InputDataType='String', InputTypeID=1, InputLenght=6, InputNote='null'}]
6
請求中未傳入name驗證返回name~~更多斷言
{
"ID":"zHUX3",
"mobile":"0J9jR",
"apple":"BTOfiV",
"orange":"ZUz1DB",
"pear":"8vHDVB"}
請求中未傳入ID驗證返回ID~~更多斷言
{
"name":"8gJfa",
"mobile":"5pKjY",
"apple":"7vZVSJ",
"orange":"45cTEN",
"pear":"v9FliS"}
請求中未傳入mobile驗證返回mobile~~更多斷言
{
"name":"Bi5Xm",
"ID":"OmYSR",
"apple":"IEYHCO",
"orange":"1zPaB6",
"pear":"Jw0d84"}
請求中未傳入apple驗證返回apple~~更多斷言
{
"name":"gesB1",
"ID":"fSCeE",
"mobile":"HmY6j",
"orange":"SKInay",
"pear":"kDeurf"}
請求中未傳入orange驗證返回orange~~更多斷言
{
"name":"KnSwW",
"ID":"9VKd2",
"mobile":"thAXp",
"apple":"apjji8",
"pear":"J3UkLR"}
請求中未傳入pear驗證返回pear~~更多斷言
{
"name":"OTKPo",
"ID":"5WgEh",
"mobile":"gfJZA",
"apple":"aXksSk",
"orange":"JCCGZp"}

 

生成測試用例的表

 

CREATE TABLE [DBO].[QA_APICASE](
	[APICASE_ID] [INT] IDENTITY(1,1) NOT NULL PRIMARY KEY,
	[API_ID] [INT] NOT NULL, 
	[APICASE_NAME] [VARCHAR](100) NULL,
	[APICASE_BODY] [NVARCHAR](2000) NULL,
	[APICASE_ASSERCTION] [VARCHAR](100) NULL, 
	[APICASE_PRIORITYID] INT ,
	[APICASE_PASSID] INT,
	[APICASE_DELETED_FLAG] [BIT] NOT NULL DEFAULT 0,
	[APICASE_MEMO] [NVARCHAR](2000) NULL,
	[APICASE_CREATEDT] DATETIME NOT NULL,
	[APICASE_UPDATEDT] DATETIME NOT NULL
)

 

 

 有了用例描述和數據后,不管用什么接口測試工具,還是自已用Java/Python寫的框架,導入數據即可

比如 https://www.cnblogs.com/qianjinyan/p/9951465.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM