Selenium WebDriver—如何測試REST API
- 2019 年 10 月 7 日
- 筆記
前言:關於如何使用selenium webdriver測試REST api的問題,你可以在StackOverflow.com上看到很多相關的問題。不熟悉自動化測試的新人有時不理解Selenium僅僅基於WebUI做自動化測試。但是,如果你想使用Selenium為UI測試執行一些數據設置/數據清理,那麼可以通過一些額外的庫來實現這一點;這就是我們將在本文中看到內容。
Web UI測試存在的問題:
- 慢(這是因為你的瀏覽器首先向伺服器發送一個請求以獲取某些資訊,一旦獲得所需數據,可能需要一些時間來處理數據,並通過下載的圖片和應用樣式使其顯示在表格中/或者以適配的格式顯示,所以你必須等待整個過程完成之後才能與應用程式進行交互);
- 費時;
- 對於測試不同的瀏覽器,可能必須重複相同的測試集;
- 瀏覽器是獨立於selenium腳本的進程。所以同步總是一個問題;
- UI測試有很多依賴項,比如Browsers/Versions/Grid/Driver等等。
因此,這並不意味著我們應該總是做API級別的測試並發布產品;我們應該嘗試儘可能的進行API級別測試。我們可以只為UI測試提供較小覆蓋率。
REST API測試:與Selenium WebDriver UI測試相比,REST API測試並不難,大多數api都是GET / POST / PUT / PATCH / DELETE請求之一:
- GET 用於從後端獲取資訊以顯示在UI中;
- POST 用於在後端添加新資訊;
- PUT用於更新/替換任何現有資訊;
- PATCH 用於部分更新;
- DELETE 用於從後端刪除資訊。
如果你的目的是對REST api進行詳盡的測試,我建議看看JMeter。你可以查看下面關於使用JMeter進行REST API測試的文章。
- JMeter – 如何測試REST API / 微服務[2]
- JMeter – REST API Testing – 一個完整的數據驅動方法[3]
- 微服務 – 契約測試[4]
假設你使用testNG/Junit這樣的框架,並使用Selenium進行應用程式UI測試 –而現在希望在相同的框架中也包含API測試 –可能需要快速設置數據或斷言等,那麼接下來就讓我們看看如何在本文中完成。
依賴包
在maven文件中添加如下依賴:
<dependency> <groupId>com.mashape.unirest</groupId> <artifactId>unirest-java</artifactId> <version>1.4.9</version> </dependency> <dependency> <groupId>org.jtwig</groupId> <artifactId>jtwig-core</artifactId> <version>5.87.0.RELEASE</version> </dependency>
- Unirest是一個簡單的輕量級流暢式HTTP請求庫
- JTwig是一個非常簡單的模板引擎
程式示例:
我將考慮這個應用程式[5]進行測試。
【注意:本文並沒有去下載該開源項目部署到本地,而是使用了已經部署在GitHub上的該項目作為學習使用,Live Demo: https://restool-sample-app.herokuapp.com/,倘若你有興趣部署可以嘗試下自己部署】
使用Rest API列出所有可用的聯繫人,添加/編輯/刪除聯繫人;它還使用Angular構建了比較友好的UI介面;你可以克隆並部署到你的本地運行。一旦上述應用程式部署成功並啟動,就可以使用API GET請求獲取聯繫人列表,顯示在UI介面上。
1-獲取聯繫人
當您訪問應用程式的主頁時,它會列出所有可用的聯繫人。

如果監視Chrome-network中的Network,可以看到發送了一些API GET請求來獲取聯繫人列表。
- 如果你不確定在哪裡檢查,在Chrome頁面按下F12,Chrome開發工具將會出現。
- 檢查API url的header部分

F12 開發者工具
本地部署的地址 https://localhost:4200/api/contacts?q= 而本文例子使用如下Live Demo鏈接: https://restool-sample-app.herokuapp.com/
你可以看到以下格式的JSON Response:
[ { "id": "xiyydaS9CLqV", "thumbnail": "https://www.hbo.com……", "name": "Tyrion Lannister", "realName": "Peter Dinklage", "location": "Winterfell", "isAlive": true } ]
你可以通過應用程式添加聯繫人,修改聯繫人,刪除聯繫人等
2- GET Request:
一旦應用程式啟動,可以使用API GET請求獲取聯繫人列表,以便在應用程式中顯示數據。可以使用Unirest發出上面說到的GET請求,如下所示:
String searchQueryApi = "https://restool-sample-app.herokuapp.com/api/character?search="; JsonNode body = Unirest.get(searchQueryApi) .asJson() .getBody(); System.out.println(body); // 列印完整的json響應資訊 System.out.println(body.getArray().length()); // 列印item編號
其請求如下圖所示:

也可以在測試框架中進行簡單的斷言。例如下面的示例程式碼確認API響應中的所有數據是否都顯示在UI中:
driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://restool-sample-app.herokuapp.com/"); List<WebElement> contacts = driver.findElements(By.cssSelector("tbody > tr")); Assert.assertEquals(contacts.size(), body.getArray().length(), "The contacts not equals with Body length");
3- POST Request:
每當我們試圖添加新的聯繫人時,就會發送POST請求並攜帶如下格式JSON作為Body:
{ "thumbnail": "https://www.hbo.com……", "name": "Test Name", "realName": "Test Real Name", "location": "Test location", "isAlive": false }
如果你的目標是自己發送請求,那麼您可能不希望在JSON文件中硬編碼任何值。這就是我們使用JTwig模板引擎的地方。首先,我在模板下面創建。
{ "thumbnail": "{{URL}}", "name": "{{name}}", "realName": "{{realName}}", "location": "{{location}}", "isAlive": true }
我將上面的JSON保存在一個名為「contact.json」的文件中。現在我可以讀取模板並在運行時替換這些值,如下所示:
JtwigTemplate template = JtwigTemplate.classpathTemplate("contact.json"); JtwigModel model = JtwigModel.newModel() .with("URL", "http://n.sinaimg.cn/ent/transform/20160502/n4qY-fxrunru8640821.png") .with("name", "TestName") .with("realName", "TestRailName") .with("location", "Winterfell"); template.render(model);//用上述的值替換模板表達式中的值
接下來可以發送POST請求創建新的聯繫人了(發送POST請求之後,在這裡還可以通過UI介面進行檢查聯繫人是否成功顯示在UI介面,此處不做詳細Demo)
String postApi = "https://restool-sample-app.herokuapp.com/api/character"; Unirest.post(postApi) .header("accept", "application/json") .header("Content-Type", "application/json") .body(template.render(model)) .asJson();

使用上面這個方法,我們可以在應用程式中快速的添加聯繫人。
假設頁面最多只能顯示50個聯繫人,你需要點擊翻頁按鈕查看更多聯繫人,但是在本地/QA環境中,當你啟動一個新的應用程式時,可能沒有足夠的聯繫人來測試該顯示功能;如果頁面對象公開了一個方法來添加聯繫人,則需要調用50多次,通過UI介面添加聯繫人可能非常耗時,由於同步問題,它可能隨時會失敗,並且還需要處理:比如當用例重試失敗或者退出導致測試失敗等情況。
但是使用Api,您可以輕鬆地修改頁面對象,如下所示,現在你可以用它來建立數據等等。它應該比UI方法快得多,而且更不容易出錯。
class ContactsPage{ //all find bys //methods for interacting with web elements public void addContacts(int numberOfContacts){ String postApi = "https://restool-sample-app.herokuapp.com/api/character"; for(int i = 0; i<numberOfContacts; i++){ Unirest.post(postApi) .header("accept", "application/json") .header("Content-Type", "application/json") .body(template.render(model)) .asJson(); } } }
Unirest可以很容易地在page對象中使用,如上面的示例所示。
4- 編輯請求
要編輯聯繫人,我們需要發送如下所示的PUT請求。
String editApi = "https://restool-sample-app.herokuapp.com/api/character/{contact_id}"; JtwigModel model = JtwigModel.newModel() .with("name", "Snow") .with("location", "Winterfell"); Unirest.put(editApi) .routeParam("contact_id", "T2S6kHv4cS1A") .header("accept", "application/json") .header("Content-Type", "application/json") .body(template.render(model)) .asJson();
更新了Name:

5- 刪除請求
刪除就這就更簡單了。
String editApi = "https://restool-sample-app.herokuapp.com/api/character/{contact_id}"; Unirest.delete(editApi) .routeParam("contact_id", "T2S6kHv4cS1A") .asJson();
我們可以使用這個API來清理測試中新建的數據,這樣就保持測試之後的數據清潔,不會過多的新建無用甚至垃圾數據。
public class ContactsPageTest{ private String editApi = "https://localhost:4200/api/contacts/{contact_id}"; @Test public void someUItest1(){ // } @Test public void someUItest2(){ // } @AfterTest public void teardown(){ for(String contactid: listOfContacts){ Unirest.delete(editApi) .routeParam("contact_id", contactid) .asJson(); } } }
總結:通過在現有的測試框架/頁面對象中使用Unirest,可以和REST api進行交互,還可以使用這些api在應用程式中進行快速設置數據,以便進行快速功能驗證;正如上面的示例中所提到的,只要可能,就盡量使用api進行測試。