Junit5 + YAML 參數化和數據驅動,讓 App 自動化測試更高效(一)

1. 何爲數據驅動

什麼是參數化?什麼又是數據驅動?經常有人會搞不明白他們的關係,淺談一下個人的理解,先來看兩個測試中最常見的場景:

登錄:不同的用戶名,不同的密碼,不同的組合都需要做登錄場景的測試,正常的排列組合下可能會產生多個用例

搜索:不同的搜索條件產生不同的搜索結果,搜索也是常見的測試項,單個搜索參數或者多種搜索參數的組合;同樣也會產生多個用例。

以上兩種場景都有一個共同點,就是測試的執行步驟不變,變的只是輸入的測試數據,那麼引出兩個概念——參數化和數據驅動

參數化:我們在寫自動化用例的時候會有很多方法,一般我們都會把數據通過參數來傳遞給方法,而不會直接在方法中寫“死”,所以方法之間的數據傳遞都是通過參數化來進行,利用參數化進行數據與變量的對應;比如我們的登錄賬號密碼設置在參數中,再將參數傳遞到方法中。

public MainPage login(String username, String password) {
sendKeys(inputUsername,username);
sendKeys(inputPassword,password);
click(loginBtn);
return new MainPage();
}

數據驅動:將參數化中的數據來源變成從外部讀取,參數有一個存放數據的地方,在用例執行的時候去去數據;這個數據存儲的地方可以是我們定義的數組、hashmap,也可以是從外部文件中(excel、csv、xml、yaml等)讀取。

例如上述的搜索案例,我們可以將搜索條件放入外部文件中,每次執行搜索用例時,去文件中獲取數據,根據獲取到的數據執行不同的搜索測試即可。

-
- 洗衣液
-
- 帽子
-
- 手套

總結下來:

數據驅動爲自動化測試框架的一種設計思想,而參數化是實現數據驅動的一種手段,我們利用參數化來完成數據驅動,從而將數據與腳本分離,增加了框架的可維護性和腳本的複用性。

2. 爲什麼要做數據驅動

2.1 測試數據

在執行測試工作過程中,有很多過程是需要動態變化的,如果每一次的變化都需要編碼部署,那麼整個執行的流程就會邊長;

對於業務測試工程師來說,維護自動化代碼有一定的門檻,需要熟悉編程語言和測試框架的結構;

定義好了數據驅動,將變化的數據放入配置文件中進行維護,既便捷(無需找到對應代碼修改部署),也降低了維護的門檻(業務測試只需要在配置文件中修改數據即可)

2.2 測試步驟

與測試數據的數據驅動大致相同,主要也是方便業務測試維護,降低維護門檻和代碼修改部署出錯的風險;修改配置文件,整個業務行爲和抽象是不用改變的,當然,在UI自動化中配合PO一起使用會“風味更佳”。

2.3 動態生成測試步驟

手工錄製測試步驟,直接生成代碼比較困難,可以生成步驟的配置文件,讓代碼去讀配置文件,完成自動化的回放;(此方面本人暫時僅瞭解過,還未實踐落地,理論上是可以實現的。)

3. 在哪裏做數據驅動

3.1 不要在哪裏做數據驅動

不要在測試用例內完成大量的數據驅動:用例通過PO的調用是能夠非常清晰展現出業務執行場景的,業務纔是用例的核心;一旦在用例裏使用了大量數據驅動,如調用各種yaml、csv等數據文件,會造成用例可讀性變差,維護複雜度變高;

3.2 可以在哪裏做數據驅動

1. 測試數據的數據驅動

2. 測試步驟的數據驅動

  • 定位符
  • 行爲流

3. 斷言的數據驅動

4. 如何做數據驅動

4.1 數據格式的選擇

我們要將數據存入文件中,不同的文件有着不同的數據格式,那麼作何選擇呢?

  • 不同數據格式文件的對比
Junit5 + YAML 參數化和數據驅動,讓 App 自動化測試更高效(一)

 

從上述對比結果中,Json 和 YAML 對於數據結構的支持和書寫程度是較好的;但是, YAML 的寫法更簡潔,並且還可以註釋,因此最推薦使用的就是(從表格中的所處都位置也可猜到~)…位於C位的YAML!

那麼到底什麼是YAML,又如何使用,下面簡單來了解一下

4.2 YAML 文件的使用

yaml 的語法

  • 大小寫敏感
  • 使用縮進表示層級關係
  • 縮進時不允許使用Tab鍵,只允許使用空格。
  • 縮進的空格數目不重要,只要相同層級的元素左側對齊即可
  • # 表示註釋

yaml 支持的三種數據結構

  • 純量(scalars):單個的、不可再分的值,例如數字、字符串、布爾值等
  • 對象:鍵值對的集合,又稱爲映射(mapping)/ 哈希(hashes) / 字典(dictionary)
#鍵值對形式
key: value
#行內對象
person: { name: allen, age: 25 }
  • 數組:一組按次序排列的值,又稱爲序列(sequence) / 列表(list)
#以-開頭表示爲一個數組裏的值
- A
- B
- C
#數組內嵌套子數組,用一個空格縮進表示
-
- a
- aa
-
- b
- bb
  • 對象和數組可以結合使用,形成複合結構
languages:
- Ruby
- Perl
- Python
websites:
YAML: yaml.org
Ruby: ruby-lang.org
Python: python.org
Perl: use.perl.org

4.3 數據讀取-jackson

既然有了數據存儲的地方,那麼就要對數據進行讀取,這裏就要介紹另一位幫手,Java的jackson庫

jackson是Java的一個庫,用的最多的是jackson-databind和jackson-dataformats-text,分別用來處理json和yaml數據格式,它可以將文件中的數據和Java中的對象建立一種映射關係,

把一個文件數據通過類型建立關聯,並創建出一個類的實例,反之也可以把一個對象寫入文件中。

4.3.1 jackson-databind

先來看jackson-databind對json文件的操作

添加 maven 依賴

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9.3</version>
</dependency>
  • 寫 json 文件

1)先創建一個類,包含變量name,age

public class TestFileSource {
public String name;
public int age;
}

2)創建單元測試,創建ObjectMapper對象,調用writeValue對json文件進行寫操作

@Test
void writeJson() throws IOException {
ObjectMapper mapper = new ObjectMapper();
TestFileSource testFileSource = new TestFileSource();
mapper.writeValue(new File("..\\demo.json"),testFileSource);
}

3)得到demo.json文件的結果,從結果可以看到TestFileSource類中的變量已經被寫入的json文件中

{"name":null,"age":0}
  • 讀 json 文件

1)創建單元測試,創建ObjectMapper對象,調用readValue方法對json文件進行數據讀取

@Test
void readJson() throws IOException {
ObjectMapper mapper = new ObjectMapper();
TestFileSource testFileSource = mapper.readValue(TestFileSource.class.getResourceAsStream("/demo.json"), TestFileSource.class);
System.out.println(testFileSource);
System.out.println(testFileSource.age);
}

2)讀取結果

 ApiDemos.testcase.TestFileSource@4562e04d
0
  • 輸出漂亮的 json 格式

1)創建單元測試,創建ObjectMapper對象,調用
writerWithDefaultPrettyPrinter().writeValueAsString方法可對指定對象進行json數據格式的輸出

@Test
void prettyPrintJson() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
// pretty print
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(new TestFileSource());
System.out.println(json);
}

2)打印結果

{
"name" : null,
"age" : 0
}

參考鏈接jackson-databind GitHub地址:

https://github.com/FasterXML/jackson-databind

4.3.2 jackson-dataformats-text

再來看jackson-dataformats-text,這是一個可以對YAML、CSV、Properties和XML文件進行操作的庫,也是目前最常用的,不過這裏我們只重點關注其對YAML文件的操作

  • 添加maven依賴
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.9.8</version>
</dependency>
  • 讀 YAML 文件

想要讀取 YAML 文件,最主要的是在new ObjectMapper對象的時候加入new YAMLFactory(),這樣就成功切換至 yaml 操作的狀態,然後利用readValue方法就可以完成對yaml文件的數據讀取了

1)創建 YAML 文件

name: allen
age: 11

2)創建ObjectMapper對象,設置new YAMLFactory()

@Test
void readYaml() throws IOException {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
TestFileSource testFileSource = mapper.readValue(TestFileSource.class.getResourceAsStream("/demo2.yaml"), TestFileSource.class);
System.out.println(testFileSource);
System.out.println(testFileSource.age);
}

打印結果

ApiDemos.testcase.TestFileSource@ba2f4ec
11

在readValue的方法中可以看到,第一個參數填的是文件地址,第二個參數就是精髓所在!我們可以給定一個對象類型,或者一個二維數組等,用來產生映射關係,將文件數據和我們的對象綁定,方便數據的讀取。

如上述例子中我們通過TestFileSource的實例化對象來調用age變量。

  • 輸出漂亮的 YAML 格式

與json輸出的方式基本一致,只需要在new ObjectMapper對象的時候加入new YAMLFactory()即可1)創建類和類的成員變量,包含純量、數組和哈希

public class TestFileSource {

public String name = "tester";
public int age = 2;
public Object[][] arr= {{1,2,3,},{"a","b","c"}};
public HashMap<String,Object> map = new HashMap<String, Object>(){
{
put("name","tester");
put("sex","男");
}
};
}

2)創建單元測試,創建ObjectMapper對象,加入new YAMLFactory() 參數,調用
writerWithDefaultPrettyPrinter().writeValueAsString方法可對指定對象進行yaml數據格式的輸出

@Test
void prettyPrintYaml() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
// pretty print
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(new TestFileSource());
System.out.println(json);
}

3)打印結果

---
name: "tester"
age: 2
arr:
- - 1
- 2
- 3
- - "a"
- "b"
- "c"
map:
sex: "男"
name: "tester"

(文章來源於霍格沃茲測試學院)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章