rodski 5.7.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 (125) hide show
  1. rodski-5.7.1/MANIFEST.in +19 -0
  2. rodski-5.7.1/PKG-INFO +101 -0
  3. rodski-5.7.1/README.md +93 -0
  4. rodski-5.7.1/pyproject.toml +98 -0
  5. rodski-5.7.1/rodski/LICENSE +21 -0
  6. rodski-5.7.1/rodski/README.md +56 -0
  7. rodski-5.7.1/rodski/__init__.py +2 -0
  8. rodski-5.7.1/rodski/api/__init__.py +0 -0
  9. rodski-5.7.1/rodski/api/rest_helper.py +116 -0
  10. rodski-5.7.1/rodski/cli_main.py +106 -0
  11. rodski-5.7.1/rodski/config/__init__.py +0 -0
  12. rodski-5.7.1/rodski/config/android_config.json +8 -0
  13. rodski-5.7.1/rodski/config/config.json +25 -0
  14. rodski-5.7.1/rodski/config/default_config.yaml +96 -0
  15. rodski-5.7.1/rodski/config/ios_config.json +7 -0
  16. rodski-5.7.1/rodski/config/llm_config.yaml +58 -0
  17. rodski-5.7.1/rodski/config/reviewer_config.yaml +31 -0
  18. rodski-5.7.1/rodski/config/vision_config.yaml +14 -0
  19. rodski-5.7.1/rodski/core/__init__.py +36 -0
  20. rodski-5.7.1/rodski/core/assertion/__init__.py +16 -0
  21. rodski-5.7.1/rodski/core/assertion/base_assertion.py +35 -0
  22. rodski-5.7.1/rodski/core/assertion/image_matcher.py +266 -0
  23. rodski-5.7.1/rodski/core/assertion/video_analyzer.py +271 -0
  24. rodski-5.7.1/rodski/core/browser_recycler.py +251 -0
  25. rodski-5.7.1/rodski/core/case_metadata.py +104 -0
  26. rodski-5.7.1/rodski/core/case_parser.py +159 -0
  27. rodski-5.7.1/rodski/core/condition_evaluator.py +92 -0
  28. rodski-5.7.1/rodski/core/config_manager.py +95 -0
  29. rodski-5.7.1/rodski/core/data_table_parser.py +93 -0
  30. rodski-5.7.1/rodski/core/diagnosis_engine.py +216 -0
  31. rodski-5.7.1/rodski/core/driver_factory.py +470 -0
  32. rodski-5.7.1/rodski/core/dynamic_executor.py +283 -0
  33. rodski-5.7.1/rodski/core/dynamic_steps.py +73 -0
  34. rodski-5.7.1/rodski/core/exceptions.py +408 -0
  35. rodski-5.7.1/rodski/core/execution_stats.py +81 -0
  36. rodski-5.7.1/rodski/core/global_value_parser.py +52 -0
  37. rodski-5.7.1/rodski/core/json_formatter.py +73 -0
  38. rodski-5.7.1/rodski/core/keyword_engine.py +2040 -0
  39. rodski-5.7.1/rodski/core/logger.py +81 -0
  40. rodski-5.7.1/rodski/core/loop_executor.py +202 -0
  41. rodski-5.7.1/rodski/core/metadata_writer.py +63 -0
  42. rodski-5.7.1/rodski/core/model_parser.py +306 -0
  43. rodski-5.7.1/rodski/core/parallel_executor.py +92 -0
  44. rodski-5.7.1/rodski/core/performance.py +48 -0
  45. rodski-5.7.1/rodski/core/profiler.py +85 -0
  46. rodski-5.7.1/rodski/core/recording/__init__.py +12 -0
  47. rodski-5.7.1/rodski/core/recording/recorder.py +142 -0
  48. rodski-5.7.1/rodski/core/recovery_engine.py +287 -0
  49. rodski-5.7.1/rodski/core/result_writer.py +227 -0
  50. rodski-5.7.1/rodski/core/runtime_context.py +20 -0
  51. rodski-5.7.1/rodski/core/runtime_control.py +115 -0
  52. rodski-5.7.1/rodski/core/ski_executor.py +652 -0
  53. rodski-5.7.1/rodski/core/statistics_collector.py +240 -0
  54. rodski-5.7.1/rodski/core/task_executor.py +122 -0
  55. rodski-5.7.1/rodski/core/test_case_explainer.py +1032 -0
  56. rodski-5.7.1/rodski/core/test_runner.py +269 -0
  57. rodski-5.7.1/rodski/core/xml_schema_validator.py +179 -0
  58. rodski-5.7.1/rodski/data/__init__.py +5 -0
  59. rodski-5.7.1/rodski/data/data_resolver.py +144 -0
  60. rodski-5.7.1/rodski/data/model_manager.py +90 -0
  61. rodski-5.7.1/rodski/drivers/__init__.py +39 -0
  62. rodski-5.7.1/rodski/drivers/android_driver.py +33 -0
  63. rodski-5.7.1/rodski/drivers/appium_driver.py +272 -0
  64. rodski-5.7.1/rodski/drivers/base_driver.py +356 -0
  65. rodski-5.7.1/rodski/drivers/desktop_driver.py +692 -0
  66. rodski-5.7.1/rodski/drivers/ios_driver.py +24 -0
  67. rodski-5.7.1/rodski/drivers/playwright_driver.py +629 -0
  68. rodski-5.7.1/rodski/drivers/pywinauto_driver.py +79 -0
  69. rodski-5.7.1/rodski/llm/__init__.py +10 -0
  70. rodski-5.7.1/rodski/llm/capabilities/__init__.py +23 -0
  71. rodski-5.7.1/rodski/llm/capabilities/base.py +14 -0
  72. rodski-5.7.1/rodski/llm/capabilities/screenshot_verifier.py +78 -0
  73. rodski-5.7.1/rodski/llm/capabilities/test_reviewer.py +131 -0
  74. rodski-5.7.1/rodski/llm/capabilities/vision_locator.py +62 -0
  75. rodski-5.7.1/rodski/llm/client.py +66 -0
  76. rodski-5.7.1/rodski/llm/config.py +134 -0
  77. rodski-5.7.1/rodski/llm/exceptions.py +21 -0
  78. rodski-5.7.1/rodski/llm/providers/__init__.py +17 -0
  79. rodski-5.7.1/rodski/llm/providers/base.py +38 -0
  80. rodski-5.7.1/rodski/llm/providers/claude.py +78 -0
  81. rodski-5.7.1/rodski/llm/providers/openai.py +73 -0
  82. rodski-5.7.1/rodski/reviewers/__init__.py +10 -0
  83. rodski-5.7.1/rodski/reviewers/cli.py +35 -0
  84. rodski-5.7.1/rodski/reviewers/llm_reviewer.py +149 -0
  85. rodski-5.7.1/rodski/rodski_cli/__init__.py +43 -0
  86. rodski-5.7.1/rodski/rodski_cli/config.py +50 -0
  87. rodski-5.7.1/rodski/rodski_cli/docs.py +126 -0
  88. rodski-5.7.1/rodski/rodski_cli/explain.py +129 -0
  89. rodski-5.7.1/rodski/rodski_cli/log.py +58 -0
  90. rodski-5.7.1/rodski/rodski_cli/model.py +57 -0
  91. rodski-5.7.1/rodski/rodski_cli/profile.py +57 -0
  92. rodski-5.7.1/rodski/rodski_cli/report.py +620 -0
  93. rodski-5.7.1/rodski/rodski_cli/run.py +229 -0
  94. rodski-5.7.1/rodski/rodski_cli/stats.py +305 -0
  95. rodski-5.7.1/rodski/schemas/case.xsd +128 -0
  96. rodski-5.7.1/rodski/schemas/data.xsd +56 -0
  97. rodski-5.7.1/rodski/schemas/globalvalue.xsd +48 -0
  98. rodski-5.7.1/rodski/schemas/model.xsd +177 -0
  99. rodski-5.7.1/rodski/schemas/result.xsd +104 -0
  100. rodski-5.7.1/rodski/ski_gui.py +6 -0
  101. rodski-5.7.1/rodski/ski_run.py +132 -0
  102. rodski-5.7.1/rodski/ui/__init__.py +0 -0
  103. rodski-5.7.1/rodski/utils/__init__.py +4 -0
  104. rodski-5.7.1/rodski/utils/helpers.py +29 -0
  105. rodski-5.7.1/rodski/vision/__init__.py +67 -0
  106. rodski-5.7.1/rodski/vision/ai_verifier.py +378 -0
  107. rodski-5.7.1/rodski/vision/bbox_locator.py +147 -0
  108. rodski-5.7.1/rodski/vision/cache.py +253 -0
  109. rodski-5.7.1/rodski/vision/coordinate_utils.py +315 -0
  110. rodski-5.7.1/rodski/vision/desktop_driver.py +258 -0
  111. rodski-5.7.1/rodski/vision/exceptions.py +267 -0
  112. rodski-5.7.1/rodski/vision/llm_analyzer.py +92 -0
  113. rodski-5.7.1/rodski/vision/locator.py +575 -0
  114. rodski-5.7.1/rodski/vision/matcher.py +136 -0
  115. rodski-5.7.1/rodski/vision/ocr_locator.py +333 -0
  116. rodski-5.7.1/rodski/vision/omni_client.py +220 -0
  117. rodski-5.7.1/rodski/vision/screen_recorder.py +210 -0
  118. rodski-5.7.1/rodski/vision/screenshot.py +148 -0
  119. rodski-5.7.1/rodski.egg-info/PKG-INFO +101 -0
  120. rodski-5.7.1/rodski.egg-info/SOURCES.txt +123 -0
  121. rodski-5.7.1/rodski.egg-info/dependency_links.txt +1 -0
  122. rodski-5.7.1/rodski.egg-info/entry_points.txt +2 -0
  123. rodski-5.7.1/rodski.egg-info/requires.txt +29 -0
  124. rodski-5.7.1/rodski.egg-info/top_level.txt +1 -0
  125. rodski-5.7.1/setup.cfg +4 -0
@@ -0,0 +1,19 @@
1
+ include rodski/LICENSE
2
+ include rodski/README.md
3
+
4
+ recursive-include rodski/schemas *.xsd
5
+ recursive-include rodski/config *.yaml *.json
6
+
7
+ prune rodski/tests
8
+ prune rodski/docs
9
+ prune rodski/examples
10
+ prune rodski/scripts
11
+ prune rodski/images
12
+ prune rodski/rodski_docs
13
+
14
+ exclude rodski/.flake8
15
+ exclude rodski/bandit.yaml
16
+ exclude rodski/mypy.ini
17
+ exclude rodski/pytest.ini
18
+ exclude rodski/selftest.py
19
+ exclude rodski/requirements.txt
rodski-5.7.1/PKG-INFO ADDED
@@ -0,0 +1,101 @@
1
+ Metadata-Version: 2.4
2
+ Name: rodski
3
+ Version: 5.7.1
4
+ Summary: RodSki - XML-driven keyword automation testing framework for AI agents
5
+ Author: Lightning Strike Team
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/user/RodSki
8
+ Project-URL: Repository, https://github.com/user/RodSki
9
+ Keywords: testing,automation,keyword-driven,xml,playwright,appium,ai-agent,test-framework
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Testing
20
+ Classifier: Topic :: Software Development :: Quality Assurance
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: xmlschema>=2.5.0
24
+ Requires-Dist: pyyaml>=6.0.0
25
+ Requires-Dist: tqdm>=4.65.0
26
+ Requires-Dist: psutil>=5.9.0
27
+ Requires-Dist: requests>=2.31.0
28
+ Provides-Extra: web
29
+ Requires-Dist: playwright>=1.40.0; extra == "web"
30
+ Provides-Extra: mobile
31
+ Requires-Dist: Appium-Python-Client>=3.0.0; extra == "mobile"
32
+ Provides-Extra: gui
33
+ Requires-Dist: PyQt6>=6.6.0; extra == "gui"
34
+ Provides-Extra: vision
35
+ Requires-Dist: pillow>=10.0.0; extra == "vision"
36
+ Provides-Extra: llm
37
+ Requires-Dist: anthropic>=0.18.0; extra == "llm"
38
+ Requires-Dist: openai>=1.12.0; extra == "llm"
39
+ Provides-Extra: dev
40
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
41
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
42
+ Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
43
+ Provides-Extra: all
44
+ Requires-Dist: rodski[gui,llm,mobile,vision,web]; extra == "all"
45
+
46
+ # RodSki - 自动化测试框架
47
+
48
+ 基于关键字驱动的现代化自动化测试框架,Python 重写版本。
49
+
50
+ ## 特性
51
+
52
+ - 🎯 关键字驱动 - 简单易用的测试语法
53
+ - 🔧 模型驱动 - 模型与数据分离
54
+ - 🌐 多驱动支持 - Playwright (Web) + PyWinAuto (Desktop) + Appium (Mobile)
55
+ - 📊 XML 用例 - 结构化测试定义
56
+ - 🔌 RESTful API - 接口测试支持
57
+
58
+ ## 快速开始
59
+
60
+ 📖 **[5分钟快速入门指南](docs/user-guides/QUICKSTART.md)** - 新手必读!
61
+
62
+ ### 安装
63
+
64
+ ```bash
65
+ pip install -r requirements.txt
66
+ playwright install chromium
67
+ ```
68
+
69
+ ### CLI 运行
70
+
71
+ ```bash
72
+ python3 cli_main.py run examples/product/DEMO/demo_site/case/demo_case.xml
73
+ ```
74
+
75
+ ## 项目结构
76
+
77
+ ```
78
+ rodski/
79
+ ├── core/ # 核心引擎
80
+ ├── drivers/ # 驱动层
81
+ ├── api/ # API 测试
82
+ ├── config/ # 配置
83
+ ├── data/ # 测试数据
84
+ ├── examples/ # 示例用例
85
+ └── docs/ # 文档
86
+ ```
87
+
88
+ ## 开发
89
+
90
+ ### 环境要求
91
+
92
+ - Python 3.8+
93
+ - Playwright
94
+
95
+ ### 贡献
96
+
97
+ 欢迎提交 Issue 和 Pull Request!
98
+
99
+ ## 许可证
100
+
101
+ MIT License
rodski-5.7.1/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # RodSki
2
+
3
+ **RodSki** 是面向 AI Agent 的跨平台确定性测试执行引擎,基于 XML 活文档协议,支持 Web(Playwright)、Android(Appium)、iOS(Appium)和桌面应用(PyWinAuto)的自动化测试执行。
4
+
5
+ > Agent 负责思考,RodSki 负责稳定执行。
6
+
7
+ ## 特性
8
+
9
+ - **结构化 XML 协议** — model / case / data 活文档,Agent 可读可写
10
+ - **多平台确定性执行** — Web / Android / iOS / Desktop 统一关键字
11
+ - **视觉定位能力** — OmniParser + LLM 语义定位(可选 AI 能力层)
12
+ - **Agent 友好 CLI** — run / validate / explain / dry-run,JSON 结构化输出
13
+ - **活文档模式** — Agent 写 XML → RodSki 执行 → 结果反馈 → Agent 分析
14
+ - **智能等待** — 自动处理元素加载延迟,零配置开箱即用
15
+ - **智能诊断** — AI 辅助失败分析与恢复建议(可选)
16
+
17
+ ## 快速开始
18
+
19
+ ```bash
20
+ # 安装
21
+ pip install -r requirements.txt
22
+
23
+ # 执行测试
24
+ rodski run case/ --output-format json
25
+
26
+ # 解释用例(自然语言)
27
+ rodski explain case/login.xml
28
+
29
+ # 干跑模式(仅验证不执行)
30
+ rodski run case/ --dry-run
31
+
32
+ # 详细输出
33
+ rodski run case/ --verbose
34
+ ```
35
+
36
+ ## 架构概览
37
+
38
+ ```
39
+ Agent (探索/决策) → XML (活文档) → RodSki (执行) → JSON (结果) → Agent (分析)
40
+ ```
41
+
42
+ RodSki 作为 Agent 工具链中的执行层,提供确定性、可重复的测试执行能力。Agent 通过 XML 协议描述测试意图,RodSki 负责跨平台执行并以 JSON 格式返回结构化结果,供 Agent 进一步分析和决策。
43
+
44
+ ## 项目结构
45
+
46
+ ```
47
+ RodSki/
48
+ ├── rodski/ # 核心框架
49
+ │ ├── core/ # 执行引擎(关键字、解析器、诊断)
50
+ │ ├── drivers/ # 平台驱动(Playwright/Appium/PyWinAuto)
51
+ │ ├── llm/ # LLM 能力层(可选)
52
+ │ ├── vision/ # 视觉定位(可选)
53
+ │ ├── rodski_cli/ # CLI 子命令
54
+ │ ├── config/ # 配置文件
55
+ │ └── docs/ # 框架文档
56
+ ├── rodski-demo/ # 官方示例
57
+ └── .pb/ # 项目管理文档
58
+ ```
59
+
60
+ ## 文档
61
+
62
+ | 文档 | 说明 |
63
+ |------|------|
64
+ | [Agent 集成指南](rodski/docs/AGENT_INTEGRATION.md) | Agent 接入主入口 |
65
+ | [用例编写指南](rodski/docs/TEST_CASE_WRITING_GUIDE.md) | XML 用例编写规范 |
66
+ | [核心设计约束](rodski/docs/CORE_DESIGN_CONSTRAINTS.md) | 框架不可违反的设计约束 |
67
+ | [关键字参考](rodski/docs/SKILL_REFERENCE.md) | 全部关键字语法说明 |
68
+ | [架构说明](rodski/docs/ARCHITECTURE.md) | 框架内部架构 |
69
+ | [视觉定位](rodski/docs/VISION_LOCATION.md) | OmniParser 视觉定位能力 |
70
+
71
+ ## 智能等待
72
+
73
+ RodSki 内置智能等待机制,自动处理 UI 元素的加载延迟,无需手动添加等待步骤。
74
+
75
+ - **零配置** — 默认启用,开箱即用
76
+ - **性能优化** — 元素就绪时立即执行,不浪费时间
77
+ - **自动重试** — 元素未加载时自动重试(默认 30 次 x 300ms = 9 秒)
78
+ - **可配置** — 支持自定义重试次数和间隔
79
+
80
+ 配置项位于 `rodski/config/config.json`:
81
+
82
+ ```json
83
+ {
84
+ "smart_wait_enabled": true,
85
+ "smart_wait_max_retries": 30,
86
+ "smart_wait_retry_interval": 0.3,
87
+ "smart_wait_log_retry": true
88
+ }
89
+ ```
90
+
91
+ ## License
92
+
93
+ MIT License - 详见 [LICENSE](rodski/LICENSE)
@@ -0,0 +1,98 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "rodski"
7
+ version = "5.7.1"
8
+ description = "RodSki - XML-driven keyword automation testing framework for AI agents"
9
+ readme = {file = "rodski/README.md", content-type = "text/markdown"}
10
+ license = "MIT"
11
+ requires-python = ">=3.9"
12
+ authors = [
13
+ {name = "Lightning Strike Team"},
14
+ ]
15
+ keywords = [
16
+ "testing", "automation", "keyword-driven", "xml", "playwright",
17
+ "appium", "ai-agent", "test-framework",
18
+ ]
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Intended Audience :: Developers",
22
+ "Operating System :: OS Independent",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.9",
25
+ "Programming Language :: Python :: 3.10",
26
+ "Programming Language :: Python :: 3.11",
27
+ "Programming Language :: Python :: 3.12",
28
+ "Programming Language :: Python :: 3.13",
29
+ "Topic :: Software Development :: Testing",
30
+ "Topic :: Software Development :: Quality Assurance",
31
+ ]
32
+
33
+ dependencies = [
34
+ "xmlschema>=2.5.0",
35
+ "pyyaml>=6.0.0",
36
+ "tqdm>=4.65.0",
37
+ "psutil>=5.9.0",
38
+ "requests>=2.31.0",
39
+ ]
40
+
41
+ [project.optional-dependencies]
42
+ web = ["playwright>=1.40.0"]
43
+ mobile = ["Appium-Python-Client>=3.0.0"]
44
+ gui = ["PyQt6>=6.6.0"]
45
+ vision = ["pillow>=10.0.0"]
46
+ llm = ["anthropic>=0.18.0", "openai>=1.12.0"]
47
+ dev = ["pytest>=7.4.0", "pytest-cov>=4.1.0", "pytest-mock>=3.12.0"]
48
+ all = ["rodski[web,mobile,gui,vision,llm]"]
49
+
50
+ [project.scripts]
51
+ rodski = "rodski.cli_main:main"
52
+
53
+ [project.urls]
54
+ Homepage = "https://github.com/user/RodSki"
55
+ Repository = "https://github.com/user/RodSki"
56
+
57
+ [tool.setuptools.packages.find]
58
+ include = ["rodski", "rodski.*"]
59
+ exclude = [
60
+ "rodski.tests", "rodski.tests.*",
61
+ "rodski.docs", "rodski.docs.*",
62
+ "rodski.examples", "rodski.examples.*",
63
+ "rodski.scripts", "rodski.scripts.*",
64
+ "rodski.images", "rodski.images.*",
65
+ "rodski.rodski_docs", "rodski.rodski_docs.*",
66
+ ]
67
+
68
+ [tool.setuptools.package-data]
69
+ rodski = [
70
+ "schemas/*.xsd",
71
+ "config/*.yaml",
72
+ "config/*.json",
73
+ ]
74
+
75
+ [tool.black]
76
+ line-length = 120
77
+ target-version = ['py39']
78
+ exclude = '''
79
+ /(
80
+ \.git
81
+ | \.venv
82
+ | venv
83
+ | build
84
+ | dist
85
+ )/
86
+ '''
87
+
88
+ [tool.isort]
89
+ profile = "black"
90
+ line_length = 120
91
+
92
+ [tool.coverage.run]
93
+ source = ["rodski"]
94
+ omit = ["*/tests/*", "*/demo_*/*"]
95
+
96
+ [tool.coverage.report]
97
+ fail_under = 80
98
+ precision = 2
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lightning Strike Team
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,56 @@
1
+ # RodSki - 自动化测试框架
2
+
3
+ 基于关键字驱动的现代化自动化测试框架,Python 重写版本。
4
+
5
+ ## 特性
6
+
7
+ - 🎯 关键字驱动 - 简单易用的测试语法
8
+ - 🔧 模型驱动 - 模型与数据分离
9
+ - 🌐 多驱动支持 - Playwright (Web) + PyWinAuto (Desktop) + Appium (Mobile)
10
+ - 📊 XML 用例 - 结构化测试定义
11
+ - 🔌 RESTful API - 接口测试支持
12
+
13
+ ## 快速开始
14
+
15
+ 📖 **[5分钟快速入门指南](docs/user-guides/QUICKSTART.md)** - 新手必读!
16
+
17
+ ### 安装
18
+
19
+ ```bash
20
+ pip install -r requirements.txt
21
+ playwright install chromium
22
+ ```
23
+
24
+ ### CLI 运行
25
+
26
+ ```bash
27
+ python3 cli_main.py run examples/product/DEMO/demo_site/case/demo_case.xml
28
+ ```
29
+
30
+ ## 项目结构
31
+
32
+ ```
33
+ rodski/
34
+ ├── core/ # 核心引擎
35
+ ├── drivers/ # 驱动层
36
+ ├── api/ # API 测试
37
+ ├── config/ # 配置
38
+ ├── data/ # 测试数据
39
+ ├── examples/ # 示例用例
40
+ └── docs/ # 文档
41
+ ```
42
+
43
+ ## 开发
44
+
45
+ ### 环境要求
46
+
47
+ - Python 3.8+
48
+ - Playwright
49
+
50
+ ### 贡献
51
+
52
+ 欢迎提交 Issue 和 Pull Request!
53
+
54
+ ## 许可证
55
+
56
+ MIT License
@@ -0,0 +1,2 @@
1
+ """RodSki Test Framework"""
2
+ __version__ = "5.7.1"
File without changes
@@ -0,0 +1,116 @@
1
+ """RESTful API 测试辅助工具"""
2
+ import json
3
+ import logging
4
+ from typing import Any, Dict, List, Optional
5
+ from jsonschema import validate, ValidationError
6
+ import requests
7
+ from requests.adapters import HTTPAdapter
8
+ from urllib3.util.retry import Retry
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class RestHelper:
14
+ """REST API 测试辅助类"""
15
+
16
+ @staticmethod
17
+ def _get_session(max_retries: int = 3, pool_connections: int = 10, pool_maxsize: int = 10) -> requests.Session:
18
+ """获取配置了连接池和重试的 Session"""
19
+ session = requests.Session()
20
+ retry_strategy = Retry(
21
+ total=max_retries,
22
+ backoff_factor=0.3,
23
+ status_forcelist=[429, 500, 502, 503, 504],
24
+ )
25
+ adapter = HTTPAdapter(max_retries=retry_strategy, pool_connections=pool_connections, pool_maxsize=pool_maxsize)
26
+ session.mount("http://", adapter)
27
+ session.mount("https://", adapter)
28
+ return session
29
+
30
+ @staticmethod
31
+ def validate_json_schema(data: Dict, schema: Dict) -> bool:
32
+ """验证 JSON Schema"""
33
+ try:
34
+ validate(instance=data, schema=schema)
35
+ return True
36
+ except ValidationError:
37
+ return False
38
+
39
+ @staticmethod
40
+ def jsonpath_extract(data: Dict, path: str) -> Any:
41
+ """简单 JSONPath 提取(支持点号路径)"""
42
+ keys = path.strip('$.').split('.')
43
+ current = data
44
+ for key in keys:
45
+ if isinstance(current, dict):
46
+ current = current.get(key)
47
+ else:
48
+ return None
49
+ return current
50
+
51
+ @staticmethod
52
+ def send_request(
53
+ method: str,
54
+ url: str,
55
+ headers: Optional[Dict[str, str]] = None,
56
+ body: Any = None,
57
+ timeout: float = 30.0,
58
+ max_retries: int = 3,
59
+ use_session: bool = True,
60
+ cookies: Optional[Dict[str, str]] = None,
61
+ ) -> requests.Response:
62
+ """发送 HTTP 请求"""
63
+ method = method.upper()
64
+ kwargs: Dict[str, Any] = {"headers": headers, "timeout": timeout}
65
+ if body is not None:
66
+ kwargs["json"] = body
67
+ if cookies:
68
+ kwargs["cookies"] = cookies
69
+
70
+ try:
71
+ logger.debug(f"Sending {method} request to {url}")
72
+ if use_session:
73
+ session = RestHelper._get_session(max_retries=max_retries)
74
+ response = session.request(method, url, **kwargs)
75
+ else:
76
+ response = requests.request(method, url, **kwargs)
77
+ logger.debug(f"Response: {response.status_code} in {response.elapsed.total_seconds():.3f}s")
78
+ return response
79
+ except requests.exceptions.Timeout as e:
80
+ logger.error(f"Request timeout: {url}")
81
+ raise
82
+ except requests.exceptions.ConnectionError as e:
83
+ logger.error(f"Connection error: {url}")
84
+ raise
85
+ except requests.exceptions.RequestException as e:
86
+ logger.error(f"Request failed: {url} - {str(e)}")
87
+ raise
88
+
89
+ @staticmethod
90
+ def assert_response_time(response: requests.Response, max_ms: float) -> bool:
91
+ """断言响应时间(毫秒)"""
92
+ elapsed_ms = response.elapsed.total_seconds() * 1000
93
+ return elapsed_ms <= max_ms
94
+
95
+ @staticmethod
96
+ def extract_headers(response: requests.Response, header_name: str) -> Optional[str]:
97
+ """提取响应头"""
98
+ return response.headers.get(header_name)
99
+
100
+ @staticmethod
101
+ def compare_responses(
102
+ resp1: Dict,
103
+ resp2: Dict,
104
+ ignore_fields: Optional[List[str]] = None,
105
+ ) -> bool:
106
+ """比较两个响应(忽略指定字段)"""
107
+ ignore_fields = ignore_fields or []
108
+
109
+ def _strip(d: Any) -> Any:
110
+ if isinstance(d, dict):
111
+ return {k: _strip(v) for k, v in d.items() if k not in ignore_fields}
112
+ if isinstance(d, list):
113
+ return [_strip(i) for i in d]
114
+ return d
115
+
116
+ return _strip(resp1) == _strip(resp2)
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env python3
2
+ """RodSki CLI 入口"""
3
+ import sys
4
+ import argparse
5
+ import traceback
6
+ from .rodski_cli import run, model, config, log, report, profile, docs
7
+
8
+ from rodski import __version__ as VERSION
9
+
10
+
11
+ def format_error(e, verbose=False):
12
+ """格式化错误信息,提高可读性"""
13
+ error_type = type(e).__name__
14
+ error_msg = str(e)
15
+
16
+ # 常见错误的友好提示
17
+ hints = {
18
+ FileNotFoundError: "请检查文件路径是否正确",
19
+ PermissionError: "请检查文件权限或以管理员身份运行",
20
+ ConnectionError: "请检查网络连接或目标服务是否可用",
21
+ TimeoutError: "操作超时,请检查网络或增加超时时间",
22
+ KeyboardInterrupt: "用户中断执行",
23
+ ImportError: "缺少依赖包,请运行: pip install -r requirements.txt",
24
+ }
25
+
26
+ hint = hints.get(type(e), "")
27
+ lines = [f"错误 [{error_type}]: {error_msg}"]
28
+ if hint:
29
+ lines.append(f"提示: {hint}")
30
+ if verbose:
31
+ lines.append("")
32
+ lines.append("详细堆栈信息:")
33
+ lines.append(traceback.format_exc())
34
+ return "\n".join(lines)
35
+
36
+
37
+ def main():
38
+ parser = argparse.ArgumentParser(
39
+ prog="rodski",
40
+ description="RodSki - 关键字驱动测试框架",
41
+ formatter_class=argparse.RawDescriptionHelpFormatter,
42
+ epilog="示例:\n"
43
+ " ski run case/ 执行测试用例\n"
44
+ " ski run case/ --dry-run 验证用例但不执行\n"
45
+ " ski run case/ --verbose 详细输出模式\n"
46
+ " ski run case/ --step-by-step 单步执行模式\n"
47
+ " ski run case/ --pause-on-error 错误时暂停\n"
48
+ " ski run case/ --interactive 交互模式\n"
49
+ " ski config list 查看配置\n"
50
+ )
51
+ parser.add_argument("--version", action="version", version=f"RodSki {VERSION}")
52
+ parser.add_argument("--verbose", action="store_true", help="详细输出模式")
53
+
54
+ subparsers = parser.add_subparsers(dest="command", help="子命令")
55
+
56
+ # run 子命令
57
+ run.setup_parser(subparsers)
58
+
59
+ # model 子命令
60
+ model.setup_parser(subparsers)
61
+
62
+ # config 子命令
63
+ config.setup_parser(subparsers)
64
+
65
+ # log 子命令
66
+ log.setup_parser(subparsers)
67
+
68
+ # report 子命令
69
+ report.setup_parser(subparsers)
70
+
71
+ # profile 子命令
72
+ profile.setup_parser(subparsers)
73
+
74
+ # docs 子命令
75
+ docs.setup_parser(subparsers)
76
+
77
+ args = parser.parse_args()
78
+
79
+ if not args.command:
80
+ parser.print_help()
81
+ return 0
82
+
83
+ # 执行对应子命令
84
+ handlers = {
85
+ "run": run.handle,
86
+ "model": model.handle,
87
+ "config": config.handle,
88
+ "log": log.handle,
89
+ "report": report.handle,
90
+ "profile": profile.handle,
91
+ "docs": docs.handle
92
+ }
93
+
94
+ verbose = getattr(args, "verbose", False)
95
+
96
+ try:
97
+ return handlers[args.command](args)
98
+ except KeyboardInterrupt:
99
+ print("\n操作已被用户中断", file=sys.stderr)
100
+ return 130
101
+ except Exception as e:
102
+ print(format_error(e, verbose=verbose), file=sys.stderr)
103
+ return 1
104
+
105
+ if __name__ == "__main__":
106
+ sys.exit(main())
File without changes
@@ -0,0 +1,8 @@
1
+ {
2
+ "platformName": "Android",
3
+ "deviceName": "Android Emulator",
4
+ "automationName": "UiAutomator2",
5
+ "appPackage": "com.example.app",
6
+ "appActivity": ".MainActivity",
7
+ "serverUrl": "http://localhost:4723"
8
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "driver": "web",
3
+ "browser": "chromium",
4
+ "headless": false,
5
+ "timeout": 60,
6
+ "retry": 0,
7
+ "retry_delay": 1.0,
8
+ "retry_on_errors": [
9
+ "ElementNotFound",
10
+ "Timeout",
11
+ "StaleElement"
12
+ ],
13
+ "log_level": "INFO",
14
+ "log_dir": "logs",
15
+ "report_format": "html",
16
+ "auto_screenshot_on_failure": true,
17
+ "auto_screenshot_on_step": true,
18
+ "screenshot_dir": "screenshots",
19
+ "smart_wait_enabled": true,
20
+ "smart_wait_max_retries": 30,
21
+ "smart_wait_retry_interval": 0.3,
22
+ "smart_wait_log_retry": true,
23
+ "element_wait_timeout": 0.5,
24
+ "element_retry_interval": 0.1
25
+ }