測試工具説明
起始
很早就構思這麼一個小工具, 但是在想用Java實現的時候,不知道如何能獲取XMind中的內容,XMind好像沒有提供Java解析的庫。 直到有一天上網衝浪的時候發現XMind竟然能解壓縮出JSON內容文件才開始做這個小工具。
基本描述
- 發佈此文章前查了查各類技術社區與此相關的內容,有一些零散的用Python實現的,有一些把思路簡單的講了講,還有與我思路相同的大佬, 看大佬的發佈文章的時候還是2022年初,早看到大佬的文章自己就不用走彎路了。 但是沒有看有整體技術實現過程。此文就是基於此,將整體的實現思路與實現過程描述出來,附上GitHub 項目,clone 下來之後可以立即運行使用。
- 環境 JDK11+ , 推薦使用JDK17以及以上版本
- 如果有人想在JDK8環境下運行此項目, 可以暫時將內容校驗框架validation相關的代碼刪除(轉CSV使用到了此校驗)
測試工具實現思路
總體思路描述
我覺得一個標準的測試用例最基本的就是有三個元素用例標題、操作步驟和預期結果,別管是是功能的、性能的、接口的、白盒的,用例標題用以表示這個用例是做什麼的,操作步驟和預期結果用以表示你要如何操作得出何種結果才算是證明此功能是通過你的測試。 再天馬行空的自由發揮,如果一個用例缺少了這三種的任何一項都不能叫做測試用例最多算是需求描述/需求感悟/需求理解。
在日常工作中基本不可能一個XMind畫布只描述一個用例,肯定要有一個用例所屬的目錄/項目, 所以XMind畫布中一個分支中最好有四個節點,來對應此四個字段,否則就不應該叫測試用例,比如一些需求的理解、描述等。
使用XMind思維導圖來寫測試用例看中的就是自由性,所以在轉文件的時候不能讓編寫者喪失了自由擴展節點的特性,如何保證編寫者可以自由擴展節點,就只能從分支節點的最後往前找,當找到最後一個節點時,這個節點當做預期結果,那他的父節點就作為操作步驟, 此時用例標題不應該是操作步驟的父節點,而應該是這個分支之前的所有節點的連接。這樣用以保證用例標題是獨一無二的,事實上在一個項目中用例標題就應該是這樣的,否則無法區分不同的用例要驗證的功能。
到此為止就生成了以用例步驟為基準的一條測試用例,此方法用遞歸來實現是項目最核心的方法,用以提供基礎數據。具體實現如下:
/**
* 進一步優化,獲取步驟後先獲取title再循環:
* @param xmind XMind 起始對象程序解析的數據源
* @param steps XMind 步驟集合,程序存儲的結果
* @param builders 用於步驟間標題的傳遞
* @return 將XMind轉為以步驟為基準的記錄
* */
public List<XMindStep> convertToBaseAction(XMind xmind, List<XMindStep> steps, StringBuilder builders){
List<XMind> xmindList = xmind.getChildren().getAttached();
XMindStep step = new XMindStep();
builders.append(xmind.getTitle()).append("-");
StringBuilder sb = new StringBuilder();
for (XMind var: xmindList){
// 一直遞歸到當前節點沒有子節為止
if (var.getChildren() != null){
convertToBaseAction(var, steps, builders);
}else {
// 預期結果賦值
sb.append(var.getTitle());
sb.append(System.getProperty("line.separator")); // 優化:預期結果換行
}
}
// 優化:減少不必要的代碼, 解決同一層級下,較少節點的分支刪除標題的問題
builders.replace(builders.length() - (xmind.getTitle().length() + 1), builders.length(),"");
if (!sb.toString().isEmpty()){
steps.add(step);
step.setStep(xmind.getTitle());
step.setExpectedResult(sb.toString().trim());
try {
step.setTitle(builders.substring(0, builders.length()-1));
}catch (Exception e){
throw new RuntimeException("請檢查每條記錄的層級是否足夠,每條記錄至少要保證三個節點");
}
}
return steps;
}
如果拿到最基礎的數據後,在通過一系列的規則,修剪標題,判定優先級等優化得出一個個完整的測試單元。因為用例標題是父節點的連接,所以用例標題相同的步驟一定是同一個用例,就算他們看起來是完全不同的分支。
層級
層級是一種用例所在路徑,用例屬於哪個大模塊下。當設置的層級超過XMInd畫布能容納的最大時就會報錯,默認最頂層為0級, 比如:我的畫布中節點有三個,層級卻為一級,這就把操作步驟作為一個層級(路徑)了,就會報錯。所以推薦層級最低為0級時,在代碼邏輯上節點最低為三個,個人推薦最少為四個(一個目錄節點,三個標準測試用例節點),這樣看起來比較好看。同時當前程序默認層級為二級,用以兼容最常見的場景。
預處理:解壓
具體實現如下:
try {
ZipFile zipFile = new ZipFile(xmindFileSource);
Enumeration<?> entries = zipFile.entries();
while (entries.hasMoreElements()){
ZipEntry entry = (ZipEntry) entries.nextElement();
if (entry.getName().equals(sourceFileName)){
xmindJSONToString = IOUtils.toString(new BufferedInputStream(zipFile.getInputStream(entry)),"UTF-8");
}
}
} catch (IOException e) {
e.printStackTrace(System.out.append("解壓出現問題請檢查Xmind文件"));
}
轉換策略
當前提供的轉換策略有兩種:CSV 和 EXCEL, 具體實現見:XMindExportStrategyEnum.class
Excel 轉換策略
- 橫向單元格設置策略
- 縱向單元格設置策略 CustomColumnCellStyleStrategy.class
- 列換設置策略 CustomColumnWidthStyleStrategy.class
- 單元格合併策略 ExcelMergeStrategy.class
橫向、縱向單元格樣式設置主要設置一般單元格樣式。
列換設置策略根據單元格內容調整列寬長度,用以適應各種XMind轉換結果
單個格合併策略用來實現將相同的用例不中合併到一塊,形成一個用例
具體實現較長見github源碼,其中應該有一些冗餘代碼,後續版本調整。
CSV 轉換
CSV就是生成標準的用例字符串後直接寫入到文件中
附地址
https://github.com/YongShuaiJi/test-util