玩轉用例設計:XMind2TestCase一個高效的測試用例設計解決方案

devinzhang發表於2019-01-02

XMind2TestCase 工具,提供了一個高效測試用例設計的解決方案(開源)

一、背景

軟體測試過程中,最重要、最核心就是測試用例的設計,也是測試童鞋、測試團隊日常投入最多時間的工作內容之一。

然而,傳統的測試用例設計過程有很多痛點:

  • 1、使用Excel表格進行測試用例設計,雖然成本低,但版本管理麻煩,維護更新耗時,用例評審繁瑣,過程報表統計難...
  • 2、使用TestLink、TestCenter、Redmine等傳統測試管理工具,雖然測試用例的執行、管理、統計比較方便,但依然存在編寫用例效率不高、思路不夠發散、在產品快速迭代過程中比較耗時等問題...
  • 3、公司自研測試管理工具,這是個不錯的選擇,但對於大部分小公司、小團隊來說,一方面研發維護成本高,另一方面對技術要有一定要求...
  • 4、...

基於這些情況,現在越來越多公司選擇使用思維導圖這種高效的生產力工具進行用例設計,特別是敏捷開發團隊。

事實上也證明,思維導圖其發散性思維、圖形化思維的特點,跟測試用例設計時所需的思維非常吻合,所以在實際工作中極大提升了我們測試用例設計的效率,也非常方便測試用例評審。

但是與此同時,使用思維導圖進行測試用例設計的過程中也帶來不少問題:

  • 1、測試用例難以量化管理、執行情況難以統計;
  • 2、測試用例執行結果與BUG管理系統難以打通;
  • 3、團隊成員用思維導圖設計用例的風格各異,溝通成本巨大;
  • 4、...

綜合以上情況,我們可以發現不同的測試用例設計方式,各有各個的優劣。

那麼問題來了,我們能不能將它們各自優點合在一起呢?這樣不就可以提升我們的效率了!

於是,這時候 XMind2TestCase 就應運而生了,該工具基於 Python 實現,通過制定測試用例通用模板, 然後使用 XMind 這款廣為流傳且開源的思維導圖工具進行用例設計。 其中制定測試用例通用模板是一個非常核心的步驟(具體請看使用指南),有了通用的測試用例模板,我們就可以在 XMind 檔案上解析並提取出測試用例所需的基本資訊, 然後合成常見測試用例管理系統所需的用例匯入檔案。這樣就將 XMind 設計測試用例的便利常見測試用例系統的高效管理結合起來了!

當前 XMind2TestCase 已實現從 XMind 檔案到 TestLink 和 Zentao(禪道) 兩大常見用例管理系統的測試用例轉換,同時也提供 XMind 檔案解析後的兩種資料介面 (TestSuites、TestCases兩種級別的JSON資料),方便快速與其他測試用例管理系統打通。

二、使用示例

1、Web工具示例

webtool

2、轉換後用例預覽

testcase_preview

3、TestLink匯入結果示例

testlink

4、禪道(ZenTao)匯入結果示例

zentao

三、安裝方式

pip3 install xmind2testcase
複製程式碼

四、版本升級

pip3 install -U xmind2testcase
複製程式碼

五、使用方式

1、命令列呼叫

Usage:
 xmind2testcase [path_to_xmind_file] [-csv] [-xml] [-json]

Example:
 xmind2testcase /path/to/testcase.xmind        => output testcase.csv、testcase.xml、testcase.json
 xmind2testcase /path/to/testcase.xmind -csv   => output testcase.csv
 xmind2testcase /path/to/testcase.xmind -xml   => output testcase.xml
 xmind2testcase /path/to/testcase.xmind -json  => output testcase.json
複製程式碼

2、使用Web介面

web_tool_cli

Usage:
 xmind2testcase [webtool] [port_num]

Example:
 xmind2testcase webtool        => launch the web testcase convertion tool locally -> 127.0.0.1:5001
 xmind2testcase webtool 8000   => launch the web testcase convertion tool locally -> 127.0.0.1:8000
複製程式碼

3、API呼叫

import json
import xmind
from xmind2testcase.zentao import xmind_to_zentao_csv_file
from xmind2testcase.testlink import xmind_to_testlink_xml_file
from xmind2testcase.utils import xmind_testcase_to_json_file
from xmind2testcase.utils import xmind_testsuite_to_json_file
from xmind2testcase.utils import get_xmind_testcase_list
from xmind2testcase.utils import get_xmind_testsuite_list


def main():
    xmind_file = 'docs/xmind_testcase_template.xmind'
    print('Start to convert XMind file: %s' % xmind_file)

    zentao_csv_file = xmind_to_zentao_csv_file(xmind_file)
    print('Convert XMind file to zentao csv file successfully: %s' % zentao_csv_file)

    testlink_xml_file = xmind_to_testlink_xml_file(xmind_file)
    print('Convert XMind file to testlink xml file successfully: %s' % testlink_xml_file)

    testsuite_json_file = xmind_testsuite_to_json_file(xmind_file)
    print('Convert XMind file to testsuite json file successfully: %s' % testsuite_json_file)

    testcase_json_file = xmind_testcase_to_json_file(xmind_file)
    print('Convert XMind file to testcase json file successfully: %s' % testcase_json_file)

    testsuites = get_xmind_testsuite_list(xmind_file)
    print('Convert XMind to testsuits dict data:\n%s' % json.dumps(testsuites, indent=2, separators=(',', ': '), ensure_ascii=False))

    testcases = get_xmind_testcase_list(xmind_file)
    print('Convert Xmind to testcases dict data:\n%s' % json.dumps(testcases, indent=4, separators=(',', ': ')))

    workbook = xmind.load(xmind_file)
    print('Convert XMind to Json data:\n%s' % json.dumps(workbook.getData(), indent=2, separators=(',', ': '), ensure_ascii=False))

    print('Finished conversion, Congratulations!')


if __name__ == '__main__':
    main()
複製程式碼

4、XMind用例檔案轉為JSON資料

xmind_testcase_demo

(1)轉為測試用例JSON資料
from xmind2testcase.utils import get_xmind_testcase_list
xmind_file = 'docs/xmind_testcase_demo.xmind'
testcases = get_xmind_testcase_list(xmind_file)
print(testcases)


Output:

[
    {                                                # 測試用例
        "name": "測試用例1",                           # 用例標題
        "version": 1,                                 # 用例版本
        "summary": "測試用例1",                        # 用例摘要
        "preconditions": "前置條件",                   # 前置條件
        "execution_type": 1,                          # 用例執行型別(1:手動、2:自動)
        "importance": 1,                              # 優先順序(1:高、2:中、3:低)
        "estimated_exec_duration": 3,                 # 預計執行時間(分鐘)
        "status": 7,                                  # 用例狀態(1:草稿、2:待評審、3:評審中、4:重做、5、廢棄、6:feature、7:終稿)
        "steps": [                                    # 測試步驟列表
            {
                "step_number": 1,                     # 編號
                "actions": "測試步驟1",                 # 步驟內容
                "expectedresults": "預期結果1",         # 預期結果
                "execution_type": 1                    # 執行型別(1:手動,2:自動)
            }, 
            {
                "step_number": 2, 
                "actions": "測試步驟2", 
                "expectedresults": "預期結果2", 
                "execution_type": 1
            }
        ], 
        "product": "我是產品名",                          # 產品名稱
        "suite": "我是模組名(測試集1)"                     # 測試集(模組名)
    }, 
    {
        "name": "測試用例2", 
        "version": 1, 
        "summary": "測試用例2", 
        "preconditions": "前置條件", 
        "execution_type": 1, 
        "importance": 1, 
        "estimated_exec_duration": 3, 
        "status": 7, 
        "steps": [
            {
                "step_number": 1, 
                "actions": "測試步驟1", 
                "expectedresults": "預期結果1", 
                "execution_type": 1
            }, 
            {
                "step_number": 2, 
                "actions": "測試步驟2(預期結果2可以為空)", 
                "expectedresults": "", 
                "execution_type": 1
            }, 
            {
                "step_number": 3, 
                "actions": "測試步驟3", 
                "expectedresults": "預期結果3", 
                "execution_type": 1
            }, 
            {
                "step_number": 4, 
                "actions": "測試步驟4", 
                "expectedresults": "預期結果4", 
                "execution_type": 1
            }
        ], 
        "product": "我是產品名", 
        "suite": "我是模組名(測試集1)"
    }, 
    {
        "name": "測試用例3(測試步驟和預期結果可以都為空)", 
        "version": 1, 
        "summary": "測試用例3(測試步驟和預期結果可以都為空)", 
        "preconditions": "無", 
        "execution_type": 1, 
        "importance": 2, 
        "estimated_exec_duration": 3, 
        "status": 7, 
        "steps": [ ], 
        "product": "我是產品名", 
        "suite": "我是模組名(測試集1)"
    }, 
    {
        "name": "測試步驟2(優先順序預設為中)", 
        "version": 1, 
        "summary": "測試步驟2(優先順序預設為中)", 
        "preconditions": "無", 
        "execution_type": 1, 
        "importance": 3, 
        "estimated_exec_duration": 3, 
        "status": 7, 
        "steps": [
            {
                "step_number": 1, 
                "actions": "測試步驟1", 
                "expectedresults": "預期結果1", 
                "execution_type": 1
            }, 
            {
                "step_number": 2, 
                "actions": "測試步驟3", 
                "expectedresults": "", 
                "execution_type": 1
            }
        ], 
        "product": "我是產品名", 
        "suite": "我是模組名(測試集2)"
    }, 
    {
        "name": "測試用例3(前置條件預設為空) 無設定優先順序,這裡加入用例標題", 
        "version": 1, 
        "summary": "測試用例3(前置條件預設為空) 無設定優先順序,這裡加入用例標題", 
        "preconditions": "無", 
        "execution_type": 1, 
        "importance": 2, 
        "estimated_exec_duration": 3, 
        "status": 7, 
        "steps": [ ], 
        "product": "我是產品名", 
        "suite": "我是模組名(測試集2)"
    }
]
複製程式碼
(2)轉為測試集JSON資料
from xmind2testcase.utils import get_xmind_testsuite_list
xmind_file = 'docs/xmind_testcase_demo.xmind'
testsuites = get_xmind_testsuite_list(xmind_file)
print(testsuites)


Output:

[
  {                                                 # XMind畫布(Sheet)列表
    "name": "我是產品名",                             # 產品名稱
    "details": null,                                 # 產品摘要
    "testcase_list": [],                             # 用例列表
    "sub_suites": [                                  # 用例集列表
      {
        "name": "我是模組名(測試集1)",                  # 用例集1名稱(模組名)
        "details": null,                             # 用例集摘要
        "testcase_list": [                           # 用例列表
          {                                          # 具體用例
            "name": "測試用例1",
            "version": 1,
            "summary": "測試用例1",
            "preconditions": "前置條件",
            "execution_type": 1,
            "importance": 1,
            "estimated_exec_duration": 3,
            "status": 7,
            "steps": [
              {
                "step_number": 1,
                "actions": "測試步驟1",
                "expectedresults": "預期結果1",
                "execution_type": 1
              },
              {
                "step_number": 2,
                "actions": "測試步驟2",
                "expectedresults": "預期結果2",
                "execution_type": 1
              }
            ]
          },
          {
            "name": "測試用例2",
            "version": 1,
            "summary": "測試用例2",
            "preconditions": "前置條件",
            "execution_type": 1,
            "importance": 1,
            "estimated_exec_duration": 3,
            "status": 7,
            "steps": [
              {
                "step_number": 1,
                "actions": "測試步驟1",
                "expectedresults": "預期結果1",
                "execution_type": 1
              },
              {
                "step_number": 2,
                "actions": "測試步驟2(預期結果2可以為空)",
                "expectedresults": "",
                "execution_type": 1
              },
              {
                "step_number": 3,
                "actions": "測試步驟3",
                "expectedresults": "預期結果3",
                "execution_type": 1
              },
              {
                "step_number": 4,
                "actions": "測試步驟4",
                "expectedresults": "預期結果4",
                "execution_type": 1
              }
            ]
          },
          {
            "name": "測試用例3(測試步驟和預期結果可以都為空)",
            "version": 1,
            "summary": "測試用例3(測試步驟和預期結果可以都為空)",
            "preconditions": "無",
            "execution_type": 1,
            "importance": 2,
            "estimated_exec_duration": 3,
            "status": 7,
            "steps": []
          }
        ],
        "sub_suites": []                            # 用例集中可以包含子用例集(目前只要產品類別下有用例集)
      },
      {
        "name": "我是模組名(測試集2)",                  # 用例集2名稱(模組名)
        "details": "測試集摘要(詳情)",
        "testcase_list": [
          {
            "name": "測試步驟2(優先順序預設為中)",
            "version": 1,
            "summary": "測試步驟2(優先順序預設為中)",
            "preconditions": "無",
            "execution_type": 1,
            "importance": 3,
            "estimated_exec_duration": 3,
            "status": 7,
            "steps": [
              {
                "step_number": 1,
                "actions": "測試步驟1",
                "expectedresults": "預期結果1",
                "execution_type": 1
              },
              {
                "step_number": 2,
                "actions": "測試步驟3",
                "expectedresults": "",
                "execution_type": 1
              }
            ]
          },
          {
            "name": "測試用例3(前置條件預設為空) 無設定優先順序,這裡加入用例標題",
            "version": 1,
            "summary": "測試用例3(前置條件預設為空) 無設定優先順序,這裡加入用例標題",
            "preconditions": "無",
            "execution_type": 1,
            "importance": 2,
            "estimated_exec_duration": 3,
            "status": 7,
            "steps": []
          }
        ],
        "sub_suites": []
      }
    ]
  }
]
複製程式碼
(3)XMind檔案轉換為JSON資料

以上(1)TestCase資料、(2)TestSuite資料的獲取,其實是基於**XMind**這個工具,對XMind檔案進行解析和資料提取,然後轉換而來。 這個工具是在設計XMind2TestCase時,針對XMind單獨抽取出來的庫,提供了XMind思維導圖建立、解析、更新的一系列方法。使用它可以直接將XMind檔案轉換為JSON資料:

import xmind
xmind_file = 'docs/xmind_testcase_demo.xmind'
workbook = xmind.load(xmind_file)
data = workbook.getData()
print(data)


Output:

[
  {                                                    # XMind畫布(sheet)列表
    "id": "7hmnj6ahp0lonp4k2hodfok24f",                # 畫布ID
    "title": "畫布 1",                                  # 畫布名稱
    "topic": {                                         # 中心主題
      "id": "7c8av5gt8qfbac641lth4g1p67",              # 主題ID
      "link": null,                                    # 主題上的超連結資訊
      "title": "我是產品名",                             # 主題名稱
      "note": null,                                    # 主題上的備註資訊
      "label": null,                                   # 主題上標籤資訊
      "comment": null,                                 # 主題上的批註(評論)資訊
      "markers": [],                                   # 主題上的圖示資訊
      "topics": [                                      # 子主題列表
        {
          "id": "2rj4ek3nn4sk0lc4pje3gvgv9k",
          "link": null,
          "title": "我是模組名(測試集1)",                  # 子主題1
          "note": null,
          "label": null,
          "comment": null,
          "markers": [],
          "topics": [                                    # 子主題下的子主題列表
            {
              "id": "3hjj43s7rv66uncr1srl3qsboi",
              "link": null,
              "title": "測試用例1",
              "note": "前置條件\n",
              "label": "手動(執行方式預設為手動)",
              "comment": null,
              "markers": [
                "priority-1"
              ],
              "topics": [
                {
                  "id": "3djn37j1fdc6081de319slf035",
                  "link": null,
                  "title": "測試步驟1",
                  "note": null,
                  "label": null,
                  "comment": null,
                  "markers": [],
                  "topics": [
                    {
                      "id": "7v0f1152popou38ndaaamt49l5",
                      "link": null,
                      "title": "預期結果1",
                      "note": null,
                      "label": null,
                      "comment": null,
                      "markers": []
                    }
                  ]
                },
                {
                  "id": "2srtqqjp818clkk1drm233lank",
                  "link": null,
                  "title": "測試步驟2",
                  "note": null,
                  "label": null,
                  "comment": null,
                  "markers": [],
                  "topics": [
                    {
                      "id": "4jlbo280urmid3qkd01j7h8jnq",
                      "link": null,
                      "title": "預期結果2",
                      "note": null,
                      "label": null,
                      "comment": null,
                      "markers": []
                    }
                  ]
                }
              ]
            },
            ...
          ]
        },
        ...
      ]
    }
  }
]
複製程式碼

具體參考:xmind_testcase_demo.json

四、自動化釋出:一鍵打 Tag 並上傳至 PYPI

每次在 __ about __.py 更新版本號後,執行以下命令,實現自動化更新打包上傳至 PYPI ,同時根據其版本號自動打 Tag 並推送到倉庫:

python3 setup.py pypi
複製程式碼

upload_pypi

五、致謝

XMind2TestCase 工具的產生,受益於以下四個開源專案,並在此基礎上擴充套件、優化,受益匪淺,感恩!

  • 1、XMind:XMind思維導圖建立、解析、更新的一站式解決方案(Python實現)!
  • 2、xmind2testlink:踐行了XMind通用測試用例模板設計思路,同時提供了Web轉換工具!
  • 3、TestLink:提供了完整的測試用例管理流程和文件;
  • 4、禪道開源版(ZenTao):提供了完整的專案管理流程、文件和使用者交流釋疑群;

得益於開源,也將堅持開源,併為努力開源貢獻自己的點滴之力。後續,將繼續根據實際專案需要,定期進行更新維護, 歡迎大夥的使用意見反饋,謝謝!

(如果本專案對你有幫助的話,也歡迎 star

QA之禪

相關文章