接口自動化·分享·第三篇·單接口的批量測試如何實現

一、痛點:一條測試數據對應一個測試方法

前面的章節中我們已經寫代碼實現了登錄接口的處理調用,但是一個接口往往是需要多條測試用例才能完整的覆蓋到每一種情況,針對於單接口多條測試用例需要執行的情況,該如何處理呢,可能很多人最先想到的就是:一條測試數據對應一個測試方法?下面有一個註冊接口,我們基於此思路來編碼實現接口的完整測試。

1) 接口業務:會員註冊

2) 接口地址:http://119.23.241.154:8080/futureloan/mvc/api/member/register

3) 接口參數:mobilephone+pwd

4) 接口響應:json格式的報文

  關於這個接口的更多詳細的細節我們可以從公司提供的接口文檔中獲取,在公司裏面做接口項目的測試,不管是自動化測試還是非自動化,都會有這樣的一個文檔描述接口項目中的每一個接口的細節,包括業務,接口地址,參數,響應報文中的字段以及格式,這是我們在測試前編寫測試用例的重要參考文獻,大部分接口文檔的撰寫都大同小異,關於接口的一些重要信息一般都會涵蓋到,比如以下接口文檔關於註冊接口的描述:

 

  現在我們整理得到一條正向用例和幾條反向用例:

1.合格手機號,合格密碼

2.重複以上的手機號,密碼

3.傳手機號,不傳密碼

4.不傳手機號,傳密碼

5.不合格的手機號

6.合格的手機號,不合格密碼

  編寫測試類,每條用例,準備一個測試方法:test1-test6對應上面每種測試情況:

  test1方法(mobilephone:18999700122;pwd:123456)

    @Test
    public void test1(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.創建post對象,以post方式提交接口請求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.準備提交參數
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "18999700122");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "123456");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.參數封裝到請求體當中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.準備客戶端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交請求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回數據,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.輸出結果到控制檯驗證數據
            System.out.println("*********返回數據:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

  test2方法(mobilephone:18999700122pwd:123456

 

    @Test
    public void test1(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.創建post對象,以post方式提交接口請求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.準備提交參數
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "18999700122");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "123456");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.參數封裝到請求體當中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.準備客戶端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交請求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回數據,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.輸出結果到控制檯驗證數據
            System.out.println("*********返回數據:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

 

 

  test3方法(mobilephone:18999700122;pwd:空)

 

  @Test
    public void test3(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.創建post對象,以post方式提交接口請求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.準備提交參數
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "18999700122");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.參數封裝到請求體當中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.準備客戶端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交請求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回數據,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
        //7.輸出結果到控制檯驗證數據
            System.out.println("*********返回數據:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

 

 

  test4方法(mobilephone:空;password:123456)

 

   @Test
    public void test3(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.創建post對象,以post方式提交接口請求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.準備提交參數
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "123456");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.參數封裝到請求體當中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.準備客戶端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交請求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回數據,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.輸出結果到控制檯驗證數據
            System.out.println("*********返回數據:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

  test5方法(mobilephone:189;password:123456)

 

   @Test
    public void test3(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.創建post對象,以post方式提交接口請求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.準備提交參數
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "189");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "123456");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.參數封裝到請求體當中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.準備客戶端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交請求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回數據,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.輸出結果到控制檯驗證數據
            System.out.println("*********返回數據:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

 

  test6(mobilephone:18999700122;password:123456789)

 

  @Test
    public void test3(){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.創建post對象,以post方式提交接口請求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.準備提交參數
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", "18999700122");
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", "123456789");
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.參數封裝到請求體當中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.準備客戶端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交請求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回數據,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.輸出結果到控制檯驗證數據
            System.out.println("*********返回數據:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

執行完畢,我們可以看到六個測試方法都有響應數據返回。

 

說明這種設計是可以達到我們的目的,但是問題是什麼

我們看到每個方法的代碼幾乎是一模一樣,除了測試數據。目前我們只設計了六條用例,試想,如果有七組,八組,九組...更多組的測試數據,那麼將會有更多的重複代碼,這樣的設計簡直就是災難性的。

二、痛點解決

  上面已經將問題拋出,我們該如何去解決這個問題呢?

  第一種辦法是我們自己去編碼實現一條解決方案,但是成本太高,而且可能寫出來的框架有很多問題。

  第二種辦法就是去找一些第三方的框架來幫助我們來解決這個問題,而testng正式我們想要找的這樣一個框架,testng的數據提供者技術就能幫我們優雅的解決這個痛點,我們準備一個測試方法就可以了。

測試方法代碼

 

  @Test(dataprrovider=”datas”)
    public void test(String mobilephone,String pwd){
        String restUrl = "http://119.23.241.154:8080/futureloan/mvc/api/member/register";
        //1.創建post對象,以post方式提交接口請求
        HttpPost httpPost = new HttpPost(restUrl);
        //2.準備提交參數
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("mobilephone", mobilephone);
        BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("pwd", pwd);
        params.add(basicNameValuePair1);
        params.add(basicNameValuePair2);
        //3.參數封裝到請求體當中
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(params));
            System.out.println("method:"+httpPost.getMethod());
            //4.準備客戶端
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //5.提交請求
            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            //6.解析接口返回數據,返回字符串
            String result = EntityUtils.toString(httpResponse.getEntity());
            //7.輸出結果到控制檯驗證數據
            System.out.println("*********返回數據:"+result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

 

代碼改動:

1) 測試方法上多了兩個參數

 

2) 代碼中直接綁定參數

 

數據提供者代碼

① 數據提供者的作用就是提供幾組測試數據給測試方法,方法的返回值必須是二維數組,並且此方法要用@DataProvider來標註:

 

 

② 測試方法如果要引用數據提供者則必須指定數據提供者的名字:

 

 

  測試用例執行結果爲:

 

 

總結:

  對於同一接口的批量測試,變動的數據可能就只有測試數據,因此,我們我們可以考慮通過@Dataprovider來提供幾組測試數據,測試方法引用了dataprovider後就能拿到數據,依次注入完成批量測試,從而簡化代碼,簡化測試。

 

三、 思路延伸

  數據提供者能依次提供測試數據的功能固然很好,但是我們需要的這些測試數據來自於哪裏呢。像上面那樣直接定義在代碼當中,其實屬於硬編碼的情況,耦合性很高,一旦我們要修改測試數據,那麼我們就必須修改代碼,而頻繁的修改代碼就可能導致各種不可預期的問題,要實現一個好的自動化測試框架應該儘可能保證代碼的健壯性和兼容性

  那麼問題來了,數據源的問題怎麼解決?

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