24.1 Cucumber+Rest Assured快速搭建api自動(dòng)化測(cè)試平臺(tái)

雖然我寫(xiě)了這文章汰寓,但是我不建議這種做法,原因很簡(jiǎn)單苹粟,這是把簡(jiǎn)單事情復(fù)雜化有滑。

什么是Cucumber?什么是BDD嵌削?這里不細(xì)講毛好,不懂的直接查看官方:https://cucumber.io/
  什么是Rest Assured?傳送門(mén):https://github.com/rest-assured/rest-assured

以下以java為開(kāi)發(fā)語(yǔ)言掷贾,快速搭建一個(gè)cucumber+Rest Assured的api自動(dòng)化測(cè)試平臺(tái)。
  1. 用IDEA 新建一個(gè)Maven工程荣茫,并pom文件添加如下配置:

     
        <!--ccucumber 相關(guān)依賴(lài)-->
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java8</artifactId>
            <version>1.2.4</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>1.2.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/info.cukes/cucumber-html -->
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-html</artifactId>
            <version>0.2.3</version>
        </dependency>

        <!--rest-assured 接口測(cè)試框架-->
        <!-- https://mvnrepository.com/artifact/com.jayway.restassured/rest-assured -->
        <dependency>
            <groupId>com.jayway.restassured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>2.9.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.testng/testng -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.9.10</version>
        </dependency>

        <!--log 引入-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.5</version>
            <scope>provided</scope>
        </dependency>

        <!--compare jsoon-->
        <dependency>
            <groupId>net.javacrumbs.json-unit</groupId>
            <artifactId>json-unit</artifactId>
            <version>1.13.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.1</version>
        </dependency>
  1. 新建個(gè)ApiTools類(lèi)想帅,并對(duì)Rest Assured進(jìn)程二次封裝,主要是Post 和 Get請(qǐng)求的基礎(chǔ)封裝和對(duì)返回json解析的封裝啡莉,具體代碼如下:
  /**
     * 帶json的post請(qǐng)求
     *
     * @param apiPath api地址
     * @param json    請(qǐng)求json
     * @return api返回的Response
     */
    public static Response post(String apiPath, String json) {
//        開(kāi)始發(fā)起post 請(qǐng)求
        String path = Parameters.BOSEHOST + apiPath;
        Response response = given().
                contentType("application/json;charset=UTF-8").
                headers("header1", "value1").
                cookies("cookies1", "value1").
                body(json).
                when().log().all().post(path.trim());
        log.info(response.statusCode());
        log.info("reponse:");
        response.getBody().prettyPrint();
        return response;
    }

    /**
     * get 請(qǐng)求
     *
     * @param apiPath api路徑
     * @return api的response
     */
    public static Response get(String apiPath) {
//        開(kāi)始發(fā)起GET 請(qǐng)求
        String path = Parameters.BOSEHOST + apiPath;
        Response response = given().
                contentType("application/json;charset=UTF-8").
                headers("headers1", "value1").
                cookie("cookie1", "value1").
                when().log().all().get(path.trim());
        log.info(response.statusCode());
        log.info("reponse:");
        response.getBody().prettyPrint();
        return response;
    }

    /**
     * 獲取json中某個(gè)key值
     * @param response  接口返回
     * @param jsonPath  jsonpath, 例如 a.b.c   a.b[1].c  a
     * @return
     */
    public static String getJsonPathValue(Response response, String jsonPath) {
        String reponseJson = String.valueOf(response.jsonPath().get(jsonPath));
//        String jsonValue = String.valueOf(from(reponseJson).get(jsonPath));
        return reponseJson;
    }

3.新建個(gè)Steps 類(lèi)港准,完成常用step的封裝,具體代碼如下:

import com.jayway.restassured.response.Response;
import com.tools.apitools.ApiTools;
import com.tools.apitools.MyAssert;
import com.tools.filetools.ReadTxtFile;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
/**
 * Created by MeYoung on 8/1/2016.
 * <p>
 * Steps 集合
 */
public class Steps {

    Response response = null;

    @When("^I send a GET request to \"(.*?)\"$")
    public void getRequest(String path) {
        response = ApiTools.get(path);
    }

    @When("^I send a POST request to \"(.*?)\"$")
    public void postRequest(String apiPath) throws Throwable {
        response = ApiTools.post(apiPath);
    }

    @When("^I send a POST request to \"(.*?)\" and request json:$")
    public void postRequestWithJson(String apiPath, String json) {
        response = ApiTools.post(apiPath, json);
    }

    @When("^I use a \"(.*?)\" file to send a POST request to \"(.*?)\"$")
    public void postRequestWihtFile(String fileName, String path) {
        String json = ReadTxtFile.readTxtFile(fileName);
        response = ApiTools.post(path, json);
    }

    @Then("^the JSON response equals$")
    public void assertResponseJson(String expected) {
        String responseJson = response.body().asString();
        assertJsonEquals(responseJson, expected);
    }

    @Then("^the JSON response equals json file \"(.*?)\"$")
    public void theJSONResponseEqualsJsonFile(String fileName) {
        String responseJson = response.body().asString();
        String fileJson = ReadTxtFile.readTxtFile(fileName);
        assertJsonEquals(responseJson, fileJson);
    }

    @Then("^the response status should be \"(\\d{3})\"$")
    public void assertStatusCode(int statusCode) {
        Object jsonResponse = response.getStatusCode();
        MyAssert.assertEquals(jsonResponse, statusCode);
    }

    @Then("^the JSON response \"(.*?)\" equals \"(.*?)\"$")
    public void assertEquals(String str, String expected) {
        String jsonValue = ApiTools.getJsonPathValue(response, str);
        MyAssert.assertEquals(jsonValue, expected);
    }

    @Then("^the JSON response \"(.*?)\" type should be \"(.*?)\"$")
    public void assertMatch(String str, String match) {
        String jsonValue = ApiTools.getJsonPathValue(response, str);
        MyAssert.assertMatch(jsonValue, match);
    }

    @Then("^the JSON response \"(.*?)\" should be not null$")
    public void assertNotNull(String str) {
        String jsonValue = ApiTools.getJsonPathValue(response, str);
        MyAssert.assertNotNull(jsonValue);
    }

    @Then("^the JSON response \"(.*?)\" start with \"(.*?)\"$")
    public void assertStartWith(String str, String start) {
        String jsonValue = ApiTools.getJsonPathValue(response, str);
        MyAssert.assertStartWith(jsonValue, start);
    }
    @Then("^the JSON response \"(.*?)\" end with \"(.*?)\"$")
    public void assertEndWith(String str, String end) {
        String jsonValue = ApiTools.getJsonPathValue(response, str);
        MyAssert.assertEndWith(jsonValue, end);
    }
    @Then("^the JSON response \"(.*?)\" include \"(.*?)\"$")
    public void assertInclude(String str, String include) {
        String jsonValue = ApiTools.getJsonPathValue(response, str);
        MyAssert.assertInclude(jsonValue, include);
    }
}

當(dāng)然上面代碼還涉及到一些Asssert的封裝咧欣,這里就不列出來(lái)浅缸,個(gè)人喜好不同,更具自己熟悉的情況去引入自己熟悉的jar包魄咕。

ok衩椒,最后我們愉快的寫(xiě)兩個(gè)case,看看效果:

  @get
  Scenario Outline: use examples
    When I send a GET request to "apiurl"
    Then the response status should be "200"
    Then the JSON response "<jsonPath>" equals "<value>"
    Examples:
      | jsonPath     | value             |
      | genericPlan  | false             |
      | ehiCarrierId | 90121100          |
      | carrierName  | Anthem Blue Cross |

  @post
  Scenario: test post request
    When I send a POST request to "apiurl"
    Then the response status should be "200"
    And the JSON response "message" equals "success"
    #    校驗(yàn)放回值是否是某種類(lèi)型
    And the JSON response "sessionId" type should be "^\d{6}$"
    #    校驗(yàn)返回值不為空
    And the JSON response "url" should be not null
    #    校驗(yàn)是否以XX開(kāi)頭
    Then the JSON response "message" start with "su"
    #    校驗(yàn)是否以XX開(kāi)頭
    Then the JSON response "message" end with "ss"
    #    校驗(yàn)是否以XX開(kāi)頭
    Then the JSON response "message" include "ss"
    #    校驗(yàn)返回json是否為XXX,對(duì)整個(gè)返回json的校驗(yàn)
    Then the JSON response equals
    """
      {
          "result":"success"
      }
    """

通過(guò)Junit 運(yùn)行feature.

  1. 在Pom.xml 文件添加junit相關(guān)包:
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>1.2.4</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
  1. 在feature 同級(jí)目錄下新建個(gè)運(yùn)行類(lèi)毛萌,代碼例子如下:
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(
        strict = true,
        monochrome = true,
        plugin = {"pretty", "html:target/cucumber", "json:target/cucumber.json"},
        features = {"src/test/java/bosev2"},
        glue = {"com.bose.step"},
        tags = {"~@unimplemented"})
public class RunnerBoseTest {
}

@RunWith(Cucumber.class) : 注解表示通過(guò)Cucumber的Junit 方式運(yùn)行腳本
@CucumberOptions () :注解用于配置運(yùn)行信息苟弛,其中代碼中的plugin 表示測(cè)試報(bào)告輸出的路徑和格式, feature 表示被運(yùn)行的feature文件的包路徑阁将, glue中配置steps的包路徑地址膏秫,tags中配置要運(yùn)行的用例的tags名,其實(shí)~符號(hào)表示除了這個(gè)tags的所有tags.

通過(guò)Jenkins 執(zhí)行

  1. 在Pom.xml 文件里面添加運(yùn)行插件做盅,如下:
 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <inherited>true</inherited>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.18.1</version>
                <configuration>
                    <reuseForks>false</reuseForks>
                </configuration>
            </plugin>
        </plugins>
    </build>
  1. 在Jenkins 中添加Cucumber-JVM reports插件缤削。
  2. 新建Maven job,配置maven構(gòu)建方式和構(gòu)建后的測(cè)試報(bào)告展示吹榴。
Paste_Image.png

Cucumber-JVM reports 提供了非常漂亮的report亭敢,如下:

Paste_Image.png

最后附上項(xiàng)目地址:https://github.com/MeYoung/cucumber_restassured

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市腊尚,隨后出現(xiàn)的幾起案子吨拗,更是在濱河造成了極大的恐慌,老刑警劉巖婿斥,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劝篷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡民宿,警方通過(guò)查閱死者的電腦和手機(jī)娇妓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)活鹰,“玉大人哈恰,你說(shuō)我怎么就攤上這事≈救海” “怎么了着绷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)锌云。 經(jīng)常有香客問(wèn)我荠医,道長(zhǎng),這世上最難降的妖魔是什么桑涎? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任彬向,我火速辦了婚禮,結(jié)果婚禮上攻冷,老公的妹妹穿的比我還像新娘娃胆。我一直安慰自己,他們只是感情好等曼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布里烦。 她就那樣靜靜地躺著凿蒜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪招驴。 梳的紋絲不亂的頭發(fā)上篙程,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音别厘,去河邊找鬼虱饿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛触趴,可吹牛的內(nèi)容都是我干的氮发。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼冗懦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼爽冕!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起披蕉,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤颈畸,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后没讲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體眯娱,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年爬凑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了徙缴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嘁信,死狀恐怖于样,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情潘靖,我是刑警寧澤穿剖,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站卦溢,受9級(jí)特大地震影響糊余,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜既绕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一啄刹、第九天 我趴在偏房一處隱蔽的房頂上張望涮坐。 院中可真熱鬧凄贩,春花似錦、人聲如沸袱讹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至椒丧,卻和暖如春壹甥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背壶熏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工句柠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棒假。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓溯职,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親帽哑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谜酒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)妻枕,斷路器僻族,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • API自動(dòng)化測(cè)試方式非常多,可謂百花齊放屡谐,各種做法有各自的優(yōu)勢(shì)述么,那么今天我們簡(jiǎn)單介紹一種,通過(guò)Rest Assur...
    博客已遷移I米陽(yáng)閱讀 19,772評(píng)論 11 40
  • 序 寫(xiě)的api多了以后或者接手別人的項(xiàng)目之后康嘉,對(duì)api的運(yùn)維也會(huì)比較多碉输,特別是在測(cè)試環(huán)境,種種因素會(huì)導(dǎo)致接口出現(xiàn)不...
    go4it閱讀 2,870評(píng)論 1 4
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,811評(píng)論 6 342
  • Hey!你知道嗎肄梨?從小學(xué)一年級(jí)開(kāi)始阻荒,我的學(xué)費(fèi)一般拖到學(xué)期末才交的——開(kāi)學(xué)的第一天,同學(xué)們都高高興興地聊自己暑假去哪...
    風(fēng)逍揚(yáng)閱讀 526評(píng)論 1 2