最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

REST Assured 實(shí)踐(二):斷言實(shí)現(xiàn)

2022-10-12 16:13 作者:愛測軟件測試  | 我要投稿


在上一篇文章中,我們初步探討了 REST Assured 的應(yīng)用實(shí)踐,還有很多豐富的用法需要慢慢探索研究。而 REST Assured 提供的完整斷言手段,是測試工程師最常用最重要的功能之一。斷言該如何使用呢?

這里以 rest-assured 官方給的一個(gè)示例做演示學(xué)習(xí)

{

"lotto":{?

?"lottoId":5,?

?"winning-numbers":[2,45,34,23,7,5,3],?

?"winners":[{?

?? "winnerId":23,?

? "numbers":[2,45,34,23,3,5]?

?},{?

?? "winnerId":54, ?

?"numbers":[52,3,12,11,18,22]?

?}] } }

在本地使用 python -m CGIHTTPServer 臨時(shí)搭建起一個(gè)服務(wù):

根節(jié)點(diǎn).子節(jié)點(diǎn) 1)我們可以使用根節(jié)點(diǎn).(點(diǎn))子節(jié)點(diǎn)的方式一層層的找下去,例如我們需要對lottoId等于 5 進(jìn)行斷言:

@Test

?void testGPath(){ ??

? given(). ?

?? when(). ? ? ? ? ? ? log().all().get("http://127.0.0.1:8000/restAssured.json"). ?

?? then(). ? ? ?

?? ? ? log().all().body("lotto.lottoId",equalTo(5)); }

2)如果我們想要斷言winners數(shù)組下面的winnerId,檢查23和54是否包含其中,可以如下lotto.winners.winnerId寫法

@Test?

void testGPath(){ ?

?given(). ?

?when(). ? ? ? ? ? ?log().all().get("http://127.0.0.1:8000/restAssured.json"). ?

??then(). ? ? ??

? ? ?log().all()?

.body("lotto.winners.winnerId",hasItems(54,23)); }

索引取值

1)如果我們想要取某些相同字段中的某一個(gè),可以使用類似索引的方式獲取,例如想要斷言 winners 數(shù)組下面的 winnerId 的第一個(gè)值是否為23,可以使用 lotto.winners.winnerId[0],寫法如下:

@Test

void testGPath(){ ?

??given(). ??

?when(). ? ? ? ? ? ?log().all().get("http://127.0.0.1:8000/restAssured.json"). ??

?then(). ? ? ??

??log().all()? ??

??.body("lotto.winners.winnerId[0]",equalTo(23)); }

2)如果我們想要取某些相同字段中的最后一個(gè),可以使用 -1 作為索引,例如斷言斷言 winners 數(shù)組下面的 winnerId 的最后一個(gè)的值是否為 54

@Test?

void testGPath(){ ?

??given(). ??

?when(). ? ? ? ? ? ?log().all().get("http://127.0.0.1:8000/restAssured.json"). ?

??then(). ? ? ? ?

?? ?log().all() ? ? ? ? ? ?.body("lotto.winners.winnerId[-1]",equalTo(54)); }

findAll 有時(shí)候我們需要獲取符合某些條件的結(jié)果來進(jìn)行斷言,這里 findAll 可以幫助我們實(shí)現(xiàn),我們可以在 findAll 方法中寫篩選條件,例如我們想取 winnerId 的值在大于或等于 30 小于 60 之間的結(jié)果進(jìn)行斷言,具體寫法如下:

@Test void testGPath(){ ? ?given(). ? ?when(). ? ? ? ? ? ?log().all().get("http://127.0.0.1:8000/restAssured.json"). ? ?then(). ? ? ? ? ? ?log().all() ? ? ? ? ? ?.body("lotto.winners.findAll{ winners -> winners.winnerId >= 30 && winners.winnerId < 60}.winnerId[0]",equalTo(54)); }

find find 的用法與 findAll 基本一致,只是 find 默認(rèn)取匹配到的第一個(gè):

@Test

void testGPath(){ ?

?given(). ??

?when(). ? ? ? ? ? ?log().all().get("http://127.0.0.1:8000/restAssured.json").

?? ?then(). ? ??

? ? ? ?log().all() ? ? ?

?? ? ?.body("lotto.winners.find{ winners -> winners.winnerId >= 30 && winners.winnerId < 60}.winnerId",equalTo(54)); ? ?}

將上述各個(gè)斷言語法寫在一起,實(shí)際運(yùn)行校驗(yàn)結(jié)果:

上面介紹了,GPath 也支持 XML 格式的斷言,這里再以 rest-assured 官方給的一個(gè)實(shí)例做演示

<shopping>?

?<category type="groceries">?

?<item> <name>Chocolate</name>?

?<price>10</price> </item>?

<item> <name>Coffee</name>?

<price>20</price>?

</item>?

</category> <category type="supplies">

<item> <name>Paper</name> <price>5</price>?

?</item> <item quantity="4"> <name>Pens</name>

?<price>15</price> </item> </category>

<category type="present"> <item when="Aug 10">?

?<name>Kathryn's Birthday</name> <price>200</price>?

?</item> </category> </shopping>

再次在本地搭起一個(gè)臨時(shí)服務(wù):

若我們要對第二個(gè) name 的值 Coffee 進(jìn)行斷言,寫法如下:

@Test void testXML(){ ?

?when().? ? ? ? ?

?get("http://127.0.0.1:8000/restAssured.xml"). ?

?then(). ? ? ?

?log().all(). ? ? ? ? ? ?body("shopping.category[0].item[1].name",equalTo("Coffee")); }

size() 可以利用 size() 方法來獲取對應(yīng)節(jié)點(diǎn)的數(shù)量,例如這里要斷言 category 的數(shù)量:

@Test void testXML(){ ?

?when(). ? ? ?

?get("http://127.0.0.1:8000/restAssured.xml"). ? ?then(). ? ? ? ? ? ?log().all() ? ? ??

? .body("shopping.category.size()",equalTo(3)); }

it.@type、it.price 在 xml中 斷言中,可以利用 it. 屬性或節(jié)點(diǎn)的值來作為篩選條件; 例如這里要獲取 type 為 supplies 的 category 下的第一個(gè) item 的 name,以及獲取 price 為 10 的商品名 name。

@Test void testXML(){ ??

? when(). ? ? ?

? ? ? get("http://127.0.0.1:8000/restAssured.xml"). ??

? then(). ? ? ? ?

?? ? log().all() ? ? ? ?

?? ? .body("shopping.category.findAll{ it.@type == 'supplies' }.item[0].name",equalTo("Paper")) ? ? ? ? ? ? .body("shopping.category.item.findAll{ it.price == 10 }.name",equalTo("Chocolate")); }

.findAll?對于xml中有一個(gè)特別的語法,.findAll,可以直接忽略前面的節(jié)點(diǎn),直接對篩選條件進(jìn)行匹配,依然獲取price為10的商品名name,寫法如下:

@Test?

void testXML(){ ??

?when(). ??

? ? ? ? ?get("http://127.0.0.1:8000/restAssured.xml"). ?

?then(). ? ??

? ? ? ?log().all() ? ? ? ?

?? ?.body("**.findAll{ it.price == 10 }.name",equalTo("Chocolate")); }

將上述各個(gè)斷言語法寫在一起,實(shí)際運(yùn)行校驗(yàn)結(jié)果:

在實(shí)際工作中,對接口返回值進(jìn)行斷言校驗(yàn),除了常用字段的斷言檢測以外,還要對其他字段的類型進(jìn)行檢測,原因在于:

  • 返回字段較多,無法保證每個(gè)字段都寫斷言

  • 防止客戶端未做 null 值的校驗(yàn)判斷,如果因?yàn)榘姹咀兏蚓W(wǎng)絡(luò)等原因造成某個(gè)不能接收 null 值的返回字段為 null,就很有可能造成軟件的崩潰

  • 某些數(shù)值是不能為負(fù)的

  • 小數(shù)點(diǎn)保留位數(shù),對于股票的交易、醫(yī)療數(shù)據(jù)的分析,小數(shù)點(diǎn)的精確度都是有其實(shí)際價(jià)值的

對返回的字段一個(gè)個(gè)寫斷言顯然是非常耗時(shí)的,這個(gè)時(shí)候就需要一個(gè)模板,可以定義好數(shù)據(jù)類型和匹配條件,除了關(guān)鍵參數(shù)外,其余可直接通過此模板來斷言,這個(gè)就要請出JsonSchema了

先對上述的 json 例子做少許修改,增加一個(gè) String 類型的 winnername 字段,這里可以先你不用疑惑為什么加,后續(xù)自有其演示作用

1)首先要借助于Json schema tool的網(wǎng)站jsonschema.net/,將返回json字符串復(fù)制到頁面左邊,然后點(diǎn)擊INFER SHCEMA,就會(huì)自動(dòng)轉(zhuǎn)換為schema json文件類型,會(huì)將每個(gè)地段的返回值類型都設(shè)置一個(gè)默認(rèn)類型; 在pattern中也可以寫正則進(jìn)行匹配

2)點(diǎn)擊“設(shè)置”按鈕會(huì)出現(xiàn)各個(gè)類型返回值更詳細(xì)的斷言設(shè)置,這個(gè)就是schema最常用也是最實(shí)用的功能,也可以對每種類型的字段最更細(xì)化的區(qū)間值校驗(yàn)或者斷言,例如長度,取值范圍等,具體感興趣的話可以從官網(wǎng)學(xué)習(xí)深入學(xué)習(xí);平常對重要字段的校驗(yàn)我通常會(huì)選用其他斷言,比如hamcrest斷言

3)選擇復(fù)制功能,可以將生成的schema模板保存下來

4)添加maven依賴,在rest-assured完成支持

<dependency> ??

?<groupId>io.rest-assured</groupId> ??

?<artifactId>json-schema-validator</artifactId> ? ?<version>4.0.0</version> </dependency>

5)使用matchesJsonSchemaInClasspath方法對響應(yīng)結(jié)果進(jìn)行schema斷言

@Test void jsonSchemaTest(){ ? ?get("http://127.0.0.1:8000/restAssured.json"). ? ?then().log().all() ? ? ? ? ? ?.body(matchesJsonSchemaInClasspath("jsonSchema.json")); }

運(yùn)行結(jié)果:

  • String類型的默認(rèn)值為null,后端很有可能在某個(gè)字段無值時(shí)返回null,例如我們將之前添加的winnername字段返回null:

運(yùn)行查看斷言結(jié)果:

很明顯用例執(zhí)行失敗,當(dāng)我們定義了winnername為String類型后,返回null就會(huì)斷言失敗,這顯然不符合我們的需求,會(huì)造成用例執(zhí)行結(jié)果的誤判,這個(gè)時(shí)候我們需要使winnername即可以為String類型,又可以為null;

這就要用到j(luò)sonSchema提供的Combining schemas方法了 Combining schemas提供了如下幾種方式:

  • allOf

  • anyOf

  • oneOf

  • not

這里我們選取anyOf(任何一項(xiàng)滿足即可)來完成上述的舉例,將原來的type換成String和null任何一個(gè)都支持的類型:

再次運(yùn)行用例,查看斷言結(jié)果:

用例完美通過,到此結(jié)束~

另外,在我們實(shí)際工作中,很多時(shí)候并不是直接對響應(yīng)結(jié)果直接斷言,我們可能需要獲取響應(yīng)結(jié)果中的某些值,將這些值傳遞到下一個(gè)接口或者和其他接口的響應(yīng)進(jìn)行比較斷言,這就涉及到了對響應(yīng) response 的獲取與處理了,后續(xù)文章繼續(xù)探討。


REST Assured 實(shí)踐(二):斷言實(shí)現(xiàn)的評論 (共 條)

分享到微博請遵守國家法律
古交市| 林芝县| 宁武县| 利辛县| 历史| 东乌珠穆沁旗| 休宁县| 吴川市| 凤阳县| 罗山县| 广安市| 荃湾区| 阳城县| 肇庆市| 南华县| 阿鲁科尔沁旗| 崇文区| 河源市| 柯坪县| 耒阳市| 东阳市| 岐山县| 浦江县| 尖扎县| 龙游县| 平阳县| 洛浦县| 泰顺县| 靖江市| 永福县| 张家界市| 抚松县| 广州市| 利川市| 秦安县| 佳木斯市| 乃东县| 民和| 乌审旗| 太原市| 亚东县|