ui-engine-xin 0.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.
Files changed (35) hide show
  1. ui_engine_xin-0.0.1/LICENSE +21 -0
  2. ui_engine_xin-0.0.1/MANIFEST.in +3 -0
  3. ui_engine_xin-0.0.1/PKG-INFO +239 -0
  4. ui_engine_xin-0.0.1/README.md +215 -0
  5. ui_engine_xin-0.0.1/UIEngine/__init__.py +9 -0
  6. ui_engine_xin-0.0.1/UIEngine/basecase.py +60 -0
  7. ui_engine_xin-0.0.1/UIEngine/browser/__init__.py +2 -0
  8. ui_engine_xin-0.0.1/UIEngine/browser/base_browser.py +158 -0
  9. ui_engine_xin-0.0.1/UIEngine/caseLog.py +145 -0
  10. ui_engine_xin-0.0.1/UIEngine/config/__init__.py +1 -0
  11. ui_engine_xin-0.0.1/UIEngine/config/default.yaml +6 -0
  12. ui_engine_xin-0.0.1/UIEngine/core/__init__.py +4 -0
  13. ui_engine_xin-0.0.1/UIEngine/core/exceptions.py +9 -0
  14. ui_engine_xin-0.0.1/UIEngine/core/keyword_manager.py +109 -0
  15. ui_engine_xin-0.0.1/UIEngine/core/variable_resolver.py +74 -0
  16. ui_engine_xin-0.0.1/UIEngine/keywords/__init__.py +7 -0
  17. ui_engine_xin-0.0.1/UIEngine/keywords/assert_keywords.py +172 -0
  18. ui_engine_xin-0.0.1/UIEngine/keywords/iframe_keywords.py +124 -0
  19. ui_engine_xin-0.0.1/UIEngine/keywords/locator_keywords.py +268 -0
  20. ui_engine_xin-0.0.1/UIEngine/keywords/mouse_keywords.py +74 -0
  21. ui_engine_xin-0.0.1/UIEngine/keywords/page_keywords.py +144 -0
  22. ui_engine_xin-0.0.1/UIEngine/keywords/wait_keywords.py +68 -0
  23. ui_engine_xin-0.0.1/UIEngine/reporting/__init__.py +2 -0
  24. ui_engine_xin-0.0.1/UIEngine/reporting/result.py +128 -0
  25. ui_engine_xin-0.0.1/UIEngine/runner/__init__.py +3 -0
  26. ui_engine_xin-0.0.1/UIEngine/runner/runner.py +140 -0
  27. ui_engine_xin-0.0.1/UIEngine/runner/screenshot_manager.py +67 -0
  28. ui_engine_xin-0.0.1/pyproject.toml +3 -0
  29. ui_engine_xin-0.0.1/setup.cfg +4 -0
  30. ui_engine_xin-0.0.1/setup.py +47 -0
  31. ui_engine_xin-0.0.1/ui_engine_xin.egg-info/PKG-INFO +239 -0
  32. ui_engine_xin-0.0.1/ui_engine_xin.egg-info/SOURCES.txt +33 -0
  33. ui_engine_xin-0.0.1/ui_engine_xin.egg-info/dependency_links.txt +1 -0
  34. ui_engine_xin-0.0.1/ui_engine_xin.egg-info/requires.txt +6 -0
  35. ui_engine_xin-0.0.1/ui_engine_xin.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 UIEngine Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ include LICENSE
2
+ include README.md
3
+ recursive-include UIEngine/config *.yaml
@@ -0,0 +1,239 @@
1
+ Metadata-Version: 2.1
2
+ Name: ui_engine_xin
3
+ Version: 0.0.1
4
+ Summary: 基于 Playwright 的关键字驱动 UI 自动化测试引擎
5
+ Home-page: https://pypi.org/project/ui_engine_xin/
6
+ Author: Shawn
7
+ Author-email: xiaoh0525@xiaoh.com
8
+ Keywords: python,playwright,ui-automation,keyword-driven,testing,uiEngine
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Topic :: Software Development :: Testing
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ Provides-Extra: dev
22
+ License-File: LICENSE
23
+
24
+
25
+ # UIEngine
26
+
27
+ 基于 Playwright 的关键字驱动 UI 自动化测试引擎。
28
+
29
+ ## 特性
30
+
31
+ - **关键字驱动**:通过中文/英文关键字编写测试用例,降低使用门槛
32
+ - **中英文双注册**:每个关键字同时支持中英文名称,大小写兼容
33
+ - **丰富的内置关键字**:覆盖页面操作、元素交互、等待策略、断言、iframe 等场景
34
+ - **变量替换**:支持 `${variable}` 语法引用全局变量
35
+ - **截图管理**:按套件自动创建截图目录,引擎内最多保留 10 个
36
+ - **灵活配置**:支持 dict 和 YAML 两种配置方式
37
+
38
+ ## 安装
39
+
40
+ ```bash
41
+ pip install ui-engine
42
+ playwright install
43
+ ```
44
+
45
+ ## 快速开始
46
+
47
+ ```python
48
+ from UIEngine import Runner
49
+
50
+ config = {
51
+ "is_debug": True, # True=显示浏览器,False=无头模式
52
+ "browser_type": "chromium",
53
+ "host": "http://localhost:8080",
54
+ "global_variable": {
55
+ "username": "admin",
56
+ "password": "123456"
57
+ }
58
+ }
59
+
60
+ suite = {
61
+ "id": "suite_001",
62
+ "name": "登录功能测试",
63
+ "setup_step": [
64
+ {
65
+ "desc": "打开浏览器",
66
+ "keyword": "open_browser",
67
+ "params": {"browser_type": "chromium"}
68
+ },
69
+ {
70
+ "desc": "打开登录页",
71
+ "keyword": "打开页面", # 中文关键字同样支持
72
+ "params": {"url": "/login"}
73
+ },
74
+ ],
75
+ "cases": [
76
+ {
77
+ "id": "case_001",
78
+ "name": "正确密码登录",
79
+ "skip": False,
80
+ "steps": [
81
+ {
82
+ "desc": "输入用户名",
83
+ "keyword": "fill_value",
84
+ "params": {"locator": "#username", "value": "${username}"}
85
+ },
86
+ {
87
+ "desc": "输入密码",
88
+ "keyword": "输入值", # 中文关键字
89
+ "params": {"locator": "#password", "value": "${password}"}
90
+ },
91
+ {
92
+ "desc": "点击登录",
93
+ "keyword": "click_element",
94
+ "params": {"locator": "#login-btn"}
95
+ },
96
+ {
97
+ "desc": "验证登录成功",
98
+ "keyword": "except_to_have_text",
99
+ "params": {"locator": ".welcome", "expect_results": "admin"}
100
+ }
101
+ ]
102
+ }
103
+ ]
104
+ }
105
+
106
+ result = Runner(config).run(suite)
107
+ print(result)
108
+ ```
109
+
110
+ ## 关键字列表
111
+
112
+ ### 页面操作
113
+
114
+ | 英文 | 中文 | 说明 |
115
+ |------|------|------|
116
+ | `open_url` | `打开页面` | 打开 URL |
117
+ | `refresh` | `刷新页面` | 刷新当前页面 |
118
+ | `go_back` | `返回上一页` | 浏览器后退 |
119
+ | `go_forward` | `前进下一页` | 浏览器前进 |
120
+ | `scroll_to_height` | `滚动到高度` | 滚动到指定高度 |
121
+ | `execute_script` | `执行脚本` | 执行 JavaScript |
122
+ | `download_file` | `下载文件` | 触发并等待文件下载 |
123
+ | `accept_dialog` | `接受弹窗` | 接受浏览器弹窗 |
124
+ | `dismiss_dialog` | `关闭弹窗` | 关闭浏览器弹窗 |
125
+ | `get_page_title` | `获取页面标题` | 获取当前页面标题 |
126
+ | `get_page_url` | `获取页面URL` | 获取当前页面 URL |
127
+ | `set_viewport_size` | `设置窗口大小` | 设置浏览器视口大小 |
128
+
129
+ ### 元素操作
130
+
131
+ | 英文 | 中文 | 说明 |
132
+ |------|------|------|
133
+ | `click_element` | `点击元素` | 单击元素 |
134
+ | `double_click` | `双击` | 双击元素 |
135
+ | `fill_value` | `输入值` | 输入框填值 |
136
+ | `type_text` | `输入文本` | 模拟逐字符输入 |
137
+ | `clear` | `清空输入框` | 清空输入框 |
138
+ | `hover` | `悬停` | 鼠标悬停 |
139
+ | `focus_element` | `聚焦元素` | 聚焦元素 |
140
+ | `check` | `勾选` | 勾选复选框 |
141
+ | `uncheck` | `取消勾选` | 取消勾选 |
142
+ | `select_option` | `选择选项` | 下拉框选择 |
143
+ | `select_multiple_options` | `多选下拉` | 下拉框多选 |
144
+ | `drag_and_drop` | `拖拽` | 拖拽元素 |
145
+ | `upload_file` | `上传文件` | 上传文件 |
146
+ | `scroll_to_element` | `滚动到元素` | 滚动至元素可见 |
147
+ | `highlight_element` | `高亮元素` | 高亮元素(调试用) |
148
+ | `get_text` | `获取文本` | 获取元素文本 |
149
+ | `get_attribute` | `获取属性` | 获取元素属性 |
150
+ | `get_input_value` | `获取输入值` | 获取输入框值 |
151
+ | `get_element_count` | `获取元素数量` | 获取匹配元素数量 |
152
+ | `is_visible` | `是否可见` | 查询元素可见性 |
153
+ | `is_hidden` | `是否隐藏` | 查询元素隐藏 |
154
+ | `is_enabled` | `是否可用` | 查询元素可用性 |
155
+ | `is_checked` | `是否选中` | 查询元素选中状态 |
156
+
157
+ ### 鼠标键盘
158
+
159
+ | 英文 | 中文 | 说明 |
160
+ |------|------|------|
161
+ | `mouse_click` | `鼠标点击` | 坐标点击 |
162
+ | `move_mouse` | `移动鼠标` | 坐标移动 |
163
+ | `long_click` | `长按` | 长按元素 |
164
+ | `right_click` | `右键点击` | 右键点击元素 |
165
+ | `press_key` | `按键` | 键盘按键 |
166
+ | `press_type` | `键盘输入` | 键盘输入文本 |
167
+
168
+ ### 等待
169
+
170
+ | 英文 | 中文 | 说明 |
171
+ |------|------|------|
172
+ | `wait_for_time` | `强制等待` | 固定等待 |
173
+ | `wait_for_load` | `等待加载` | 等待页面加载 |
174
+ | `wait_for_network` | `等待网络` | 等待网络空闲 |
175
+ | `wait_for_element` | `等待元素` | 等待元素可见 |
176
+ | `wait_for_element_hidden` | `等待元素消失` | 等待元素不可见 |
177
+ | `wait_for_url` | `等待URL` | 等待 URL 匹配 |
178
+
179
+ ### 断言
180
+
181
+ | 英文 | 中文 | 说明 |
182
+ |------|------|------|
183
+ | `assert_page_title` | `断言标题` | 断言页面标题 |
184
+ | `assert_page_url` | `断言URL` | 断言页面 URL |
185
+ | `except_to_have_text` | `断言有文本` | 断言元素文本 |
186
+ | `except_to_have_value` | `断言有值` | 断言元素值 |
187
+ | `except_to_be_visible` | `断言可见` | 断言元素可见 |
188
+ | `except_to_be_hidden` | `断言隐藏` | 断言元素隐藏 |
189
+ | `except_to_be_enabled` | `断言可用` | 断言元素可用 |
190
+ | `except_to_be_checked` | `断言选中` | 断言元素选中 |
191
+
192
+ ### iframe
193
+
194
+ | 英文 | 中文 | 说明 |
195
+ |------|------|------|
196
+ | `frame_click_element` | `框架点击` | iframe 内点击 |
197
+ | `frame_fill_value` | `框架输入` | iframe 内输入 |
198
+ | `switch_to_frame` | `切换iframe` | 切换到 iframe |
199
+ | `switch_to_main_frame` | `切回主页面` | 切回主页面 |
200
+
201
+ ## 动态注册关键字
202
+
203
+ ```python
204
+ from UIEngine import KeyWordManager
205
+
206
+ # 注册中英文关键字
207
+ KeyWordManager.register_keyword(
208
+ ["custom_login", "自定义登录"],
209
+ '''
210
+ def custom_login(self, username, password):
211
+ self.page.locator("#user").fill(username)
212
+ self.page.locator("#pass").fill(password)
213
+ self.page.locator("#submit").click()
214
+ '''
215
+ )
216
+ ```
217
+
218
+ ## 配置
219
+
220
+ 支持 dict 和 YAML 两种方式:
221
+
222
+ ```python
223
+ # dict 方式
224
+ config = {
225
+ "browser_type": "chromium",
226
+ "is_debug": True,
227
+ "host": "http://localhost:8080",
228
+ "global_variable": {"username": "admin"}
229
+ }
230
+
231
+ # YAML 文件方式
232
+ config = "config.yaml"
233
+
234
+ result = Runner(config).run(suite)
235
+ ```
236
+
237
+ ## License
238
+
239
+ MIT
@@ -0,0 +1,215 @@
1
+ # UIEngine
2
+
3
+ 基于 Playwright 的关键字驱动 UI 自动化测试引擎。
4
+
5
+ ## 特性
6
+
7
+ - **关键字驱动**:通过中文/英文关键字编写测试用例,降低使用门槛
8
+ - **中英文双注册**:每个关键字同时支持中英文名称,大小写兼容
9
+ - **丰富的内置关键字**:覆盖页面操作、元素交互、等待策略、断言、iframe 等场景
10
+ - **变量替换**:支持 `${variable}` 语法引用全局变量
11
+ - **截图管理**:按套件自动创建截图目录,引擎内最多保留 10 个
12
+ - **灵活配置**:支持 dict 和 YAML 两种配置方式
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ pip install ui-engine
18
+ playwright install
19
+ ```
20
+
21
+ ## 快速开始
22
+
23
+ ```python
24
+ from UIEngine import Runner
25
+
26
+ config = {
27
+ "is_debug": True, # True=显示浏览器,False=无头模式
28
+ "browser_type": "chromium",
29
+ "host": "http://localhost:8080",
30
+ "global_variable": {
31
+ "username": "admin",
32
+ "password": "123456"
33
+ }
34
+ }
35
+
36
+ suite = {
37
+ "id": "suite_001",
38
+ "name": "登录功能测试",
39
+ "setup_step": [
40
+ {
41
+ "desc": "打开浏览器",
42
+ "keyword": "open_browser",
43
+ "params": {"browser_type": "chromium"}
44
+ },
45
+ {
46
+ "desc": "打开登录页",
47
+ "keyword": "打开页面", # 中文关键字同样支持
48
+ "params": {"url": "/login"}
49
+ },
50
+ ],
51
+ "cases": [
52
+ {
53
+ "id": "case_001",
54
+ "name": "正确密码登录",
55
+ "skip": False,
56
+ "steps": [
57
+ {
58
+ "desc": "输入用户名",
59
+ "keyword": "fill_value",
60
+ "params": {"locator": "#username", "value": "${username}"}
61
+ },
62
+ {
63
+ "desc": "输入密码",
64
+ "keyword": "输入值", # 中文关键字
65
+ "params": {"locator": "#password", "value": "${password}"}
66
+ },
67
+ {
68
+ "desc": "点击登录",
69
+ "keyword": "click_element",
70
+ "params": {"locator": "#login-btn"}
71
+ },
72
+ {
73
+ "desc": "验证登录成功",
74
+ "keyword": "except_to_have_text",
75
+ "params": {"locator": ".welcome", "expect_results": "admin"}
76
+ }
77
+ ]
78
+ }
79
+ ]
80
+ }
81
+
82
+ result = Runner(config).run(suite)
83
+ print(result)
84
+ ```
85
+
86
+ ## 关键字列表
87
+
88
+ ### 页面操作
89
+
90
+ | 英文 | 中文 | 说明 |
91
+ |------|------|------|
92
+ | `open_url` | `打开页面` | 打开 URL |
93
+ | `refresh` | `刷新页面` | 刷新当前页面 |
94
+ | `go_back` | `返回上一页` | 浏览器后退 |
95
+ | `go_forward` | `前进下一页` | 浏览器前进 |
96
+ | `scroll_to_height` | `滚动到高度` | 滚动到指定高度 |
97
+ | `execute_script` | `执行脚本` | 执行 JavaScript |
98
+ | `download_file` | `下载文件` | 触发并等待文件下载 |
99
+ | `accept_dialog` | `接受弹窗` | 接受浏览器弹窗 |
100
+ | `dismiss_dialog` | `关闭弹窗` | 关闭浏览器弹窗 |
101
+ | `get_page_title` | `获取页面标题` | 获取当前页面标题 |
102
+ | `get_page_url` | `获取页面URL` | 获取当前页面 URL |
103
+ | `set_viewport_size` | `设置窗口大小` | 设置浏览器视口大小 |
104
+
105
+ ### 元素操作
106
+
107
+ | 英文 | 中文 | 说明 |
108
+ |------|------|------|
109
+ | `click_element` | `点击元素` | 单击元素 |
110
+ | `double_click` | `双击` | 双击元素 |
111
+ | `fill_value` | `输入值` | 输入框填值 |
112
+ | `type_text` | `输入文本` | 模拟逐字符输入 |
113
+ | `clear` | `清空输入框` | 清空输入框 |
114
+ | `hover` | `悬停` | 鼠标悬停 |
115
+ | `focus_element` | `聚焦元素` | 聚焦元素 |
116
+ | `check` | `勾选` | 勾选复选框 |
117
+ | `uncheck` | `取消勾选` | 取消勾选 |
118
+ | `select_option` | `选择选项` | 下拉框选择 |
119
+ | `select_multiple_options` | `多选下拉` | 下拉框多选 |
120
+ | `drag_and_drop` | `拖拽` | 拖拽元素 |
121
+ | `upload_file` | `上传文件` | 上传文件 |
122
+ | `scroll_to_element` | `滚动到元素` | 滚动至元素可见 |
123
+ | `highlight_element` | `高亮元素` | 高亮元素(调试用) |
124
+ | `get_text` | `获取文本` | 获取元素文本 |
125
+ | `get_attribute` | `获取属性` | 获取元素属性 |
126
+ | `get_input_value` | `获取输入值` | 获取输入框值 |
127
+ | `get_element_count` | `获取元素数量` | 获取匹配元素数量 |
128
+ | `is_visible` | `是否可见` | 查询元素可见性 |
129
+ | `is_hidden` | `是否隐藏` | 查询元素隐藏 |
130
+ | `is_enabled` | `是否可用` | 查询元素可用性 |
131
+ | `is_checked` | `是否选中` | 查询元素选中状态 |
132
+
133
+ ### 鼠标键盘
134
+
135
+ | 英文 | 中文 | 说明 |
136
+ |------|------|------|
137
+ | `mouse_click` | `鼠标点击` | 坐标点击 |
138
+ | `move_mouse` | `移动鼠标` | 坐标移动 |
139
+ | `long_click` | `长按` | 长按元素 |
140
+ | `right_click` | `右键点击` | 右键点击元素 |
141
+ | `press_key` | `按键` | 键盘按键 |
142
+ | `press_type` | `键盘输入` | 键盘输入文本 |
143
+
144
+ ### 等待
145
+
146
+ | 英文 | 中文 | 说明 |
147
+ |------|------|------|
148
+ | `wait_for_time` | `强制等待` | 固定等待 |
149
+ | `wait_for_load` | `等待加载` | 等待页面加载 |
150
+ | `wait_for_network` | `等待网络` | 等待网络空闲 |
151
+ | `wait_for_element` | `等待元素` | 等待元素可见 |
152
+ | `wait_for_element_hidden` | `等待元素消失` | 等待元素不可见 |
153
+ | `wait_for_url` | `等待URL` | 等待 URL 匹配 |
154
+
155
+ ### 断言
156
+
157
+ | 英文 | 中文 | 说明 |
158
+ |------|------|------|
159
+ | `assert_page_title` | `断言标题` | 断言页面标题 |
160
+ | `assert_page_url` | `断言URL` | 断言页面 URL |
161
+ | `except_to_have_text` | `断言有文本` | 断言元素文本 |
162
+ | `except_to_have_value` | `断言有值` | 断言元素值 |
163
+ | `except_to_be_visible` | `断言可见` | 断言元素可见 |
164
+ | `except_to_be_hidden` | `断言隐藏` | 断言元素隐藏 |
165
+ | `except_to_be_enabled` | `断言可用` | 断言元素可用 |
166
+ | `except_to_be_checked` | `断言选中` | 断言元素选中 |
167
+
168
+ ### iframe
169
+
170
+ | 英文 | 中文 | 说明 |
171
+ |------|------|------|
172
+ | `frame_click_element` | `框架点击` | iframe 内点击 |
173
+ | `frame_fill_value` | `框架输入` | iframe 内输入 |
174
+ | `switch_to_frame` | `切换iframe` | 切换到 iframe |
175
+ | `switch_to_main_frame` | `切回主页面` | 切回主页面 |
176
+
177
+ ## 动态注册关键字
178
+
179
+ ```python
180
+ from UIEngine import KeyWordManager
181
+
182
+ # 注册中英文关键字
183
+ KeyWordManager.register_keyword(
184
+ ["custom_login", "自定义登录"],
185
+ '''
186
+ def custom_login(self, username, password):
187
+ self.page.locator("#user").fill(username)
188
+ self.page.locator("#pass").fill(password)
189
+ self.page.locator("#submit").click()
190
+ '''
191
+ )
192
+ ```
193
+
194
+ ## 配置
195
+
196
+ 支持 dict 和 YAML 两种方式:
197
+
198
+ ```python
199
+ # dict 方式
200
+ config = {
201
+ "browser_type": "chromium",
202
+ "is_debug": True,
203
+ "host": "http://localhost:8080",
204
+ "global_variable": {"username": "admin"}
205
+ }
206
+
207
+ # YAML 文件方式
208
+ config = "config.yaml"
209
+
210
+ result = Runner(config).run(suite)
211
+ ```
212
+
213
+ ## License
214
+
215
+ MIT
@@ -0,0 +1,9 @@
1
+ """UIEngine - 基于 Playwright 的关键字驱动 UI 自动化测试引擎"""
2
+ __version__ = "0.0.1"
3
+
4
+ from UIEngine.basecase import BaseCase
5
+ from UIEngine.core.keyword_manager import KeyWordManager
6
+ from UIEngine.core.variable_resolver import VariableResolver
7
+ from UIEngine.runner.runner import Runner
8
+ from UIEngine.reporting.result import TestResult
9
+ from UIEngine.caseLog import CaseLogHandler
@@ -0,0 +1,60 @@
1
+ """BaseCase 组合类
2
+
3
+ 将所有 Mixin 组合为统一的测试用例基类。
4
+ 包含关键字调度(perform)和变量替换功能。
5
+ 所有 Mixin 方法在类定义后自动注册到 KeyWordManager。
6
+ """
7
+ from UIEngine.browser.base_browser import BaseBrowser
8
+ from UIEngine.keywords.page_keywords import PageMixin
9
+ from UIEngine.keywords.locator_keywords import LocatorMixin
10
+ from UIEngine.keywords.mouse_keywords import MouseMixin
11
+ from UIEngine.keywords.wait_keywords import WaitMixin
12
+ from UIEngine.keywords.iframe_keywords import IFrameMixin
13
+ from UIEngine.keywords.assert_keywords import AssertMixin
14
+ from UIEngine.core.keyword_manager import KeyWordManager
15
+ from UIEngine.core.variable_resolver import VariableResolver
16
+ from UIEngine.core.exceptions import KeywordNotFoundError
17
+
18
+
19
+ class BaseCase(PageMixin, LocatorMixin, MouseMixin, WaitMixin, IFrameMixin, AssertMixin):
20
+ """测试用例基类 - 组合所有关键字 Mixin
21
+
22
+ 继承链(MRO):
23
+ BaseCase → PageMixin → LocatorMixin → MouseMixin → WaitMixin
24
+ → IFrameMixin → AssertMixin → BaseBrowser
25
+ """
26
+
27
+ def __init__(self, config, log, **kwargs):
28
+ super().__init__(config, log, **kwargs)
29
+ self.variable_resolver = VariableResolver(config, log)
30
+
31
+ def perform(self, step):
32
+ """执行测试步骤
33
+
34
+ 支持两种执行模式:
35
+ 1. 关键字模式:通过 KeyWordManager.maps 查表调用(step 中使用 "keyword" 或 "method")
36
+ 2. 直接调用模式:关键字未注册时,回退到 getattr(self, method) 直接调用
37
+
38
+ 模式 2 允许调用未注册为关键字的实例方法(如 open_browser, close, reset_browser_context 等)。
39
+
40
+ :param step: 测试步骤字典,包含 keyword/method、params、desc 等字段
41
+ """
42
+ keyword = step.get("keyword") or step.get("method")
43
+ # 优先通过关键字注册表查找
44
+ method = KeyWordManager.get_keyword_maps(keyword)
45
+ if method:
46
+ params = step.get("params", {})
47
+ params = self.variable_resolver.resolve(params)
48
+ method(self, **params)
49
+ elif hasattr(self, keyword):
50
+ # 回退:直接调用实例方法(兼容未注册为关键字的方法)
51
+ params = step.get("params", {})
52
+ params = self.variable_resolver.resolve(params)
53
+ getattr(self, keyword)(**params)
54
+ else:
55
+ raise KeywordNotFoundError(f"{step.get('desc', '')}执行的关键字 '{keyword}' 不存在")
56
+
57
+
58
+ # 自动注册:将 BaseCase 的所有公共方法注册到关键字映射表
59
+ # 已通过 @register 装饰器注册的方法不会被覆盖
60
+ KeyWordManager.auto_register_methods(BaseCase)
@@ -0,0 +1,2 @@
1
+ """浏览器管理模块"""
2
+ from UIEngine.browser.base_browser import BaseBrowser