版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2019.08.12 星期一 |
前言
WireMock是基于HTTP的API的模擬器,下面我們就一起來(lái)學(xué)習(xí)和了解御板。
開(kāi)始
首先看下主要內(nèi)容
了解如何使用WireMock,這是一種可以與用戶界面測(cè)試結(jié)合使用的工具,用于提供遠(yuǎn)程API調(diào)用結(jié)果的本地副本。
然后看一下寫(xiě)作環(huán)境
Swift 5, iOS 13, Xcode 11
WireMock是基于HTTP的API的模擬器弓柱。 有些人可能會(huì)認(rèn)為它是服務(wù)虛擬化(service virtualization)
工具或模擬服務(wù)器(mock server)
〔嗟可以看一下WireMock官網(wǎng)矢空,和 GitHub - WireMock。
當(dāng)您依賴的API不存在或不完整時(shí)俊犯,它可以使您保持高效妇多。 它支持測(cè)試真實(shí)API無(wú)法可靠生成的邊緣情況和失敗模式。 而且因?yàn)樗俣瓤煅嘞溃梢詫?gòu)建時(shí)間從幾小時(shí)減少到幾分鐘者祖。
它具有以下幾個(gè)特點(diǎn):
-
Flexible Deployment:從
Java
應(yīng)用程序立莉,JUnit
測(cè)試,Servlet
容器或獨(dú)立進(jìn)程中運(yùn)行WireMock
七问。 -
Powerful Request Matching:使用各種策略匹配請(qǐng)求URL蜓耻,方法,
header
械巡,cookie
和正文刹淌。 對(duì)JSON
和XML
支持。 - Record and Playback:通過(guò)捕獲現(xiàn)有API的流量來(lái)快速啟動(dòng)并運(yùn)行讥耗。
WireMock
是一個(gè)開(kāi)發(fā)工具有勾,它提供遠(yuǎn)程API調(diào)用結(jié)果的本地副本。 您可以將它與User Interface(UI)
測(cè)試結(jié)合使用古程,以呈現(xiàn)不同類型的API響應(yīng)蔼卡。
UI測(cè)試充當(dāng)安全網(wǎng),確保您提供預(yù)期的用戶體驗(yàn)挣磨。 它側(cè)重于您的應(yīng)用程序的端到端體驗(yàn)雇逞。 同樣,UI測(cè)試可以回答不同于單元測(cè)試的問(wèn)題茁裙,例如:
- 如果我的視圖為空塘砸,在此屏幕上會(huì)發(fā)生什么?
- 如果我從網(wǎng)絡(luò)請(qǐng)求中收到錯(cuò)誤會(huì)怎么樣晤锥?
- 我的驗(yàn)證用戶界面是否顯示了不同類型輸入的正確信息掉蔬?
- 我的
table cells
是否反映了收到的數(shù)據(jù)?
首先查近,找到入門(mén)項(xiàng)目并打開(kāi)它眉踱。 構(gòu)建并運(yùn)行項(xiàng)目以檢查功能。
星球大戰(zhàn)(Star Wars)
信息應(yīng)用程序使用Star Wars API來(lái)檢索星球大戰(zhàn)角色列表霜威。 您可以點(diǎn)擊每個(gè)單元格以導(dǎo)航到該角色的詳細(xì)信息頁(yè)面谈喳。
1. Running the Tests
該應(yīng)用程序已經(jīng)設(shè)置了UI測(cè)試目標(biāo)(UI testing target)
和兩個(gè)UI測(cè)試。 UI測(cè)試目標(biāo)已連接到構(gòu)建方案的默認(rèn)Test
操作戈泼。
通過(guò)按Command-U
或單擊菜單項(xiàng)Product ? Test
來(lái)運(yùn)行測(cè)試婿禽。 您將看到應(yīng)用程序啟動(dòng)并從列表視圖導(dǎo)航到詳細(xì)視圖并返回。 在此導(dǎo)航期間大猛,UI測(cè)試驗(yàn)證列表視圖和詳細(xì)信息視圖上的預(yù)期條件扭倾。
要查看測(cè)試報(bào)告,請(qǐng)轉(zhuǎn)到左側(cè)窗格中的Report navigator
挽绩,然后查看測(cè)試結(jié)果:
只要您的計(jì)算機(jī)處于聯(lián)機(jī)狀態(tài)并且測(cè)試可以成功點(diǎn)擊Star Wars API
膛壹,測(cè)試就會(huì)通過(guò)。
2. UI Test Code
查看StarWarsInfoUITests.swift
以查看UI tests
。 UI測(cè)試的詳細(xì)信息超出了本文的范圍模聋。
示例項(xiàng)目演示了最佳實(shí)踐肩民,包括:
- 盡可能使用輔助功能標(biāo)識(shí)符而非輔助功能標(biāo)簽
labels
來(lái)標(biāo)識(shí)元素。這種方法的好處包括:- 用戶無(wú)法以任何方式使用輔助功能標(biāo)識(shí)符链方,因此您可以根據(jù)需要為其命名持痰。
- 標(biāo)識(shí)符保持不變。例如祟蚀,
label
可能具有不同的值工窍,但其標(biāo)識(shí)符保持不變。所以你的測(cè)試仍然可以在屏幕上找到元素前酿。
- 在
XCTestCase
上的擴(kuò)展中名為waitForElementToAppear(_:file:line:elementName:timeout :)
的便捷方法允許自定義超時(shí)患雏。 - 將文件和行號(hào)傳遞給便利函數(shù)允許UI測(cè)試系統(tǒng)報(bào)告測(cè)試失敗。
Challenges With the Current Setup
這個(gè)小應(yīng)用程序和相關(guān)的測(cè)試在當(dāng)前配置中表現(xiàn)良好罢维,但隨著代碼庫(kù)的增長(zhǎng)纵苛,應(yīng)用程序?qū)⒁蕾囉诟嗟木W(wǎng)絡(luò)請(qǐng)求。 測(cè)試會(huì)變慢并變得不穩(wěn)定言津。
以下是代碼庫(kù)增長(zhǎng)時(shí)可以預(yù)見(jiàn)的一些問(wèn)題:
- 如果您依賴的網(wǎng)絡(luò)請(qǐng)求失敗,會(huì)發(fā)生什么取试?
- 如果網(wǎng)絡(luò)速度變慢悬槽,導(dǎo)致超時(shí)或延長(zhǎng)等待時(shí)間,會(huì)發(fā)生什么瞬浓?
- 如果列表請(qǐng)求開(kāi)始以不同的排序順序發(fā)回?cái)?shù)據(jù)怎么辦初婆?
在所有三種情況下,您的測(cè)試都會(huì)失敗猿棉。 有一個(gè)共同點(diǎn)磅叛。 這些測(cè)試失敗都不是由編程錯(cuò)誤或邏輯問(wèn)題引起的。 在這些情況下測(cè)試失敗將是誤報(bào)萨赁,因?yàn)槭⒊瞿目刂品秶?/p>
1. Mitigating Network Failures
在本教程中弊琴,您將消除UI測(cè)試中的一個(gè)不確定性來(lái)源。 您將停止制作實(shí)時(shí)網(wǎng)絡(luò)請(qǐng)求并依賴稱為WireMock的網(wǎng)絡(luò)模擬技術(shù)杖爽。 WireMock
允許您將網(wǎng)絡(luò)排除為UI測(cè)試中潛在的故障源敲董。
使用WireMock
,您將在每次測(cè)試運(yùn)行時(shí)始終獲得與給定請(qǐng)求相同的響應(yīng)慰安。 這使您可以更自信地進(jìn)行測(cè)試腋寨。 如果出現(xiàn)failure
,您將花費(fèi)更少的時(shí)間來(lái)確定原因化焕。 網(wǎng)絡(luò)是任何應(yīng)用程序中更易變的組件之一萄窜。 通過(guò)將其從失敗的潛在原因列表中刪除,您將能夠?qū)W⒂谀鷩L試使用每個(gè)屏幕測(cè)試的基本功能。
Overview of WireMock
WireMock
是一個(gè)開(kāi)源庫(kù)查刻,允許您運(yùn)行本地Web服務(wù)器進(jìn)行測(cè)試键兜。通過(guò)在運(yùn)行測(cè)試時(shí)更新您從應(yīng)用程序調(diào)用的API端點(diǎn),您可以返回已知的響應(yīng)赖阻。這可以幫助您在開(kāi)發(fā)過(guò)程中更快地進(jìn)行蝶押。在測(cè)試運(yùn)行期間,將應(yīng)用程序指向WireMock
實(shí)例允許您從API請(qǐng)求接收預(yù)期的響應(yīng)火欧。
足夠的理論棋电。開(kāi)始的時(shí)候了!
Setting Up WireMock
WireMock
至少需要Java 7
苇侵,因此請(qǐng)確保您的Mac安裝了更新版本的Java赶盔。從Oracle
下載最新的Java Development Kit
JDK。您將作為獨(dú)立實(shí)例運(yùn)行WireMock
榆浓。轉(zhuǎn)到下載頁(yè)面download page于未,獲取WireMock
的最新穩(wěn)定版本。下載將是一個(gè)JAR
文件陡鹃。
轉(zhuǎn)到starter
項(xiàng)目的基本目錄烘浦,并創(chuàng)建名為Vendor
的目錄。將JAR
文件移動(dòng)到此目錄中萍鲸。重命名JAR
文件WireMock.jar
闷叉,以便更容易地從命令行進(jìn)行交互。接下來(lái)脊阴,打開(kāi)終端并導(dǎo)航到您創(chuàng)建的Vendor
目錄握侧。
在此目錄中,鍵入以下命令以啟動(dòng)WireMock
進(jìn)程:
java -jar wiremock.jar --port 9999 --verbose
此命令在端口9999
上啟動(dòng)WireMock
并打開(kāi)詳細(xì)模式(verbose mode)
嘿期。 打開(kāi)詳細(xì)模式可以讓您在應(yīng)用與WireMock
端點(diǎn)交互時(shí)查看所有消息品擎,包括URL匹配和未命中。 在嘗試確定WireMock
端點(diǎn)可能無(wú)法正常工作的原因時(shí)备徐,這是一個(gè)很大的幫助萄传。
現(xiàn)在,測(cè)試WireMock
是否在您的系統(tǒng)上運(yùn)行坦喘。 打開(kāi)瀏覽器并轉(zhuǎn)到http://localhost:9999/__admin/mappings盲再。
你應(yīng)該看到以下內(nèi)容:
{
"mappings" : [ ],
"meta" : {
"total" : 0
}
}
很好! 這意味著WireMock
已啟動(dòng)并正在運(yùn)行瓣铣。 您還會(huì)注意到WireMock
在Vendor
中創(chuàng)建了兩個(gè)目錄:__ files
和mappings
答朋。
默認(rèn)情況下,WireMock
的獨(dú)立實(shí)例會(huì)查找與可執(zhí)行文件位置相關(guān)的這兩個(gè)目錄棠笑。
-
__files
目錄包含您要為任何給定的API請(qǐng)求發(fā)回的模擬響應(yīng)梦碗。 -
mappings
目錄包含將API請(qǐng)求模式映射到包含所需響應(yīng)的特定文件的文件。
Setting Up a Mock Response
示例應(yīng)用程序使用Star Wars API
中的一個(gè)端點(diǎn)來(lái)請(qǐng)求字符列表。 該端點(diǎn)是https://swapi.co/api/people/洪规。
如果您在瀏覽器中訪問(wèn)此端點(diǎn)印屁,Star Wars API
頁(yè)面可以很好地向您顯示JSON響應(yīng),包括headers
斩例。 您只對(duì)這里的回復(fù)感興趣雄人。
復(fù)制不包括headers
的完整response
:
{
"count": 87,
"next": "https://swapi.co/api/people/?page=2",
"previous": null,
"results": [
{
"name": "Luke Skywalker",
"height": "172",
"mass": "77",
"hair_color": "blond",
"skin_color": "fair",
"eye_color": "blue",
"birth_year": "19BBY",
"gender": "male",
// Clipped for brevity here
]
}
將此響應(yīng)作為character-list.json
保存到__
files目錄中。
1. Setting Up Mappings
接下來(lái)念赶,您需要讓WireMock
知道如何將people
端點(diǎn)映射到此響應(yīng)础钠。 在名為 character-list.json
的映射目錄中創(chuàng)建一個(gè)新文件。
使文件的內(nèi)容如下所示:
{
"request": {
"method": "GET",
"url": "/swapi.co/api/people"
},
"response": {
"status": 200,
"bodyFileName": "character-list.json"
}
}
這使得Wiremock
知道使用/swapi.co/api/people
路徑將任何GET
請(qǐng)求映射到具有HTTP 200
成功狀態(tài)的character-list.json
響應(yīng)叉谜。
您的最終Vendor
目錄布局應(yīng)如下所示:
2. Verify Functionality
現(xiàn)在旗吁,驗(yàn)證WireMock
是否已將您的映射編入索引。 如果您的終端仍然在上一個(gè)會(huì)話中運(yùn)行停局,請(qǐng)按Control-C
停止它很钓,然后使用以下命令再次啟動(dòng)WireMock
:
java -jar wiremock.jar --port 9999 --verbose
WireMock
應(yīng)該已經(jīng)拿起你的新映射文件。 要檢查這一點(diǎn)董栽,請(qǐng)轉(zhuǎn)到http://localhost:9999/__admin/mappings码倦。
您應(yīng)該看到以下輸出:
{
"mappings" : [ {
"id" : "5804b634-2a15-4fb0-a16e-2c19559f37df",
"request" : {
"url" : "/swapi.co/api/people",
"method" : "GET"
},
"response" : {
"status" : 200,
"bodyFileName" : "character-list.json"
},
"uuid" : "5804b634-2a15-4fb0-a16e-2c19559f37df"
} ],
"meta" : {
"total" : 1
}
}
此輸出表示WireMock
正在拾取您的映射文件。 接下來(lái)锭碳,檢查為端點(diǎn)返回的響應(yīng)叹洲。 轉(zhuǎn)到瀏覽器并輸入http://localhost:9999/swapi.co/api/people。
您應(yīng)該看到以下輸出:
很棒工禾!一切都在WireMock
方面發(fā)揮作用。現(xiàn)在蝗柔,您將把WireMock
集成到UI test
中闻葵。
Integrating WireMock
要將WireMock
的工作實(shí)例集成到UI測(cè)試中,請(qǐng)按照下列步驟操作:
- 1) 設(shè)置項(xiàng)目以允許來(lái)自本地運(yùn)行的
WireMock
實(shí)例的HTTP
加載癣丧。 - 2) 使用啟動(dòng)參數(shù)啟動(dòng)UI測(cè)試以傳遞已定義的參數(shù)槽畔。
- 3) 創(chuàng)建一種基于啟動(dòng)參數(shù)在代碼中切換
URL schemes
的方法。
1. Allowing Loads from a Local HTTP Server
首先胁编,配置項(xiàng)目以允許來(lái)自非SSL連接的HTTP
請(qǐng)求厢钧。如果您不執(zhí)行此步驟,App Transport Security(ATS)
將不允許網(wǎng)絡(luò)請(qǐng)求連接到WireMock
嬉橙。
通常不建議允許不安全的負(fù)載早直,但對(duì)于UI測(cè)試,它比配置自簽名證書(shū)更容易從WireMock
啟用SSL
市框。在更復(fù)雜的設(shè)置中霞扬,您可以將項(xiàng)目配置為僅允許測(cè)試方案中的不安全負(fù)載使用構(gòu)建配置設(shè)置或測(cè)試目標(biāo)的不同Info.plist
。
按照以下步驟使用WireMock
設(shè)置ATS
進(jìn)行UI測(cè)試:
- 1) 在
StarWarsInfo group
組中打開(kāi)Info.plist
。 - 2) 在底部喻圃,單擊最后一行上的
+
萤彩。 - 3) 從
Key
列的下拉列表中選擇App Transport Security Settings
。 - 4) 按
Tab
鍵斧拍。 - 5) 選擇右側(cè)的顯示三角形使其指向下方雀扶。
- 6) 現(xiàn)在,在
App Transport Security Settings
行中單擊+
肆汹。 - 7) 從新行的下拉列表中愚墓,選擇
Allow Arbitrary Loads
。 - 8) 最后县踢,在此行的
Value
列中洲劣,將值更改為YES
。
2. Defining a Launch Argument
接下來(lái)袜刷,您將定義一個(gè)啟動(dòng)參數(shù)横堡,讓?xiě)?yīng)用程序知道何時(shí)切換URL schemes
。 從Xcode啟動(dòng)時(shí)谴返,您可以將參數(shù)傳遞給您的應(yīng)用程序煞肾,類似于將參數(shù)傳遞給終端命令的方式。 在Xcode
中使用Scheme Editor
嗓袱。
您將在該scheme
的運(yùn)行操作中定義啟動(dòng)參數(shù)籍救。 通過(guò)這種方式配置,您可以在模擬器中運(yùn)行應(yīng)用程序而無(wú)需運(yùn)行任何測(cè)試渠抹。 一旦確定一切都按照您想要的方式運(yùn)行蝙昙,您將在測(cè)試代碼中定義相同的參數(shù)并使用它們啟動(dòng)應(yīng)用程序。 運(yùn)行UI測(cè)試時(shí)梧却,應(yīng)用程序的行為方式應(yīng)該相同奇颠。
3. Editing the Xcode Scheme
單擊Xcode
中的StarWarsInfo
方案,然后單擊Edit Scheme
放航。
在左側(cè)窗格中選擇Run
操作烈拒。 在中間窗格中,選擇Arguments
選項(xiàng)卡广鳍。 在Arguments Passed on Launch
部分中荆几,單擊+
并添加啟動(dòng)參數(shù)-runlocal
。 確保選中新啟動(dòng)參數(shù)左側(cè)的復(fù)選框赊时。
單擊Close
接受更改并返回到您的代碼吨铸。
4. Updating to Use Launch Arguments
現(xiàn)在,您需要更新代碼庫(kù)以查找此啟動(dòng)參數(shù)并使用適當(dāng)?shù)?code>URL scheme祖秒。
Adding a Utility Function
首先焊傅,創(chuàng)建一個(gè)實(shí)用程序方法來(lái)查找啟動(dòng)參數(shù)剂陡。 按住Control鍵并單擊StarWarsInfo
組,然后創(chuàng)建一個(gè)名為Utils
的新組狐胎。 然后鸭栖,按住Control鍵并單擊新的Utils
組,并創(chuàng)建一個(gè)名為StartupUtils.swift
的新Swift文件握巢。 將以下代碼添加到此文件:
struct StartupUtils {
static func shouldRunLocal() -> Bool {
return CommandLine.arguments.contains("-runlocal")
}
}
此代碼檢查CommandLine.arguments
晕鹊,它是一個(gè)字符串?dāng)?shù)組。 如果該數(shù)組包含-runlocal
參數(shù)暴浦,則該函數(shù)將返回true
溅话。
Checking for Local flag in Network Client
接下來(lái),在網(wǎng)絡(luò)客戶端中使用新的便利函數(shù)歌焦。 在Network
組內(nèi)飞几,打開(kāi)StarWarsAPINetworkClient.swift
。 將baseURLString
的屬性更新為計(jì)算屬性独撇,如下所示:
var baseURLString: String {
if StartupUtils.shouldRunLocal() {
return "http://localhost:9999/swapi.co/api/"
} else {
return "https://swapi.co/api/"
}
}
如果啟動(dòng)時(shí)存在-runlocal
屬性屑墨,則baseURLString
將使用local scheme
,連接到正在運(yùn)行的WireMock
實(shí)例以獲取其數(shù)據(jù)纷铣。 現(xiàn)在卵史,您可以完全控制API的數(shù)據(jù)響應(yīng)。
打開(kāi)終端(如果尚未打開(kāi))并確保WireMock
正在運(yùn)行搜立。 導(dǎo)航到包含WireMock
可執(zhí)行文件的目錄以躯。 運(yùn)行相同的命令以啟動(dòng)WireMock
:
java -jar wiremock.jar --port 9999 --verbose
Perform a Run with WireMock
設(shè)置啟動(dòng)參數(shù),按Command-R
建立并運(yùn)行啄踊。 加載初始列表時(shí)觀察終端忧设。 當(dāng)應(yīng)用程序請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)并且WireMock
返回時(shí),您應(yīng)該看到控制臺(tái)打印輸出颠通。
5. Testing Against WireMock
現(xiàn)在见转,執(zhí)行最后的步驟,使用正確的啟動(dòng)參數(shù)設(shè)置UI測(cè)試蒜哀。
UI Test Launch Arguments
回到Xcode,展開(kāi)Project導(dǎo)航器中的StarWarsInfoUITests
組吏砂。 然后按住Control鍵并單擊Utility
組撵儿。 創(chuàng)建一個(gè)名為LaunchArguments.swift
的新文件。 請(qǐng)務(wù)必選擇StarWarsInfoUITests
并從Save As
對(duì)話框的Targets
部分中刪除StarWarsInfo
的選擇狐血。
添加以下代碼
struct LaunchArguments {
static var launchLocalArguments: [String] {
return [
"-runlocal"
]
}
}
最后淀歇,展開(kāi)項(xiàng)目導(dǎo)航器中的Tests
組并打開(kāi)StarWarsInfoUITests.swift
。 在兩個(gè)測(cè)試中的每個(gè)測(cè)試中匈织,在創(chuàng)建本地app
參數(shù)之后浪默,添加以下行:
app.launchArguments = LaunchArguments.launchLocalArguments
這會(huì)為每個(gè)測(cè)試添加-runlocal
啟動(dòng)參數(shù)牡直。
現(xiàn)在,您可以測(cè)試針對(duì)WireMock
而不是實(shí)時(shí)網(wǎng)絡(luò)運(yùn)行的UI測(cè)試纳决。
切換回Xcode并按Command-U
運(yùn)行UI測(cè)試碰逸。 如果您在測(cè)試運(yùn)行時(shí)觀察終端,您將看到WireMock
的輸出作為您的測(cè)試請(qǐng)求數(shù)據(jù)阔加,并且它們是從本地服務(wù)器返回的饵史。
恭喜! 您已消除UI測(cè)試對(duì)網(wǎng)絡(luò)的嚴(yán)重依賴胜榔。
除了模擬您從實(shí)時(shí)網(wǎng)絡(luò)請(qǐng)求獲得的相同響應(yīng)之外胳喷,您現(xiàn)在可以將不同的場(chǎng)景發(fā)送回您的UI并查看應(yīng)用程序的響應(yīng)方式。
例如:
- 如果收到
HTTP 500
狀態(tài)夭织,您的應(yīng)用會(huì)顯示正確的錯(cuò)誤消息嗎吭露? - 如果UI收到空數(shù)據(jù)集,會(huì)發(fā)生什么尊惰?
- 如果收到格式錯(cuò)誤的數(shù)據(jù)集讲竿,應(yīng)用程序是否以正確的方式響應(yīng)?
- 如果收到的某些字符串對(duì)于UI來(lái)說(shuō)太長(zhǎng)择浊,會(huì)發(fā)生什么戴卜? 是否所有內(nèi)容都按預(yù)期包裝或截?cái)啵?/li>
嘗試調(diào)整模擬的響應(yīng)以測(cè)試應(yīng)用內(nèi)的不同流。 WireMock
還允許您通過(guò)同一端點(diǎn)的許多不同變量來(lái)改變響應(yīng)琢岩,例如查詢參數(shù)和標(biāo)頭投剥。 查看文檔documentation以了解還有什么可能情況。
后記
本篇主要講述了Xcode中基于WireMock和UI Tests的本地API調(diào)用担孔,感興趣的給個(gè)贊或者關(guān)注~~~