xmind2testcase-lq 1.5.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- xmind2testcase_lq-1.5.0.1/LICENSE +22 -0
- xmind2testcase_lq-1.5.0.1/PKG-INFO +132 -0
- xmind2testcase_lq-1.5.0.1/README.md +110 -0
- xmind2testcase_lq-1.5.0.1/pyproject.toml +42 -0
- xmind2testcase_lq-1.5.0.1/setup.cfg +4 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/__about__.py +15 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/__init__.py +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/cli.py +117 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/config.py +80 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/const.py +28 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/metadata.py +123 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/parser.py +283 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/testlink.py +158 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/utils.py +140 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/__init__.py +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/application.py +299 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/schema.sql +9 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/css/custom.css +280 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/css/pure-min.css +11 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/css/style.css +718 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/XMind/346/265/213/350/257/225/347/224/250/344/276/213/346/250/241/346/235/277.xmind +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/demo1_convert_result.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/demo2_convert_result.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/index.html +200 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/index.md +120 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/pypi_upload.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/testcase_json_demo.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/testcase_template_demo1.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/testcase_template_demo2.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/testcase_template_demo3.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/testlink.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/testlink_import_result.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/testlink_select_file.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/testlink_testcase_view.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/testsuite_json_demo.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/webtool.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/webtool_cli.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/xmind_testcase_demo.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/xmind_testcase_template_rule.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/xmind_testcase_template_rule1.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/xmind_to_testcase_preview.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/zentao_import_file.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/zentao_import_result.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/static/guide/zentao_testcase_template.png +0 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/templates/index.html +76 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/webtool/templates/preview.html +82 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq/zentao.py +152 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq.egg-info/PKG-INFO +132 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq.egg-info/SOURCES.txt +51 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq.egg-info/dependency_links.txt +1 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq.egg-info/entry_points.txt +2 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq.egg-info/requires.txt +3 -0
- xmind2testcase_lq-1.5.0.1/xmind2testcase_lq.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Devin https://zhangchuzhao.site
|
|
4
|
+
Copyright (c) 2017 Toby Qin
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xmind2testcase-lq
|
|
3
|
+
Version: 1.5.0.1
|
|
4
|
+
Summary: XMind2TestCase 的定制分支:面向禅道导入的中文测试用例转换,用例编号前缀可配置
|
|
5
|
+
Author: liqin
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitee.com/QiLi1998/xmind2testcase-lq
|
|
8
|
+
Project-URL: Repository, https://gitee.com/QiLi1998/xmind2testcase-lq
|
|
9
|
+
Project-URL: 上游项目, https://github.com/zhuifengshen/xmind2testcase
|
|
10
|
+
Keywords: xmind,testcase,zentao,testlink,思维导图,测试用例,xmind2testcase
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Natural Language :: Chinese (Simplified)
|
|
14
|
+
Classifier: Topic :: Software Development :: Testing
|
|
15
|
+
Requires-Python: >=3.8
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: xmind
|
|
19
|
+
Requires-Dist: flask
|
|
20
|
+
Requires-Dist: arrow
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# xmind2testcase-lq
|
|
24
|
+
|
|
25
|
+
> **这是 [xmind2testcase](https://github.com/zhuifengshen/xmind2testcase) 的定制分支(fork),不是上游官方版本。**
|
|
26
|
+
> 面向「XMind 思维导图 → 禅道(ZenTao)测试用例 CSV」这一条链路做了调整,
|
|
27
|
+
> 并把原本写死在源码里的项目相关信息改成了可配置项。
|
|
28
|
+
|
|
29
|
+
[](LICENSE)
|
|
30
|
+
|
|
31
|
+
## 与上游的主要差异
|
|
32
|
+
|
|
33
|
+
| 方面 | 上游 `xmind2testcase` 1.5.0 | 本分支 `xmind2testcase-lq` |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| 导入包名 | `xmind2testcase` | `xmind2testcase_lq` |
|
|
36
|
+
| 禅道 CSV 表头 | 9 列(所属模块 / 用例标题 / …) | **10 列**(用例编号 / 用例描述 / 测试类型 / 前置条件 / 操作步骤 / 期望结果 / 通过准则 / 实际输出 / 测试结论 / 测试用例优先级) |
|
|
37
|
+
| 用例编号 | 无此列 | `<前缀>-<xmind文件名>-001`,**前缀可配置** |
|
|
38
|
+
| 用例编号前缀 | — | 参数 `case_id_prefix` > 环境变量 `XMIND2TESTCASE_CASE_ID_PREFIX` > 空 |
|
|
39
|
+
| 测试类型 | `1` / `2`(手动 / 自动) | 中文类型:正向功能 / 反向功能 / 接口 / 性能 / 界面 / 安全性 |
|
|
40
|
+
| 优先级映射 | 高 / 中 / 低 | 一级 / 二级 / 三级 / 四级 |
|
|
41
|
+
| 前置条件拼接 | 用 `\n----\n` 分隔 | 直接相连(逐条去空白) |
|
|
42
|
+
| 期望结果 | 只取第一条 | 支持多条,逐条编号后用换行连接 |
|
|
43
|
+
| 只取行数据 | 无 | 新增 `xmind_to_rows()`,不落盘 |
|
|
44
|
+
| 日志文件 | 无(或写死路径) | 环境变量 `XMIND2TESTCASE_LOG` 控制,目录自动创建 |
|
|
45
|
+
| `webtool` 包位置 | 顶层包 `webtool` | 收进 `xmind2testcase_lq.webtool`,不污染全局命名空间 |
|
|
46
|
+
| CLI 命令 | `xmind2testcase` | `xmind2testcase-lq` |
|
|
47
|
+
|
|
48
|
+
完整的逐文件差异见 [FORK_NOTES.md](FORK_NOTES.md)。
|
|
49
|
+
|
|
50
|
+
## 安装
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install xmind2testcase-lq
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
从源码安装:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://gitee.com/QiLi1998/xmind2testcase-lq.git
|
|
60
|
+
cd xmind2testcase-lq
|
|
61
|
+
pip install .
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 使用
|
|
65
|
+
|
|
66
|
+
### 作为库调用
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from xmind2testcase_lq.zentao import xmind_to_rows, xmind_to_zentao_csv_file
|
|
70
|
+
|
|
71
|
+
# 不设置前缀:编号形如 登录功能-001
|
|
72
|
+
rows = xmind_to_rows("用例.xmind")
|
|
73
|
+
|
|
74
|
+
# 显式指定前缀:编号形如 我的项目-登录功能-001
|
|
75
|
+
rows = xmind_to_rows("用例.xmind", case_id_prefix="我的项目")
|
|
76
|
+
|
|
77
|
+
# 直接落盘成 CSV
|
|
78
|
+
csv_path = xmind_to_zentao_csv_file("用例.xmind", case_id_prefix="我的项目")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`rows` 第一行是表头,其后每行是一条用例。
|
|
82
|
+
|
|
83
|
+
### 通过环境变量配置
|
|
84
|
+
|
|
85
|
+
适合不想改代码、或要走命令行的情况:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Linux / macOS
|
|
89
|
+
export XMIND2TESTCASE_CASE_ID_PREFIX="我的项目"
|
|
90
|
+
|
|
91
|
+
# Windows PowerShell
|
|
92
|
+
$env:XMIND2TESTCASE_CASE_ID_PREFIX = "我的项目"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
rows = xmind_to_rows("用例.xmind") # 自动读取上面的环境变量
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 命令行
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
xmind2testcase-lq 用例.xmind -csv
|
|
103
|
+
xmind2testcase-lq 用例.xmind -csv --case-id-prefix=我的项目
|
|
104
|
+
xmind2testcase-lq 用例.xmind # 同时输出 json / xml / csv
|
|
105
|
+
xmind2testcase-lq webtool 8000 # 启动本地 Web 转换工具
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## 配置项
|
|
109
|
+
|
|
110
|
+
全部通过环境变量控制,也可以用函数参数覆盖(参数优先级更高)。
|
|
111
|
+
|
|
112
|
+
| 环境变量 | 作用 | 默认值 |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| `XMIND2TESTCASE_CASE_ID_PREFIX` | 用例编号前缀 | 空(编号不含前缀) |
|
|
115
|
+
| `XMIND2TESTCASE_LOG` | 日志文件路径,父目录不存在时自动创建 | 空(只输出到控制台) |
|
|
116
|
+
| `XMIND2TESTCASE_LOG_LEVEL` | 日志级别 | `INFO` |
|
|
117
|
+
|
|
118
|
+
> 设计原则:**源码中不出现任何本机路径或具体项目名**,所有环境相关信息都走配置。
|
|
119
|
+
|
|
120
|
+
## 已知问题
|
|
121
|
+
|
|
122
|
+
- `xmind2testcase_lq.webtool` 会把 `running.log`、`uploads/`、`data.db3`
|
|
123
|
+
写在**包目录内**(沿用上游行为)。在只读的 site-packages 或受限环境下运行
|
|
124
|
+
`xmind2testcase-lq webtool` 可能失败。命令行转换功能不受影响。
|
|
125
|
+
|
|
126
|
+
## 许可证与致谢
|
|
127
|
+
|
|
128
|
+
本项目基于 MIT 许可证发布,完整许可证文本见 [LICENSE](LICENSE)。
|
|
129
|
+
|
|
130
|
+
上游项目:[zhuifengshen/xmind2testcase](https://github.com/zhuifengshen/xmind2testcase),
|
|
131
|
+
版权归 Devin 与 Toby Qin 所有。本分支保留了原始的 MIT 版权声明,仅在
|
|
132
|
+
上游 1.5.0 基础上做了上述定制改动。
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# xmind2testcase-lq
|
|
2
|
+
|
|
3
|
+
> **这是 [xmind2testcase](https://github.com/zhuifengshen/xmind2testcase) 的定制分支(fork),不是上游官方版本。**
|
|
4
|
+
> 面向「XMind 思维导图 → 禅道(ZenTao)测试用例 CSV」这一条链路做了调整,
|
|
5
|
+
> 并把原本写死在源码里的项目相关信息改成了可配置项。
|
|
6
|
+
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
## 与上游的主要差异
|
|
10
|
+
|
|
11
|
+
| 方面 | 上游 `xmind2testcase` 1.5.0 | 本分支 `xmind2testcase-lq` |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| 导入包名 | `xmind2testcase` | `xmind2testcase_lq` |
|
|
14
|
+
| 禅道 CSV 表头 | 9 列(所属模块 / 用例标题 / …) | **10 列**(用例编号 / 用例描述 / 测试类型 / 前置条件 / 操作步骤 / 期望结果 / 通过准则 / 实际输出 / 测试结论 / 测试用例优先级) |
|
|
15
|
+
| 用例编号 | 无此列 | `<前缀>-<xmind文件名>-001`,**前缀可配置** |
|
|
16
|
+
| 用例编号前缀 | — | 参数 `case_id_prefix` > 环境变量 `XMIND2TESTCASE_CASE_ID_PREFIX` > 空 |
|
|
17
|
+
| 测试类型 | `1` / `2`(手动 / 自动) | 中文类型:正向功能 / 反向功能 / 接口 / 性能 / 界面 / 安全性 |
|
|
18
|
+
| 优先级映射 | 高 / 中 / 低 | 一级 / 二级 / 三级 / 四级 |
|
|
19
|
+
| 前置条件拼接 | 用 `\n----\n` 分隔 | 直接相连(逐条去空白) |
|
|
20
|
+
| 期望结果 | 只取第一条 | 支持多条,逐条编号后用换行连接 |
|
|
21
|
+
| 只取行数据 | 无 | 新增 `xmind_to_rows()`,不落盘 |
|
|
22
|
+
| 日志文件 | 无(或写死路径) | 环境变量 `XMIND2TESTCASE_LOG` 控制,目录自动创建 |
|
|
23
|
+
| `webtool` 包位置 | 顶层包 `webtool` | 收进 `xmind2testcase_lq.webtool`,不污染全局命名空间 |
|
|
24
|
+
| CLI 命令 | `xmind2testcase` | `xmind2testcase-lq` |
|
|
25
|
+
|
|
26
|
+
完整的逐文件差异见 [FORK_NOTES.md](FORK_NOTES.md)。
|
|
27
|
+
|
|
28
|
+
## 安装
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install xmind2testcase-lq
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
从源码安装:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git clone https://gitee.com/QiLi1998/xmind2testcase-lq.git
|
|
38
|
+
cd xmind2testcase-lq
|
|
39
|
+
pip install .
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 使用
|
|
43
|
+
|
|
44
|
+
### 作为库调用
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from xmind2testcase_lq.zentao import xmind_to_rows, xmind_to_zentao_csv_file
|
|
48
|
+
|
|
49
|
+
# 不设置前缀:编号形如 登录功能-001
|
|
50
|
+
rows = xmind_to_rows("用例.xmind")
|
|
51
|
+
|
|
52
|
+
# 显式指定前缀:编号形如 我的项目-登录功能-001
|
|
53
|
+
rows = xmind_to_rows("用例.xmind", case_id_prefix="我的项目")
|
|
54
|
+
|
|
55
|
+
# 直接落盘成 CSV
|
|
56
|
+
csv_path = xmind_to_zentao_csv_file("用例.xmind", case_id_prefix="我的项目")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`rows` 第一行是表头,其后每行是一条用例。
|
|
60
|
+
|
|
61
|
+
### 通过环境变量配置
|
|
62
|
+
|
|
63
|
+
适合不想改代码、或要走命令行的情况:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Linux / macOS
|
|
67
|
+
export XMIND2TESTCASE_CASE_ID_PREFIX="我的项目"
|
|
68
|
+
|
|
69
|
+
# Windows PowerShell
|
|
70
|
+
$env:XMIND2TESTCASE_CASE_ID_PREFIX = "我的项目"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
rows = xmind_to_rows("用例.xmind") # 自动读取上面的环境变量
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 命令行
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
xmind2testcase-lq 用例.xmind -csv
|
|
81
|
+
xmind2testcase-lq 用例.xmind -csv --case-id-prefix=我的项目
|
|
82
|
+
xmind2testcase-lq 用例.xmind # 同时输出 json / xml / csv
|
|
83
|
+
xmind2testcase-lq webtool 8000 # 启动本地 Web 转换工具
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 配置项
|
|
87
|
+
|
|
88
|
+
全部通过环境变量控制,也可以用函数参数覆盖(参数优先级更高)。
|
|
89
|
+
|
|
90
|
+
| 环境变量 | 作用 | 默认值 |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| `XMIND2TESTCASE_CASE_ID_PREFIX` | 用例编号前缀 | 空(编号不含前缀) |
|
|
93
|
+
| `XMIND2TESTCASE_LOG` | 日志文件路径,父目录不存在时自动创建 | 空(只输出到控制台) |
|
|
94
|
+
| `XMIND2TESTCASE_LOG_LEVEL` | 日志级别 | `INFO` |
|
|
95
|
+
|
|
96
|
+
> 设计原则:**源码中不出现任何本机路径或具体项目名**,所有环境相关信息都走配置。
|
|
97
|
+
|
|
98
|
+
## 已知问题
|
|
99
|
+
|
|
100
|
+
- `xmind2testcase_lq.webtool` 会把 `running.log`、`uploads/`、`data.db3`
|
|
101
|
+
写在**包目录内**(沿用上游行为)。在只读的 site-packages 或受限环境下运行
|
|
102
|
+
`xmind2testcase-lq webtool` 可能失败。命令行转换功能不受影响。
|
|
103
|
+
|
|
104
|
+
## 许可证与致谢
|
|
105
|
+
|
|
106
|
+
本项目基于 MIT 许可证发布,完整许可证文本见 [LICENSE](LICENSE)。
|
|
107
|
+
|
|
108
|
+
上游项目:[zhuifengshen/xmind2testcase](https://github.com/zhuifengshen/xmind2testcase),
|
|
109
|
+
版权归 Devin 与 Toby Qin 所有。本分支保留了原始的 MIT 版权声明,仅在
|
|
110
|
+
上游 1.5.0 基础上做了上述定制改动。
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "xmind2testcase-lq"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "XMind2TestCase 的定制分支:面向禅道导入的中文测试用例转换,用例编号前缀可配置"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "liqin" }]
|
|
14
|
+
keywords = ["xmind", "testcase", "zentao", "testlink", "思维导图", "测试用例", "xmind2testcase"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Natural Language :: Chinese (Simplified)",
|
|
19
|
+
"Topic :: Software Development :: Testing",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"xmind",
|
|
23
|
+
"flask",
|
|
24
|
+
"arrow",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://gitee.com/QiLi1998/xmind2testcase-lq"
|
|
29
|
+
Repository = "https://gitee.com/QiLi1998/xmind2testcase-lq"
|
|
30
|
+
"上游项目" = "https://github.com/zhuifengshen/xmind2testcase"
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
xmind2testcase-lq = "xmind2testcase_lq.cli:cli_main"
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.dynamic]
|
|
36
|
+
version = { attr = "xmind2testcase_lq.__about__.__version__" }
|
|
37
|
+
|
|
38
|
+
[tool.setuptools.packages.find]
|
|
39
|
+
include = ["xmind2testcase_lq*"]
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.package-data]
|
|
42
|
+
"xmind2testcase_lq.webtool" = ["schema.sql", "templates/*", "static/css/*", "static/guide/*"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
__title__ = 'xmind2testcase-lq'
|
|
2
|
+
__description__ = 'XMind2TestCase 的定制分支:面向禅道导入的中文测试用例转换,用例编号前缀可配置'
|
|
3
|
+
__keywords__ = 'xmind, testcase, zentao, testlink, 思维导图, 测试用例, xmind2testcase'
|
|
4
|
+
__url__ = 'https://gitee.com/QiLi1998/xmind2testcase-lq'
|
|
5
|
+
__author__ = 'liqin'
|
|
6
|
+
__author_email__ = ''
|
|
7
|
+
__version__ = '1.5.0.1'
|
|
8
|
+
__license__ = 'MIT'
|
|
9
|
+
__cake__ = u'\u2728 \U0001f370 \u2728'
|
|
10
|
+
|
|
11
|
+
# 上游溯源信息(MIT 许可证要求保留原始版权声明,见 LICENSE)
|
|
12
|
+
__upstream_title__ = 'xmind2testcase'
|
|
13
|
+
__upstream_version__ = '1.5.0'
|
|
14
|
+
__upstream_url__ = 'https://github.com/zhuifengshen/xmind2testcase'
|
|
15
|
+
__upstream_author__ = 'Devin'
|
|
File without changes
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# _*_ coding:utf-8 _*_
|
|
3
|
+
"""命令行入口。
|
|
4
|
+
|
|
5
|
+
与上游的差异
|
|
6
|
+
------------
|
|
7
|
+
* 日志文件路径改为由环境变量 ``XMIND2TESTCASE_LOG`` 控制(见
|
|
8
|
+
:mod:`xmind2testcase_lq.config`),**不再写死本机绝对路径**;
|
|
9
|
+
未设置时只输出到控制台。
|
|
10
|
+
* ``webtool`` 改为**延迟导入**。上游在模块顶层就 ``import webtool``,
|
|
11
|
+
而 ``webtool.application`` 在导入时会自行配置 root logger,
|
|
12
|
+
导致紧随其后的 ``logging.basicConfig`` 永远被跳过(哑配置)。
|
|
13
|
+
改为延迟导入后日志配置才真正生效,同时让不依赖 Flask 的场景可以更轻量地导入本模块。
|
|
14
|
+
* 新增 ``--case-id-prefix=XXX`` 选项,等价于设置
|
|
15
|
+
``XMIND2TESTCASE_CASE_ID_PREFIX``。
|
|
16
|
+
"""
|
|
17
|
+
import logging
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
from xmind2testcase_lq import config
|
|
22
|
+
from xmind2testcase_lq.testlink import xmind_to_testlink_xml_file
|
|
23
|
+
from xmind2testcase_lq.utils import get_absolute_path, xmind_testcase_to_json_file
|
|
24
|
+
from xmind2testcase_lq.zentao import xmind_to_zentao_csv_file
|
|
25
|
+
|
|
26
|
+
_log_file = config.resolve_log_file()
|
|
27
|
+
if _log_file:
|
|
28
|
+
Path(_log_file).parent.mkdir(parents=True, exist_ok=True)
|
|
29
|
+
logging.basicConfig(
|
|
30
|
+
level=config.resolve_log_level(),
|
|
31
|
+
filename=_log_file,
|
|
32
|
+
filemode='a',
|
|
33
|
+
format=config.LOG_FORMAT,
|
|
34
|
+
datefmt=config.LOG_DATE_FORMAT,
|
|
35
|
+
force=True,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
using_doc = """
|
|
39
|
+
Xmind2Testcase is a tool to parse xmind file into testcase file, which will help you generate a testlink recognized
|
|
40
|
+
xml file or a zentao recognized cvs file, then you can import it into testlink or zentao.
|
|
41
|
+
|
|
42
|
+
Usage:
|
|
43
|
+
xmind2testcase-lq [path_to_xmind_file] [-csv] [-xml] [-json]
|
|
44
|
+
xmind2testcase-lq [webtool] [port_num]
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
xmind2testcase-lq /path/to/testcase.xmind => output testcase.csv、testcase.xml、testcase.json
|
|
48
|
+
xmind2testcase-lq /path/to/testcase.xmind -csv => output testcase.csv
|
|
49
|
+
xmind2testcase-lq /path/to/testcase.xmind -xml => output testcase.xml
|
|
50
|
+
xmind2testcase-lq /path/to/testcase.xmind -json => output testcase.json
|
|
51
|
+
xmind2testcase-lq webtool => launch the web testcase conversion tool locally: 127.0.0.1:5001
|
|
52
|
+
xmind2testcase-lq webtool 8000 => launch the web testcase conversion tool locally: 127.0.0.1:8000
|
|
53
|
+
|
|
54
|
+
Options:
|
|
55
|
+
--case-id-prefix=<前缀> 用例编号前缀,例如 --case-id-prefix=我的项目
|
|
56
|
+
等价于设置环境变量 XMIND2TESTCASE_CASE_ID_PREFIX
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _pop_case_id_prefix(argv):
|
|
61
|
+
"""从 argv 中摘出 --case-id-prefix=XXX,返回 (剩余参数, 前缀或 None)"""
|
|
62
|
+
rest, prefix = [], None
|
|
63
|
+
for arg in argv:
|
|
64
|
+
if arg.startswith('--case-id-prefix='):
|
|
65
|
+
prefix = arg.split('=', 1)[1]
|
|
66
|
+
else:
|
|
67
|
+
rest.append(arg)
|
|
68
|
+
return rest, prefix
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def cli_main():
|
|
72
|
+
argv, case_id_prefix = _pop_case_id_prefix(sys.argv)
|
|
73
|
+
prefix = config.resolve_case_id_prefix(case_id_prefix)
|
|
74
|
+
|
|
75
|
+
if len(argv) > 1 and argv[1].endswith('.xmind'):
|
|
76
|
+
xmind_file = get_absolute_path(argv[1])
|
|
77
|
+
logging.info('Start to convert XMind file: %s', xmind_file)
|
|
78
|
+
|
|
79
|
+
if len(argv) == 3 and argv[2] == '-json':
|
|
80
|
+
testlink_json_file = xmind_testcase_to_json_file(xmind_file)
|
|
81
|
+
logging.info('Convert XMind file to testcase json file successfully: %s', testlink_json_file)
|
|
82
|
+
elif len(argv) == 3 and argv[2] == '-xml':
|
|
83
|
+
testlink_xml_file = xmind_to_testlink_xml_file(xmind_file)
|
|
84
|
+
logging.info('Convert XMind file to testlink xml files successfully: %s', testlink_xml_file)
|
|
85
|
+
elif len(argv) == 3 and argv[2] == '-csv':
|
|
86
|
+
zentao_csv_file = xmind_to_zentao_csv_file(xmind_file, case_id_prefix=prefix)
|
|
87
|
+
logging.info('Convert XMind file to zentao csv file successfully: %s', zentao_csv_file)
|
|
88
|
+
else:
|
|
89
|
+
testlink_json_file = xmind_testcase_to_json_file(xmind_file)
|
|
90
|
+
testlink_xml_file = xmind_to_testlink_xml_file(xmind_file)
|
|
91
|
+
zentao_csv_file = xmind_to_zentao_csv_file(xmind_file, case_id_prefix=prefix)
|
|
92
|
+
logging.info('Convert XMind file successfully: \n'
|
|
93
|
+
'1、 testcase json file(%s)\n'
|
|
94
|
+
'2、 testlink xml file(%s)\n'
|
|
95
|
+
'3、 zentao csv file(%s)',
|
|
96
|
+
testlink_json_file,
|
|
97
|
+
testlink_xml_file,
|
|
98
|
+
zentao_csv_file)
|
|
99
|
+
elif len(argv) > 1 and argv[1] == 'webtool':
|
|
100
|
+
# 延迟导入:避免只用命令行转换功能时也拉起 Flask 及其日志配置
|
|
101
|
+
from xmind2testcase_lq.webtool.application import launch
|
|
102
|
+
|
|
103
|
+
if len(argv) == 3:
|
|
104
|
+
try:
|
|
105
|
+
port = int(argv[2])
|
|
106
|
+
launch(port=port)
|
|
107
|
+
except ValueError:
|
|
108
|
+
launch()
|
|
109
|
+
else:
|
|
110
|
+
launch()
|
|
111
|
+
|
|
112
|
+
else:
|
|
113
|
+
print(using_doc)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
if __name__ == '__main__':
|
|
117
|
+
cli_main()
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""xmind2testcase_lq 的定制项集中配置。
|
|
2
|
+
|
|
3
|
+
为什么需要这个模块
|
|
4
|
+
------------------
|
|
5
|
+
上游代码把两处**与具体环境绑定**的值直接写死在源码里,公开发布会有问题:
|
|
6
|
+
|
|
7
|
+
* ``zentao.py`` 把用例编号前缀写死成某个内网项目名 —— 一旦发布到公共源,
|
|
8
|
+
这个名称就永久公开且无法撤回;
|
|
9
|
+
* ``cli.py`` 把日志文件写死成本机绝对路径(``D:/...``)—— 换一台机器就不成立。
|
|
10
|
+
|
|
11
|
+
本模块把这些值集中到一处,按 **显式参数 > 环境变量 > 通用默认值** 的顺序解析,
|
|
12
|
+
源码中不再出现任何本机路径或内网业务信息。
|
|
13
|
+
|
|
14
|
+
环境变量
|
|
15
|
+
--------
|
|
16
|
+
``XMIND2TESTCASE_CASE_ID_PREFIX``
|
|
17
|
+
用例编号前缀,默认空串。
|
|
18
|
+
设置后编号形如 ``<前缀>-<xmind文件名>-001``;未设置时形如 ``<xmind文件名>-001``。
|
|
19
|
+
``XMIND2TESTCASE_LOG``
|
|
20
|
+
CLI 日志文件路径,默认空串(不写文件,只输出到控制台)。父目录不存在时自动创建。
|
|
21
|
+
``XMIND2TESTCASE_LOG_LEVEL``
|
|
22
|
+
日志级别,默认 ``INFO``。
|
|
23
|
+
|
|
24
|
+
用法
|
|
25
|
+
----
|
|
26
|
+
::
|
|
27
|
+
|
|
28
|
+
import os
|
|
29
|
+
os.environ["XMIND2TESTCASE_CASE_ID_PREFIX"] = "我的项目"
|
|
30
|
+
from xmind2testcase_lq.zentao import xmind_to_rows
|
|
31
|
+
rows = xmind_to_rows("用例.xmind")
|
|
32
|
+
|
|
33
|
+
也可以绕开环境变量,直接传参(优先级更高)::
|
|
34
|
+
|
|
35
|
+
rows = xmind_to_rows("用例.xmind", case_id_prefix="我的项目")
|
|
36
|
+
"""
|
|
37
|
+
from __future__ import annotations
|
|
38
|
+
|
|
39
|
+
import logging
|
|
40
|
+
import os
|
|
41
|
+
from typing import Optional
|
|
42
|
+
|
|
43
|
+
ENV_CASE_ID_PREFIX = "XMIND2TESTCASE_CASE_ID_PREFIX"
|
|
44
|
+
ENV_LOG_FILE = "XMIND2TESTCASE_LOG"
|
|
45
|
+
ENV_LOG_LEVEL = "XMIND2TESTCASE_LOG_LEVEL"
|
|
46
|
+
|
|
47
|
+
# 内置默认值:保持通用,不含任何业务信息
|
|
48
|
+
DEFAULT_CASE_ID_PREFIX = ""
|
|
49
|
+
DEFAULT_LOG_LEVEL = "INFO"
|
|
50
|
+
|
|
51
|
+
# 与上游一致的日志格式
|
|
52
|
+
LOG_FORMAT = "%(asctime)s %(name)s %(levelname)s [%(module)s - %(funcName)s]: %(message)s"
|
|
53
|
+
LOG_DATE_FORMAT = "%Y/%m/%d %H:%M:%S"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def resolve_case_id_prefix(explicit: Optional[str] = None) -> str:
|
|
57
|
+
"""解析用例编号前缀。显式参数 > 环境变量 > 空串。"""
|
|
58
|
+
if explicit is not None:
|
|
59
|
+
return explicit.strip()
|
|
60
|
+
return os.environ.get(ENV_CASE_ID_PREFIX, DEFAULT_CASE_ID_PREFIX).strip()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def resolve_log_file(explicit: Optional[str] = None) -> str:
|
|
64
|
+
"""解析日志文件路径。返回空串表示不写文件。"""
|
|
65
|
+
if explicit is not None:
|
|
66
|
+
return explicit.strip()
|
|
67
|
+
return os.environ.get(ENV_LOG_FILE, "").strip()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def resolve_log_level(explicit: Optional[str] = None) -> int:
|
|
71
|
+
"""解析日志级别,返回 ``logging`` 模块的整型常量;无法识别时回退 INFO。"""
|
|
72
|
+
raw = explicit if explicit is not None else os.environ.get(ENV_LOG_LEVEL, DEFAULT_LOG_LEVEL)
|
|
73
|
+
name = (raw or DEFAULT_LOG_LEVEL).strip().upper()
|
|
74
|
+
return getattr(logging, name, logging.INFO)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def build_case_id(prefix: str, xmind_filename: str, case_index: int) -> str:
|
|
78
|
+
"""拼装用例编号:``<前缀>-<xmind文件名>-<三位序号>``,前缀为空时自动省略。"""
|
|
79
|
+
parts = [p for p in (prefix.strip(), xmind_filename.strip(), f"{case_index:03d}") if p]
|
|
80
|
+
return "-".join(parts)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# _*_ coding:utf-8 _*_
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
TAG_XML = 'xml'
|
|
6
|
+
|
|
7
|
+
TAG_TESTSUITE = 'testsuite'
|
|
8
|
+
TAG_DETAILS = 'details'
|
|
9
|
+
|
|
10
|
+
TAG_TESTCASE = 'testcase'
|
|
11
|
+
TAG_VERSION = 'version'
|
|
12
|
+
TAG_SUMMARY = 'summary'
|
|
13
|
+
TAG_PRECONDITIONS = 'preconditions'
|
|
14
|
+
TAG_IMPORTANCE = 'importance'
|
|
15
|
+
TAG_ESTIMATED_EXEC_DURATION = 'estimated_exec_duration'
|
|
16
|
+
TAG_STATUS = 'status'
|
|
17
|
+
TAG_IS_OPEN = 'is_open'
|
|
18
|
+
TAG_ACTIVE = 'active'
|
|
19
|
+
TAG_STEPS = 'steps'
|
|
20
|
+
TAG_STEP = 'step'
|
|
21
|
+
TAG_STEP_NUMBER = 'step_number'
|
|
22
|
+
TAG_ACTIONS = 'actions'
|
|
23
|
+
TAG_EXPECTEDRESULTS = 'expectedresults'
|
|
24
|
+
TAG_EXECUTION_TYPE = 'execution_type'
|
|
25
|
+
|
|
26
|
+
ATTR_NMAE = 'name'
|
|
27
|
+
ATTR_ID = 'id'
|
|
28
|
+
ATTR_INTERNALID = 'internalid'
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# _*_ coding:utf-8 _*_
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
testlink.testlink
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestSuite(object):
|
|
10
|
+
|
|
11
|
+
def __init__(self, name='', details='', testcase_list=None, sub_suites=None, statistics=None):
|
|
12
|
+
"""
|
|
13
|
+
TestSuite
|
|
14
|
+
:param name: test suite name
|
|
15
|
+
:param details: test suite detail infomation
|
|
16
|
+
:param testcase_list: test case list
|
|
17
|
+
:param sub_suites: sub test suite list
|
|
18
|
+
:param statistics: testsuite statistics info {'case_num': 0, 'non_execution': 0, 'pass': 0, 'failed': 0, 'blocked': 0, 'skipped': 0}
|
|
19
|
+
"""
|
|
20
|
+
self.name = name
|
|
21
|
+
self.details = details
|
|
22
|
+
self.testcase_list = testcase_list
|
|
23
|
+
self.sub_suites = sub_suites
|
|
24
|
+
self.statistics = statistics
|
|
25
|
+
|
|
26
|
+
def to_dict(self):
|
|
27
|
+
data = {
|
|
28
|
+
'name': self.name,
|
|
29
|
+
'details': self.details,
|
|
30
|
+
'testcase_list': [],
|
|
31
|
+
'sub_suites': []
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if self.sub_suites:
|
|
35
|
+
for suite in self.sub_suites:
|
|
36
|
+
data['sub_suites'].append(suite.to_dict())
|
|
37
|
+
|
|
38
|
+
if self.testcase_list:
|
|
39
|
+
for case in self.testcase_list:
|
|
40
|
+
data['testcase_list'].append(case.to_dict())
|
|
41
|
+
|
|
42
|
+
if self.statistics:
|
|
43
|
+
data['statistics'] = self.statistics
|
|
44
|
+
|
|
45
|
+
return data
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TestCase(object):
|
|
49
|
+
|
|
50
|
+
def __init__(self, name='', version=1, summary='', preconditions='', execution_type=1, importance=2, estimated_exec_duration=3, status=7, result=0, steps=None):
|
|
51
|
+
"""
|
|
52
|
+
TestCase
|
|
53
|
+
:param name: test case name
|
|
54
|
+
:param version: test case version infomation
|
|
55
|
+
:param summary: test case summary infomation
|
|
56
|
+
:param preconditions: test case pre condition
|
|
57
|
+
:param execution_type: manual:1 or automate:2
|
|
58
|
+
:param importance: high:1, middle:2, low:3
|
|
59
|
+
:param estimated_exec_duration: estimated execution duration
|
|
60
|
+
:param status: draft:1, ready ro review:2, review in progress:3, rework:4, obsolete:5, future:6, final:7
|
|
61
|
+
:param result: non-execution:0, pass:1, failed:2, blocked:3, skipped:4
|
|
62
|
+
:param steps: test case step list
|
|
63
|
+
"""
|
|
64
|
+
self.name = name
|
|
65
|
+
self.version = version
|
|
66
|
+
self.summary = summary
|
|
67
|
+
self.preconditions = preconditions
|
|
68
|
+
self.execution_type = execution_type
|
|
69
|
+
self.importance = importance
|
|
70
|
+
self.estimated_exec_duration = estimated_exec_duration
|
|
71
|
+
self.status = status
|
|
72
|
+
self.result = result
|
|
73
|
+
self.steps = steps
|
|
74
|
+
|
|
75
|
+
def to_dict(self):
|
|
76
|
+
data = {
|
|
77
|
+
'name': self.name,
|
|
78
|
+
'version': self.version, # TODO(devin): get version content
|
|
79
|
+
'summary': self.summary,
|
|
80
|
+
'preconditions': self.preconditions,
|
|
81
|
+
'execution_type': self.execution_type,
|
|
82
|
+
'importance': self.importance,
|
|
83
|
+
'estimated_exec_duration': self.estimated_exec_duration, # TODO(devin): get estimated content
|
|
84
|
+
'status': self.status, # TODO(devin): get status content
|
|
85
|
+
'result': self.result,
|
|
86
|
+
'steps': []
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if self.steps:
|
|
90
|
+
for step in self.steps:
|
|
91
|
+
data['steps'].append(step.to_dict())
|
|
92
|
+
|
|
93
|
+
return data
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class TestStep(object):
|
|
97
|
+
|
|
98
|
+
def __init__(self, step_number=1, actions='', expectedresults='', execution_type=1, result=0):
|
|
99
|
+
"""
|
|
100
|
+
TestStep
|
|
101
|
+
:param step_number: test step number
|
|
102
|
+
:param actions: test step actions
|
|
103
|
+
:param expectedresults: test step expected results
|
|
104
|
+
:param execution_type: test step execution type
|
|
105
|
+
:param result: non-execution:0, pass:1, failed:2, blocked:3, skipped:4
|
|
106
|
+
"""
|
|
107
|
+
self.step_number = step_number
|
|
108
|
+
self.actions = actions
|
|
109
|
+
self.expectedresults = expectedresults
|
|
110
|
+
self.execution_type = execution_type # TODO(devin): get execution type content
|
|
111
|
+
self.result = result
|
|
112
|
+
|
|
113
|
+
def to_dict(self):
|
|
114
|
+
data = {
|
|
115
|
+
'step_number': self.step_number,
|
|
116
|
+
'actions': self.actions,
|
|
117
|
+
'expectedresults': self.expectedresults,
|
|
118
|
+
'execution_type': self.execution_type,
|
|
119
|
+
'result': self.result
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return data
|
|
123
|
+
|