1. 概述
本文將介紹 Karate,一個用於 Java 的行為驅動開發 (BDD) 測試框架。
2. Karate 和 BDD
Karate 是基於 Cucumber 構建的,另一個 BDD 測試框架,並共享一些相同的概念。 其中之一是 使用 Gherkin 文件,該文件描述了被測試的功能。 但是,與 Cucumber 不同,測試用例不使用 Java 編寫,並且完全在 Gherkin 文件中描述。
Gherkin 文件以 “.feature” 擴展名保存。 它以 Feature 關鍵字開頭,並在同一行中包含功能名稱。 它還包含不同的測試場景,每個場景以 Scenario 關鍵字開頭,並由多個步驟組成,這些步驟使用 Given, When, Then, And, 和 But 關鍵字。
關於 Cucumber 和 Gherkin 結構,請參考此處。
3. Maven 依賴與配置
為了在 Maven 項目中使用 Karate,只需添加 karate-junit4 依賴。
<dependency>
<groupId>com.intuit.karate</groupId>
<artifactId>karate-junit4</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>此外,為了使我們的 .feature 文件位於 Junit 類同一目錄下,我們需要將以下代碼添加到我們的 Maven <build> 部分:
<build>
<testResources>
<testResource>
<directory>src/test/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
<plugins>
...
</plugins>
</build>卡拉特團隊推薦這樣做,以保持測試和執行描述並排顯示,並將 .feature 文件與其他測試資源分離。
4. 創建測試
我們將首先為 Gherkin 中的一些常見場景編寫測試,這些場景存在於 Feature 文件中。
4.1. 測試狀態碼
讓我們編寫一個場景來測試一個 GET 端點並檢查它是否返回 200 (OK) HTTP 狀態碼:
Scenario: Testing valid GET endpoint
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200這顯然可以與所有可能的 HTTP 狀態碼一起工作。
4.2. 響應測試
讓我們編寫另一個場景,以測試 REST 端點返回特定響應:
Scenario: Testing the exact response of a GET endpoint
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200
And match $ == {id:"1234",name:"John Smith"}匹配操作用於驗證,其中 ‘$’ 表示響應。因此,上述場景檢查響應是否與 ‘{id:”1234″,name:”John Smith”}’ 完全匹配。
我們還可以專門檢查 id 字段的值:
And match $.id == "1234"匹配操作也可用於檢查響應是否包含特定字段。這在僅需檢查特定字段或響應字段並非全部已知時特別有用:
Scenario: Testing that GET response contains specific field
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200
And match $ contains {id:"1234"}4.3. 使用標記驗證響應值
當我們無法確定返回的具體值時,仍然可以使用標記來驗證值,這些標記是響應中匹配字段的佔位符。
例如,我們可以使用標記來指示我們是否期望null值:
- #null
- #notnull
或者,我們可以使用標記來匹配字段中的特定類型的值:
- #boolean
- #number
- #string
還有標記用於當字段預期包含 JSON 對象或數組時:
- #array
- #object
此外,還有標記用於匹配特定格式或正則表達式,以及評估布爾表達式的標記:
- #uuid — 值符合 UUID 格式
- #regex STR — 值與正則表達式 STR 匹配
- #? EXPR — 驗證 JavaScript 表達式 EXPR 是否評估為 true
最後,如果不想對字段進行任何檢查,可以使用#ignore標記。
讓我們重寫上述場景,以檢查id字段是否為null:
Scenario: Test GET request exact response
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200
And match $ == {id:"#notnull",name:"John Smith"}4.4. 使用請求體測試 POST 端點
讓我們來看一個最終場景,該場景測試一個 POST 端點並接受請求體:
Scenario: Testing a POST endpoint with request body
Given url 'http://localhost:8097/user/create'
And request { id: '1234' , name: 'John Smith'}
When method POST
Then status 200
And match $ contains {id:"#notnull"}5. 運行測試
現在測試場景已完成,我們可以通過將 Karate 與 JUnit 集成來運行我們的測試。
@RunWith(Karate.class)
public class KarateUnitTest {
//...
}為了演示 REST API,我們將使用 WireMock 服務器。
對於這個示例,我們將模擬所有在 @BeforeClass 註解方法中被測試的端點。 我們將在 @AfterClass 註解方法中關閉 WireMock 服務器:
private static WireMockServer wireMockServer
= new WireMockServer(WireMockConfiguration.options().port(8097));
@BeforeClass
public static void setUp() throws Exception {
wireMockServer.start();
configureFor("localhost", 8097);
stubFor(
get(urlEqualTo("/user/get"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{ \"id\": \"1234\", name: \"John Smith\" }")));
stubFor(
post(urlEqualTo("/user/create"))
.withHeader("content-type", equalTo("application/json"))
.withRequestBody(containing("id"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json; charset=UTF-8")
.withBody("{ \"id\": \"1234\", name: \"John Smith\" }")));
}
@AfterClass
public static void tearDown() throws Exception {
wireMockServer.stop();
}當運行
6. 結論
在本教程中,我們探討了如何使用 Karate 測試框架測試 REST API。