diff --git a/README.md b/README.md index 40b857d..d232a11 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,704 @@ -# Webrunner -WebRunner is a cross‑platform web automation framework designed to simplify browser automation. -It supports multiple browsers, parallel execution, automatic driver management, -and generates detailed reports. -Built on top of Selenium with additional abstractions, WebRunner helps developers write, run, -and manage automation scripts with ease. +# WebRunner -## Key Features +
+ A cross-platform web automation framework built on Selenium +
+ + + + + +--- -- Multi‑browser support: Chrome, Edge, Safari -- Report generation: JSON / HTML / XML -- Automatic screenshots and window handling -- Element interaction: locate, input, click, and more -- Automatic WebDriver download -- Cross‑platform: Windows, macOS, Ubuntu, Raspberry Pi -- Remote automation and project template +WebRunner (`je_web_runner`) is a cross-platform web automation framework designed to simplify browser automation. It supports multiple browsers, parallel execution, automatic driver management, and generates detailed reports. Built on top of Selenium with additional abstractions, WebRunner helps developers write, run, and manage automation scripts with ease. + +## Table of Contents + +- [Key Features](#key-features) +- [Installation](#installation) +- [Requirements](#requirements) +- [Quick Start](#quick-start) +- [Architecture Overview](#architecture-overview) +- [Core Components](#core-components) + - [WebDriver Manager](#webdriver-manager) + - [WebDriver Wrapper](#webdriver-wrapper) + - [Web Element Wrapper](#web-element-wrapper) + - [Test Object](#test-object) +- [Action Executor](#action-executor) + - [Action Format](#action-format) + - [Available Commands](#available-commands) + - [Execute from JSON Files](#execute-from-json-files) +- [Report Generation](#report-generation) +- [Remote Automation (Socket Server)](#remote-automation-socket-server) +- [Callback Executor](#callback-executor) +- [Package Manager](#package-manager) +- [Project Template](#project-template) +- [CLI Usage](#cli-usage) +- [WebDriver Options Configuration](#webdriver-options-configuration) +- [Test Record](#test-record) +- [Exception Handling](#exception-handling) +- [Logging](#logging) +- [Supported Browsers](#supported-browsers) +- [Supported Platforms](#supported-platforms) +- [License](#license) + +## Key Features +- **Multi-browser support** — Chrome, Chromium, Firefox, Edge, IE, Safari +- **Automatic WebDriver management** — Automatic download and configuration via `webdriver-manager` +- **Parallel execution** — Manage multiple browser instances simultaneously +- **Action executor** — Define automation scripts as JSON action lists +- **Report generation** — HTML, JSON, and XML test reports with success/failure highlighting +- **Remote automation** — TCP socket server for remote command execution +- **Callback system** — Event-driven automation with callback functions +- **Dynamic extension** — Load external Python packages into the executor at runtime +- **Project templates** — Quick-start project structure generation +- **Cross-platform** — Windows, macOS, Ubuntu, Raspberry Pi +- **CLI interface** — Execute automation scripts from the command line +- **Screenshots** — Automatic screenshot capture (PNG, Base64) +- **Comprehensive element interaction** — Locate, click, input, drag-and-drop, and more ## Installation -``` +**Stable version:** + +```bash pip install je_web_runner ``` -## Requires +**Development version:** +```bash +pip install je_web_runner_dev ``` -python 3.9 or later -``` -| All test in test dir +## Requirements + +- Python **3.10** or later +- Dependencies: `selenium>=4.0.0`, `requests`, `python-dotenv`, `webdriver-manager` + +## Quick Start + +### Example 1: Direct API -# Quick Start ```python from je_web_runner import TestObject from je_web_runner import get_webdriver_manager from je_web_runner import web_element_wrapper -from je_web_runner import webdriver_wrapper_instance -# 取得 WebDriver 管理器 (這裡使用 Firefox) -# Get webdriver manager (using Firefox here) -driver_wrapper = get_webdriver_manager("firefox") +# Create a WebDriver manager (using Chrome) +manager = get_webdriver_manager("chrome") -# 前往 Google 首頁 -# Navigate to Google main page -driver_wrapper.webdriver_wrapper.to_url("https://www.google.com") +# Navigate to a URL +manager.webdriver_wrapper.to_url("https://www.google.com") -# 建立測試物件,定位方式為 "name",名稱為 "q" (Google 搜尋框) -# Create a test object, locate by "name", value "q" (Google search box) -google_input = TestObject("q", "name") +# Set implicit wait +manager.webdriver_wrapper.implicitly_wait(2) -# 設定隱式等待 2 秒 -# Set implicit wait to 2 seconds -driver_wrapper.webdriver_wrapper.implicitly_wait(2) +# Create a test object to locate the search box by name +search_box = TestObject("q", "name") -# 尋找目前的網頁元素 (Google 搜尋框) -# Find the current web element (Google search box) -webdriver_wrapper_instance.find_element(google_input) +# Find the element +manager.webdriver_wrapper.find_element(search_box) -# 點擊目前的網頁元素 -# Click the current web element +# Click and type into the element web_element_wrapper.click_element() +web_element_wrapper.input_to_element("WebRunner automation") -# 在目前的網頁元素中輸入文字 "abc_test" -# Input text "abc_test" into the current web element -web_element_wrapper.input_to_element("abc_test") - -# 關閉瀏覽器 # Close the browser -driver_wrapper.quit() +manager.quit() +``` + +### Example 2: JSON Action List + +```python +from je_web_runner import execute_action + +actions = [ + ["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], + ["WR_to_url", {"url": "https://www.google.com"}], + ["WR_implicitly_wait", {"time_to_wait": 2}], + ["WR_SaveTestObject", {"test_object_name": "q", "object_type": "name"}], + ["WR_find_element", {"element_name": "q"}], + ["WR_click_element"], + ["WR_input_to_element", {"input_value": "WebRunner automation"}], + ["WR_quit"] +] + +result = execute_action(actions) +``` + +## Architecture Overview + +``` +je_web_runner/ +├── __init__.py # Public API exports +├── __main__.py # CLI entry point +├── element/ +│ └── web_element_wrapper.py # WebElement interaction wrapper +├── manager/ +│ └── webrunner_manager.py # Multi-driver management +├── webdriver/ +│ ├── webdriver_wrapper.py # Core WebDriver wrapper +│ └── webdriver_with_options.py # Browser options configuration +└── utils/ + ├── callback/ # Callback function executor + ├── exception/ # Custom exception classes + ├── executor/ # Action executor engine + ├── file_process/ # File utilities + ├── generate_report/ # HTML/JSON/XML report generators + ├── json/ # JSON file operations + ├── logging/ # Logging configuration + ├── package_manager/ # Dynamic package loading + ├── project/ # Project template generator + ├── selenium_utils_wrapper/ # Selenium utilities (Keys, Capabilities) + ├── socket_server/ # TCP socket server for remote control + ├── test_object/ # Test object & record classes + ├── test_record/ # Action recording + └── xml/ # XML utilities +``` + +## Core Components + +### WebDriver Manager + +`WebdriverManager` manages multiple WebDriver instances for parallel browser automation. + +```python +from je_web_runner import get_webdriver_manager + +# Create a manager with Chrome +manager = get_webdriver_manager("chrome") + +# Add another browser instance +manager.new_driver("firefox") + +# Switch between browser instances +manager.change_webdriver(0) # Switch to Chrome +manager.change_webdriver(1) # Switch to Firefox + +# Close a specific driver +manager.close_choose_webdriver(1) # Close Firefox + +# Quit all drivers +manager.quit() +``` + +### WebDriver Wrapper + +`WebDriverWrapper` is the central component that wraps Selenium WebDriver with comprehensive methods. + +#### Navigation + +```python +wrapper = manager.webdriver_wrapper + +wrapper.to_url("https://example.com") +wrapper.forward() +wrapper.back() +wrapper.refresh() +``` + +#### Element Location + +```python +from je_web_runner import TestObject + +# Locator strategies: id, name, xpath, css selector, class name, tag name, link text, partial link text +element = TestObject("search-input", "id") +wrapper.find_element(element) # Find single element +wrapper.find_elements(element) # Find multiple elements +``` + +#### Wait Methods + +```python +wrapper.implicitly_wait(5) # Implicit wait (seconds) +wrapper.explict_wait(10, method=some_func) # Explicit WebDriverWait +wrapper.set_script_timeout(30) # Async script timeout +wrapper.set_page_load_timeout(60) # Page load timeout +``` + +#### Mouse & Keyboard Actions + +```python +wrapper.left_click() +wrapper.right_click() +wrapper.left_double_click() +wrapper.left_click_and_hold() +wrapper.release() +wrapper.drag_and_drop(source_element, target_element) +wrapper.drag_and_drop_offset(element, x=100, y=50) +wrapper.move_to_element(element) # Hover +wrapper.move_by_offset(100, 200) +wrapper.press_key(keycode) +wrapper.release_key(keycode) +wrapper.send_keys("text") +wrapper.send_keys_to_element(element, "text") +wrapper.perform() # Execute queued actions +wrapper.reset_actions() # Clear action queue +wrapper.pause(2) # Pause in action chain +``` + +#### Cookie Management + +```python +wrapper.get_cookies() # Get all cookies +wrapper.get_cookie("session_id") # Get specific cookie +wrapper.add_cookie({"name": "key", "value": "val"}) +wrapper.delete_cookie("session_id") +wrapper.delete_all_cookies() +``` + +#### JavaScript Execution + +```python +wrapper.execute_script("document.title") +wrapper.execute_async_script("arguments[0]('done')", callback) +``` + +#### Window Management + +```python +wrapper.maximize_window() +wrapper.minimize_window() +wrapper.fullscreen_window() +wrapper.set_window_size(1920, 1080) +wrapper.set_window_position(0, 0) +wrapper.get_window_position() +wrapper.get_window_rect() +wrapper.set_window_rect(x=0, y=0, width=1920, height=1080) +``` + +#### Screenshots & Scrolling + +```python +wrapper.get_screenshot_as_png() # Returns bytes +wrapper.get_screenshot_as_base64() # Returns base64 string +wrapper.scroll(0, 500) # Scroll page +``` + +#### Frame / Window / Alert Switching + +```python +wrapper.switch("frame", "frame_name") +wrapper.switch("window", "window_handle") +wrapper.switch("default_content") +``` + +#### Browser Logs + +```python +wrapper.get_log("browser") +``` + +### Web Element Wrapper + +`WebElementWrapper` provides methods for interacting with located elements. + +```python +from je_web_runner import web_element_wrapper + +web_element_wrapper.click_element() +web_element_wrapper.input_to_element("Hello World") +web_element_wrapper.clear() +web_element_wrapper.submit() + +# Inspection +web_element_wrapper.get_attribute("href") +web_element_wrapper.get_property("checked") +web_element_wrapper.get_dom_attribute("data-id") +web_element_wrapper.is_displayed() +web_element_wrapper.is_enabled() +web_element_wrapper.is_selected() +web_element_wrapper.value_of_css_property("color") + +# Select (dropdown) +select = web_element_wrapper.get_select() + +# Element screenshot +web_element_wrapper.screenshot("element.png") + +# Switch active element from a list +web_element_wrapper.change_web_element(2) + +# Validate element properties +web_element_wrapper.check_current_web_element({"tag_name": "input"}) +``` + +### Test Object + +`TestObject` encapsulates element locator information for reusable element definitions. + +```python +from je_web_runner import TestObject, create_test_object, get_test_object_type_list + +# Two ways to create +obj1 = TestObject("search", "name") +obj2 = create_test_object("id", "submit-btn") + +# View available locator types +print(get_test_object_type_list()) +# ['ID', 'NAME', 'XPATH', 'CSS_SELECTOR', 'CLASS_NAME', 'TAG_NAME', 'LINK_TEXT', 'PARTIAL_LINK_TEXT'] +``` + +## Action Executor + +The Action Executor is a powerful engine that maps command strings to callable functions. It allows you to define automation scripts as JSON action lists. + +### Action Format + +Each action is a list with the command name and optional parameters: + +```python +["command_name"] # No parameters +["command_name", {"key": "value"}] # Keyword arguments +["command_name", [arg1, arg2]] # Positional arguments +``` + +### Available Commands + +| Category | Commands | +|----------|----------| +| **Manager** | `WR_get_webdriver_manager`, `WR_change_index_of_webdriver`, `WR_quit` | +| **Navigation** | `WR_to_url`, `WR_forward`, `WR_back`, `WR_refresh` | +| **Elements** | `WR_find_element`, `WR_find_elements`, `WR_find_element_with_test_object_record`, `WR_find_elements_with_test_object_record` | +| **Wait** | `WR_implicitly_wait`, `WR_explict_wait`, `WR_set_script_timeout`, `WR_set_page_load_timeout` | +| **Click** | `WR_left_click`, `WR_right_click`, `WR_left_double_click`, `WR_left_click_and_hold`, `WR_release` | +| **Drag** | `WR_drag_and_drop`, `WR_drag_and_drop_offset`, `WR_drag_and_drop_with_test_object`, `WR_drag_and_drop_offset_with_test_object` | +| **Hover** | `WR_move_to_element`, `WR_move_to_element_with_offset`, `WR_move_by_offset` | +| **Keyboard** | `WR_press_key`, `WR_release_key`, `WR_send_keys`, `WR_send_keys_to_element` | +| **Actions** | `WR_perform`, `WR_reset_actions`, `WR_pause` | +| **Cookies** | `WR_get_cookies`, `WR_get_cookie`, `WR_add_cookie`, `WR_delete_cookie`, `WR_delete_all_cookies` | +| **JavaScript** | `WR_execute_script`, `WR_execute_async_script` | +| **Window** | `WR_maximize_window`, `WR_minimize_window`, `WR_fullscreen_window`, `WR_set_window_size`, `WR_set_window_position`, `WR_set_window_rect` | +| **Screenshot** | `WR_get_screenshot_as_png`, `WR_get_screenshot_as_base64` | +| **Element** | `WR_click_element`, `WR_input_to_element`, `WR_element_clear`, `WR_element_submit`, `WR_element_get_attribute`, `WR_element_is_displayed`, `WR_element_is_enabled`, `WR_element_is_selected` | +| **Test Object** | `WR_SaveTestObject`, `WR_CleanTestObject` | +| **Report** | `WR_generate_html_report`, `WR_generate_json_report`, `WR_generate_xml_report` | +| **Package** | `WR_add_package_to_executor` | +| **Nested** | `WR_execute_action`, `WR_execute_files` | + +### Execute from JSON Files + +```python +from je_web_runner import execute_files + +# Execute actions from JSON files +results = execute_files(["actions1.json", "actions2.json"]) +``` + +JSON file format: + +```json +[ + ["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], + ["WR_to_url", {"url": "https://example.com"}], + ["WR_quit"] +] ``` + +### Add Custom Commands + +```python +from je_web_runner import add_command_to_executor + +def my_custom_function(param1, param2): + print(f"Custom: {param1}, {param2}") + +add_command_to_executor({"my_command": my_custom_function}) +``` + +## Report Generation + +WebRunner can automatically record all actions and generate reports in three formats. + +### Enable Recording + +```python +from je_web_runner import test_record_instance + +test_record_instance.set_record_enable(True) +``` + +### HTML Report + +```python +from je_web_runner import generate_html, generate_html_report + +# Generate HTML string +html_content = generate_html() + +# Save to file (creates test_results.html) +generate_html_report("test_results") +``` + +HTML reports include color-coded tables: **aqua** for success, **red** for failure. Each row shows the function name, parameters, timestamp, and exception (if any). + +### JSON Report + +```python +from je_web_runner import generate_json, generate_json_report + +# Generate dicts +success_dict, failure_dict = generate_json() + +# Save to files (creates test_results_success.json and test_results_failure.json) +generate_json_report("test_results") +``` + +### XML Report + +```python +from je_web_runner import generate_xml, generate_xml_report + +# Generate XML strings +success_xml, failure_xml = generate_xml() + +# Save to files (creates test_results_success.xml and test_results_failure.xml) +generate_xml_report("test_results") +``` + +## Remote Automation (Socket Server) + +WebRunner includes a multi-threaded TCP socket server for remote automation control. + +### Start Server + +```python +from je_web_runner import start_web_runner_socket_server + +server = start_web_runner_socket_server(host="localhost", port=9941) +``` + +### Client Connection + +```python +import socket +import json + +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.connect(("localhost", 9941)) + +# Send actions as JSON +actions = [ + ["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], + ["WR_to_url", {"url": "https://example.com"}], + ["WR_quit"] +] +sock.send(json.dumps(actions).encode("utf-8")) + +# Receive results (ends with "Return_Data_Over_JE\n") +response = sock.recv(4096).decode("utf-8") +print(response) + +# Shutdown server +sock.send("quit_server".encode("utf-8")) +``` + +## Callback Executor + +Execute automation commands with callback functions triggered on completion. + +```python +from je_web_runner import callback_executor + +def on_complete(): + print("Navigation complete!") + +callback_executor.callback_function( + trigger_function_name="WR_to_url", + callback_function=on_complete, + url="https://example.com" +) +``` + +With parameters: + +```python +def on_element_found(result=None): + print(f"Element found: {result}") + +callback_executor.callback_function( + trigger_function_name="WR_find_element", + callback_function=on_element_found, + callback_function_param={"result": "search_box"}, + callback_param_method="kwargs", + element_name="search_box" +) +``` + +## Package Manager + +Dynamically load external Python packages into the executor at runtime. + +```python +from je_web_runner import execute_action + +actions = [ + # Load the 'time' package + ["WR_add_package_to_executor", {"package": "time"}], + # Now you can use time.sleep + ["time_sleep", [2]] +] + +execute_action(actions) +``` + +## Project Template + +Generate a quick-start project structure with sample files. + +```python +from je_web_runner import create_project_dir + +create_project_dir(project_path="./my_project", parent_name="WebRunner") +``` + +Generated structure: + +``` +my_project/WebRunner/ +├── keyword/ +│ ├── keyword1.json +│ ├── keyword2.json +│ └── bad_keyword_1.json +└── executor/ + ├── executor_one_file.py + ├── executor_folder.py + └── executor_bad_file.py +``` + +## CLI Usage + +WebRunner can be executed directly from the command line. + +```bash +# Execute a single JSON action file +python -m je_web_runner -e actions.json + +# Execute all JSON files in a directory +python -m je_web_runner -d ./actions/ + +# Execute a JSON string directly +python -m je_web_runner --execute_str '[["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], ["WR_quit"]]' +``` + +## WebDriver Options Configuration + +Configure browser options before launching. + +```python +from je_web_runner import set_webdriver_options_argument, get_webdriver_manager + +# Set browser arguments (e.g., headless mode) +options = set_webdriver_options_argument("chrome", [ + "--headless", + "--disable-gpu", + "--no-sandbox", + "--window-size=1920,1080" +]) + +# Launch with options +manager = get_webdriver_manager("chrome", options=["--headless", "--disable-gpu"]) +``` + +### DesiredCapabilities + +```python +from je_web_runner import get_desired_capabilities, get_desired_capabilities_keys + +# View available capabilities +keys = get_desired_capabilities_keys() + +# Get capabilities for a browser +caps = get_desired_capabilities("CHROME") +``` + +## Test Record + +All WebRunner actions are automatically recorded for audit trails and report generation. + +```python +from je_web_runner import test_record_instance + +# Enable recording +test_record_instance.set_record_enable(True) + +# ... perform automation ... + +# Access records +records = test_record_instance.test_record_list + +# Each record contains: +# { +# "function_name": "to_url", +# "local_param": {"url": "https://example.com"}, +# "time": "2025-01-01 12:00:00", +# "program_exception": "None" +# } + +# Clear records +test_record_instance.clean_record() +``` + +## Exception Handling + +WebRunner provides a hierarchy of custom exceptions: + +| Exception | Description | +|-----------|-------------| +| `WebRunnerException` | Base exception | +| `WebRunnerWebDriverNotFoundException` | WebDriver not found | +| `WebRunnerOptionsWrongTypeException` | Invalid options type | +| `WebRunnerArgumentWrongTypeException` | Invalid argument type | +| `WebRunnerWebDriverIsNoneException` | WebDriver is None | +| `WebRunnerExecuteException` | Execution error | +| `WebRunnerJsonException` | JSON processing error | +| `WebRunnerGenerateJsonReportException` | JSON report generation error | +| `WebRunnerAssertException` | Assertion failure | +| `WebRunnerHTMLException` | HTML report error | +| `WebRunnerAddCommandException` | Command registration error | +| `XMLException` / `XMLTypeException` | XML processing error | +| `CallbackExecutorException` | Callback execution error | + +## Logging + +WebRunner uses a rotating file handler for logging. + +- **Log file:** `WEBRunner.log` +- **Log level:** WARNING and above +- **Max file size:** 1 GB +- **Format:** `%(asctime)s | %(name)s | %(levelname)s | %(message)s` + +## Supported Browsers + +| Browser | Key | +|---------|-----| +| Google Chrome | `chrome` | +| Chromium | `chromium` | +| Mozilla Firefox | `firefox` | +| Microsoft Edge | `edge` | +| Internet Explorer | `ie` | +| Apple Safari | `safari` | + +## Supported Platforms + +- Windows +- macOS +- Ubuntu / Linux +- Raspberry Pi + +## License + +This project is licensed under the [MIT License](LICENSE). + +Copyright (c) 2021~2023 JE-Chen diff --git a/README/README_zh-CN.md b/README/README_zh-CN.md new file mode 100644 index 0000000..ce001a2 --- /dev/null +++ b/README/README_zh-CN.md @@ -0,0 +1,704 @@ +# WebRunner + ++ 基于 Selenium 的跨平台网页自动化框架 +
+ + + + + +--- + +WebRunner(`je_web_runner`)是一款跨平台网页自动化框架,旨在简化浏览器自动化操作。它支持多种浏览器、并行执行、自动驱动程序管理,并能生成详细的测试报告。基于 Selenium 构建并提供额外的抽象层,WebRunner 帮助开发者轻松编写、执行及管理自动化脚本。 + +## 目录 + +- [核心功能](#核心功能) +- [安装](#安装) +- [系统要求](#系统要求) +- [快速开始](#快速开始) +- [架构概览](#架构概览) +- [核心组件](#核心组件) + - [WebDriver 管理器](#webdriver-管理器) + - [WebDriver 包装器](#webdriver-包装器) + - [网页元素包装器](#网页元素包装器) + - [测试对象](#测试对象) +- [动作执行器](#动作执行器) + - [动作格式](#动作格式) + - [可用指令](#可用指令) + - [从 JSON 文件执行](#从-json-文件执行) +- [报告生成](#报告生成) +- [远程自动化(Socket 服务器)](#远程自动化socket-服务器) +- [回调执行器](#回调执行器) +- [包管理器](#包管理器) +- [项目模板](#项目模板) +- [命令行接口](#命令行接口) +- [WebDriver 选项配置](#webdriver-选项配置) +- [测试记录](#测试记录) +- [异常处理](#异常处理) +- [日志记录](#日志记录) +- [支持的浏览器](#支持的浏览器) +- [支持的平台](#支持的平台) +- [许可证](#许可证) + +## 核心功能 + +- **多浏览器支持** — Chrome、Chromium、Firefox、Edge、IE、Safari +- **自动 WebDriver 管理** — 通过 `webdriver-manager` 自动下载与配置 +- **并行执行** — 同时管理多个浏览器实例 +- **动作执行器** — 以 JSON 动作列表定义自动化脚本 +- **报告生成** — HTML、JSON 及 XML 格式的测试报告,含成功/失败标记 +- **远程自动化** — TCP Socket 服务器,支持远程命令执行 +- **回调系统** — 事件驱动的自动化回调机制 +- **动态扩展** — 在运行时将外部 Python 包加载到执行器 +- **项目模板** — 快速创建项目结构 +- **跨平台** — Windows、macOS、Ubuntu、Raspberry Pi +- **命令行接口** — 从命令行直接执行自动化脚本 +- **截图** — 自动捕获截图(PNG、Base64) +- **全面的元素交互** — 定位、点击、输入、拖放等操作 + +## 安装 + +**稳定版:** + +```bash +pip install je_web_runner +``` + +**开发版:** + +```bash +pip install je_web_runner_dev +``` + +## 系统要求 + +- Python **3.10** 或更高版本 +- 依赖包:`selenium>=4.0.0`、`requests`、`python-dotenv`、`webdriver-manager` + +## 快速开始 + +### 示例 1:直接使用 API + +```python +from je_web_runner import TestObject +from je_web_runner import get_webdriver_manager +from je_web_runner import web_element_wrapper + +# 创建 WebDriver 管理器(使用 Chrome) +manager = get_webdriver_manager("chrome") + +# 导航到指定网址 +manager.webdriver_wrapper.to_url("https://www.google.com") + +# 设置隐式等待 +manager.webdriver_wrapper.implicitly_wait(2) + +# 创建测试对象,以 name 属性定位搜索框 +search_box = TestObject("q", "name") + +# 查找元素 +manager.webdriver_wrapper.find_element(search_box) + +# 点击并输入文字 +web_element_wrapper.click_element() +web_element_wrapper.input_to_element("WebRunner 自动化") + +# 关闭浏览器 +manager.quit() +``` + +### 示例 2:JSON 动作列表 + +```python +from je_web_runner import execute_action + +actions = [ + ["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], + ["WR_to_url", {"url": "https://www.google.com"}], + ["WR_implicitly_wait", {"time_to_wait": 2}], + ["WR_SaveTestObject", {"test_object_name": "q", "object_type": "name"}], + ["WR_find_element", {"element_name": "q"}], + ["WR_click_element"], + ["WR_input_to_element", {"input_value": "WebRunner 自动化"}], + ["WR_quit"] +] + +result = execute_action(actions) +``` + +## 架构概览 + +``` +je_web_runner/ +├── __init__.py # 公开 API 导出 +├── __main__.py # 命令行入口点 +├── element/ +│ └── web_element_wrapper.py # 网页元素交互包装器 +├── manager/ +│ └── webrunner_manager.py # 多驱动程序管理 +├── webdriver/ +│ ├── webdriver_wrapper.py # 核心 WebDriver 包装器 +│ └── webdriver_with_options.py # 浏览器选项配置 +└── utils/ + ├── callback/ # 回调函数执行器 + ├── exception/ # 自定义异常类 + ├── executor/ # 动作执行引擎 + ├── file_process/ # 文件工具 + ├── generate_report/ # HTML/JSON/XML 报告生成器 + ├── json/ # JSON 文件操作 + ├── logging/ # 日志配置 + ├── package_manager/ # 动态包加载 + ├── project/ # 项目模板生成器 + ├── selenium_utils_wrapper/ # Selenium 工具(Keys、Capabilities) + ├── socket_server/ # TCP Socket 服务器(远程控制) + ├── test_object/ # 测试对象与记录类 + ├── test_record/ # 动作记录 + └── xml/ # XML 工具 +``` + +## 核心组件 + +### WebDriver 管理器 + +`WebdriverManager` 管理多个 WebDriver 实例,支持并行浏览器自动化。 + +```python +from je_web_runner import get_webdriver_manager + +# 创建管理器(使用 Chrome) +manager = get_webdriver_manager("chrome") + +# 添加另一个浏览器实例 +manager.new_driver("firefox") + +# 切换浏览器实例 +manager.change_webdriver(0) # 切换到 Chrome +manager.change_webdriver(1) # 切换到 Firefox + +# 关闭特定驱动程序 +manager.close_choose_webdriver(1) # 关闭 Firefox + +# 关闭所有驱动程序 +manager.quit() +``` + +### WebDriver 包装器 + +`WebDriverWrapper` 是核心组件,包装了 Selenium WebDriver 并提供全面的方法。 + +#### 导航 + +```python +wrapper = manager.webdriver_wrapper + +wrapper.to_url("https://example.com") +wrapper.forward() +wrapper.back() +wrapper.refresh() +``` + +#### 元素定位 + +```python +from je_web_runner import TestObject + +# 定位策略:id、name、xpath、css selector、class name、tag name、link text、partial link text +element = TestObject("search-input", "id") +wrapper.find_element(element) # 查找单个元素 +wrapper.find_elements(element) # 查找多个元素 +``` + +#### 等待方法 + +```python +wrapper.implicitly_wait(5) # 隐式等待(秒) +wrapper.explict_wait(10, method=some_func) # 显式等待(WebDriverWait) +wrapper.set_script_timeout(30) # 异步脚本超时 +wrapper.set_page_load_timeout(60) # 页面加载超时 +``` + +#### 鼠标与键盘操作 + +```python +wrapper.left_click() # 左键点击 +wrapper.right_click() # 右键点击 +wrapper.left_double_click() # 双击 +wrapper.left_click_and_hold() # 按住不放 +wrapper.release() # 释放 +wrapper.drag_and_drop(source, target) # 拖放 +wrapper.drag_and_drop_offset(element, x=100, y=50) # 偏移拖放 +wrapper.move_to_element(element) # 鼠标悬停 +wrapper.move_by_offset(100, 200) # 偏移移动 +wrapper.press_key(keycode) # 按下按键 +wrapper.release_key(keycode) # 释放按键 +wrapper.send_keys("文字") # 发送按键 +wrapper.send_keys_to_element(element, "文字") # 向元素发送按键 +wrapper.perform() # 执行队列中的动作 +wrapper.reset_actions() # 清除动作队列 +wrapper.pause(2) # 暂停 +``` + +#### Cookie 管理 + +```python +wrapper.get_cookies() # 获取所有 Cookie +wrapper.get_cookie("session_id") # 获取特定 Cookie +wrapper.add_cookie({"name": "key", "value": "val"}) +wrapper.delete_cookie("session_id") +wrapper.delete_all_cookies() +``` + +#### JavaScript 执行 + +```python +wrapper.execute_script("document.title") +wrapper.execute_async_script("arguments[0]('done')", callback) +``` + +#### 窗口管理 + +```python +wrapper.maximize_window() # 最大化 +wrapper.minimize_window() # 最小化 +wrapper.fullscreen_window() # 全屏 +wrapper.set_window_size(1920, 1080) # 设置大小 +wrapper.set_window_position(0, 0) # 设置位置 +wrapper.get_window_position() # 获取位置 +wrapper.get_window_rect() # 获取矩形信息 +wrapper.set_window_rect(x=0, y=0, width=1920, height=1080) +``` + +#### 截图与滚动 + +```python +wrapper.get_screenshot_as_png() # 返回 bytes +wrapper.get_screenshot_as_base64() # 返回 base64 字符串 +wrapper.scroll(0, 500) # 滚动页面 +``` + +#### Frame / 窗口 / Alert 切换 + +```python +wrapper.switch("frame", "frame_name") +wrapper.switch("window", "window_handle") +wrapper.switch("default_content") +``` + +#### 浏览器日志 + +```python +wrapper.get_log("browser") +``` + +### 网页元素包装器 + +`WebElementWrapper` 提供与已定位元素交互的方法。 + +```python +from je_web_runner import web_element_wrapper + +web_element_wrapper.click_element() # 点击 +web_element_wrapper.input_to_element("Hello World") # 输入 +web_element_wrapper.clear() # 清除 +web_element_wrapper.submit() # 提交 + +# 检查属性 +web_element_wrapper.get_attribute("href") +web_element_wrapper.get_property("checked") +web_element_wrapper.get_dom_attribute("data-id") +web_element_wrapper.is_displayed() # 是否可见 +web_element_wrapper.is_enabled() # 是否启用 +web_element_wrapper.is_selected() # 是否选中 +web_element_wrapper.value_of_css_property("color") # CSS 属性值 + +# 下拉选择框 +select = web_element_wrapper.get_select() + +# 元素截图 +web_element_wrapper.screenshot("element.png") + +# 从列表切换活动元素 +web_element_wrapper.change_web_element(2) + +# 验证元素属性 +web_element_wrapper.check_current_web_element({"tag_name": "input"}) +``` + +### 测试对象 + +`TestObject` 封装元素定位信息,可重复使用。 + +```python +from je_web_runner import TestObject, create_test_object, get_test_object_type_list + +# 两种创建方式 +obj1 = TestObject("search", "name") +obj2 = create_test_object("id", "submit-btn") + +# 查看可用的定位类型 +print(get_test_object_type_list()) +# ['ID', 'NAME', 'XPATH', 'CSS_SELECTOR', 'CLASS_NAME', 'TAG_NAME', 'LINK_TEXT', 'PARTIAL_LINK_TEXT'] +``` + +## 动作执行器 + +动作执行器是一个强大的引擎,将命令字符串映射到可调用的函数。它允许您以 JSON 动作列表定义自动化脚本。 + +### 动作格式 + +每个动作是一个列表,包含命令名称和可选参数: + +```python +["命令名称"] # 无参数 +["命令名称", {"key": "value"}] # 关键字参数 +["命令名称", [arg1, arg2]] # 位置参数 +``` + +### 可用指令 + +| 类别 | 指令 | +|------|------| +| **管理器** | `WR_get_webdriver_manager`、`WR_change_index_of_webdriver`、`WR_quit` | +| **导航** | `WR_to_url`、`WR_forward`、`WR_back`、`WR_refresh` | +| **元素** | `WR_find_element`、`WR_find_elements`、`WR_find_element_with_test_object_record`、`WR_find_elements_with_test_object_record` | +| **等待** | `WR_implicitly_wait`、`WR_explict_wait`、`WR_set_script_timeout`、`WR_set_page_load_timeout` | +| **点击** | `WR_left_click`、`WR_right_click`、`WR_left_double_click`、`WR_left_click_and_hold`、`WR_release` | +| **拖放** | `WR_drag_and_drop`、`WR_drag_and_drop_offset`、`WR_drag_and_drop_with_test_object`、`WR_drag_and_drop_offset_with_test_object` | +| **悬停** | `WR_move_to_element`、`WR_move_to_element_with_offset`、`WR_move_by_offset` | +| **键盘** | `WR_press_key`、`WR_release_key`、`WR_send_keys`、`WR_send_keys_to_element` | +| **动作链** | `WR_perform`、`WR_reset_actions`、`WR_pause` | +| **Cookie** | `WR_get_cookies`、`WR_get_cookie`、`WR_add_cookie`、`WR_delete_cookie`、`WR_delete_all_cookies` | +| **JavaScript** | `WR_execute_script`、`WR_execute_async_script` | +| **窗口** | `WR_maximize_window`、`WR_minimize_window`、`WR_fullscreen_window`、`WR_set_window_size`、`WR_set_window_position`、`WR_set_window_rect` | +| **截图** | `WR_get_screenshot_as_png`、`WR_get_screenshot_as_base64` | +| **元素操作** | `WR_click_element`、`WR_input_to_element`、`WR_element_clear`、`WR_element_submit`、`WR_element_get_attribute`、`WR_element_is_displayed`、`WR_element_is_enabled`、`WR_element_is_selected` | +| **测试对象** | `WR_SaveTestObject`、`WR_CleanTestObject` | +| **报告** | `WR_generate_html_report`、`WR_generate_json_report`、`WR_generate_xml_report` | +| **包** | `WR_add_package_to_executor` | +| **嵌套执行** | `WR_execute_action`、`WR_execute_files` | + +### 从 JSON 文件执行 + +```python +from je_web_runner import execute_files + +# 从 JSON 文件执行动作 +results = execute_files(["actions1.json", "actions2.json"]) +``` + +JSON 文件格式: + +```json +[ + ["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], + ["WR_to_url", {"url": "https://example.com"}], + ["WR_quit"] +] +``` + +### 添加自定义命令 + +```python +from je_web_runner import add_command_to_executor + +def my_custom_function(param1, param2): + print(f"自定义:{param1}、{param2}") + +add_command_to_executor({"my_command": my_custom_function}) +``` + +## 报告生成 + +WebRunner 可自动记录所有动作,并以三种格式生成报告。 + +### 启用记录 + +```python +from je_web_runner import test_record_instance + +test_record_instance.set_record_enable(True) +``` + +### HTML 报告 + +```python +from je_web_runner import generate_html, generate_html_report + +# 生成 HTML 字符串 +html_content = generate_html() + +# 保存到文件(创建 test_results.html) +generate_html_report("test_results") +``` + +HTML 报告包含颜色标记的表格:成功为**青色**,失败为**红色**。每行显示函数名称、参数、时间戳及异常信息(如有)。 + +### JSON 报告 + +```python +from je_web_runner import generate_json, generate_json_report + +# 生成字典 +success_dict, failure_dict = generate_json() + +# 保存到文件(创建 test_results_success.json 和 test_results_failure.json) +generate_json_report("test_results") +``` + +### XML 报告 + +```python +from je_web_runner import generate_xml, generate_xml_report + +# 生成 XML 字符串 +success_xml, failure_xml = generate_xml() + +# 保存到文件(创建 test_results_success.xml 和 test_results_failure.xml) +generate_xml_report("test_results") +``` + +## 远程自动化(Socket 服务器) + +WebRunner 内置多线程 TCP Socket 服务器,支持远程自动化控制。 + +### 启动服务器 + +```python +from je_web_runner import start_web_runner_socket_server + +server = start_web_runner_socket_server(host="localhost", port=9941) +``` + +### 客户端连接 + +```python +import socket +import json + +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.connect(("localhost", 9941)) + +# 以 JSON 格式发送动作 +actions = [ + ["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], + ["WR_to_url", {"url": "https://example.com"}], + ["WR_quit"] +] +sock.send(json.dumps(actions).encode("utf-8")) + +# 接收结果(以 "Return_Data_Over_JE\n" 结尾) +response = sock.recv(4096).decode("utf-8") +print(response) + +# 关闭服务器 +sock.send("quit_server".encode("utf-8")) +``` + +## 回调执行器 + +执行自动化命令并在完成后触发回调函数。 + +```python +from je_web_runner import callback_executor + +def on_complete(): + print("导航完成!") + +callback_executor.callback_function( + trigger_function_name="WR_to_url", + callback_function=on_complete, + url="https://example.com" +) +``` + +带参数: + +```python +def on_element_found(result=None): + print(f"元素已找到:{result}") + +callback_executor.callback_function( + trigger_function_name="WR_find_element", + callback_function=on_element_found, + callback_function_param={"result": "search_box"}, + callback_param_method="kwargs", + element_name="search_box" +) +``` + +## 包管理器 + +在运行时动态加载外部 Python 包到执行器。 + +```python +from je_web_runner import execute_action + +actions = [ + # 加载 'time' 包 + ["WR_add_package_to_executor", {"package": "time"}], + # 现在可以使用 time.sleep + ["time_sleep", [2]] +] + +execute_action(actions) +``` + +## 项目模板 + +快速创建项目结构及示例文件。 + +```python +from je_web_runner import create_project_dir + +create_project_dir(project_path="./my_project", parent_name="WebRunner") +``` + +生成的结构: + +``` +my_project/WebRunner/ +├── keyword/ +│ ├── keyword1.json +│ ├── keyword2.json +│ └── bad_keyword_1.json +└── executor/ + ├── executor_one_file.py + ├── executor_folder.py + └── executor_bad_file.py +``` + +## 命令行接口 + +WebRunner 可直接从命令行执行。 + +```bash +# 执行单个 JSON 动作文件 +python -m je_web_runner -e actions.json + +# 执行目录中所有 JSON 文件 +python -m je_web_runner -d ./actions/ + +# 直接执行 JSON 字符串 +python -m je_web_runner --execute_str '[["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], ["WR_quit"]]' +``` + +## WebDriver 选项配置 + +在启动前配置浏览器选项。 + +```python +from je_web_runner import set_webdriver_options_argument, get_webdriver_manager + +# 设置浏览器参数(例如:无头模式) +options = set_webdriver_options_argument("chrome", [ + "--headless", + "--disable-gpu", + "--no-sandbox", + "--window-size=1920,1080" +]) + +# 以选项启动 +manager = get_webdriver_manager("chrome", options=["--headless", "--disable-gpu"]) +``` + +### DesiredCapabilities + +```python +from je_web_runner import get_desired_capabilities, get_desired_capabilities_keys + +# 查看可用的功能 +keys = get_desired_capabilities_keys() + +# 获取浏览器的功能 +caps = get_desired_capabilities("CHROME") +``` + +## 测试记录 + +所有 WebRunner 动作会自动记录,用于审计追踪及报告生成。 + +```python +from je_web_runner import test_record_instance + +# 启用记录 +test_record_instance.set_record_enable(True) + +# ... 执行自动化操作 ... + +# 访问记录 +records = test_record_instance.test_record_list + +# 每条记录包含: +# { +# "function_name": "to_url", +# "local_param": {"url": "https://example.com"}, +# "time": "2025-01-01 12:00:00", +# "program_exception": "None" +# } + +# 清除记录 +test_record_instance.clean_record() +``` + +## 异常处理 + +WebRunner 提供完整的自定义异常层次结构: + +| 异常 | 说明 | +|------|------| +| `WebRunnerException` | 基础异常 | +| `WebRunnerWebDriverNotFoundException` | 找不到 WebDriver | +| `WebRunnerOptionsWrongTypeException` | 选项类型错误 | +| `WebRunnerArgumentWrongTypeException` | 参数类型错误 | +| `WebRunnerWebDriverIsNoneException` | WebDriver 为 None | +| `WebRunnerExecuteException` | 执行错误 | +| `WebRunnerJsonException` | JSON 处理错误 | +| `WebRunnerGenerateJsonReportException` | JSON 报告生成错误 | +| `WebRunnerAssertException` | 断言失败 | +| `WebRunnerHTMLException` | HTML 报告错误 | +| `WebRunnerAddCommandException` | 命令注册错误 | +| `XMLException` / `XMLTypeException` | XML 处理错误 | +| `CallbackExecutorException` | 回调执行错误 | + +## 日志记录 + +WebRunner 使用轮转式文件处理器记录日志。 + +- **日志文件:** `WEBRunner.log` +- **日志级别:** WARNING 及以上 +- **文件大小上限:** 1 GB +- **格式:** `%(asctime)s | %(name)s | %(levelname)s | %(message)s` + +## 支持的浏览器 + +| 浏览器 | 标识符 | +|--------|--------| +| Google Chrome | `chrome` | +| Chromium | `chromium` | +| Mozilla Firefox | `firefox` | +| Microsoft Edge | `edge` | +| Internet Explorer | `ie` | +| Apple Safari | `safari` | + +## 支持的平台 + +- Windows +- macOS +- Ubuntu / Linux +- Raspberry Pi + +## 许可证 + +本项目采用 [MIT 许可证](../LICENSE)。 + +Copyright (c) 2021~2023 JE-Chen diff --git a/README/README_zh-TW.md b/README/README_zh-TW.md new file mode 100644 index 0000000..c9f74bd --- /dev/null +++ b/README/README_zh-TW.md @@ -0,0 +1,704 @@ +# WebRunner + ++ 基於 Selenium 的跨平台網頁自動化框架 +
+ + + + + +--- + +WebRunner(`je_web_runner`)是一款跨平台網頁自動化框架,旨在簡化瀏覽器自動化操作。它支援多種瀏覽器、並行執行、自動驅動程式管理,並能產生詳細的測試報告。基於 Selenium 構建並提供額外的抽象層,WebRunner 協助開發者輕鬆撰寫、執行及管理自動化腳本。 + +## 目錄 + +- [核心功能](#核心功能) +- [安裝](#安裝) +- [系統需求](#系統需求) +- [快速開始](#快速開始) +- [架構概覽](#架構概覽) +- [核心元件](#核心元件) + - [WebDriver 管理器](#webdriver-管理器) + - [WebDriver 包裝器](#webdriver-包裝器) + - [網頁元素包裝器](#網頁元素包裝器) + - [測試物件](#測試物件) +- [動作執行器](#動作執行器) + - [動作格式](#動作格式) + - [可用指令](#可用指令) + - [從 JSON 檔案執行](#從-json-檔案執行) +- [報告產生](#報告產生) +- [遠端自動化(Socket 伺服器)](#遠端自動化socket-伺服器) +- [回呼執行器](#回呼執行器) +- [套件管理器](#套件管理器) +- [專案範本](#專案範本) +- [命令列介面](#命令列介面) +- [WebDriver 選項設定](#webdriver-選項設定) +- [測試紀錄](#測試紀錄) +- [例外處理](#例外處理) +- [日誌記錄](#日誌記錄) +- [支援的瀏覽器](#支援的瀏覽器) +- [支援的平台](#支援的平台) +- [授權條款](#授權條款) + +## 核心功能 + +- **多瀏覽器支援** — Chrome、Chromium、Firefox、Edge、IE、Safari +- **自動 WebDriver 管理** — 透過 `webdriver-manager` 自動下載與設定 +- **並行執行** — 同時管理多個瀏覽器實例 +- **動作執行器** — 以 JSON 動作列表定義自動化腳本 +- **報告產生** — HTML、JSON 及 XML 格式的測試報告,含成功/失敗標示 +- **遠端自動化** — TCP Socket 伺服器,支援遠端指令執行 +- **回呼系統** — 事件驅動的自動化回呼機制 +- **動態擴充** — 於執行期間將外部 Python 套件載入執行器 +- **專案範本** — 快速建立專案結構 +- **跨平台** — Windows、macOS、Ubuntu、Raspberry Pi +- **命令列介面** — 從命令列直接執行自動化腳本 +- **螢幕截圖** — 自動擷取螢幕截圖(PNG、Base64) +- **全面的元素互動** — 定位、點擊、輸入、拖放等操作 + +## 安裝 + +**穩定版:** + +```bash +pip install je_web_runner +``` + +**開發版:** + +```bash +pip install je_web_runner_dev +``` + +## 系統需求 + +- Python **3.10** 或更高版本 +- 相依套件:`selenium>=4.0.0`、`requests`、`python-dotenv`、`webdriver-manager` + +## 快速開始 + +### 範例 1:直接使用 API + +```python +from je_web_runner import TestObject +from je_web_runner import get_webdriver_manager +from je_web_runner import web_element_wrapper + +# 建立 WebDriver 管理器(使用 Chrome) +manager = get_webdriver_manager("chrome") + +# 前往指定網址 +manager.webdriver_wrapper.to_url("https://www.google.com") + +# 設定隱式等待 +manager.webdriver_wrapper.implicitly_wait(2) + +# 建立測試物件,以 name 屬性定位搜尋框 +search_box = TestObject("q", "name") + +# 尋找元素 +manager.webdriver_wrapper.find_element(search_box) + +# 點擊並輸入文字 +web_element_wrapper.click_element() +web_element_wrapper.input_to_element("WebRunner 自動化") + +# 關閉瀏覽器 +manager.quit() +``` + +### 範例 2:JSON 動作列表 + +```python +from je_web_runner import execute_action + +actions = [ + ["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], + ["WR_to_url", {"url": "https://www.google.com"}], + ["WR_implicitly_wait", {"time_to_wait": 2}], + ["WR_SaveTestObject", {"test_object_name": "q", "object_type": "name"}], + ["WR_find_element", {"element_name": "q"}], + ["WR_click_element"], + ["WR_input_to_element", {"input_value": "WebRunner 自動化"}], + ["WR_quit"] +] + +result = execute_action(actions) +``` + +## 架構概覽 + +``` +je_web_runner/ +├── __init__.py # 公開 API 匯出 +├── __main__.py # 命令列進入點 +├── element/ +│ └── web_element_wrapper.py # 網頁元素互動包裝器 +├── manager/ +│ └── webrunner_manager.py # 多驅動程式管理 +├── webdriver/ +│ ├── webdriver_wrapper.py # 核心 WebDriver 包裝器 +│ └── webdriver_with_options.py # 瀏覽器選項設定 +└── utils/ + ├── callback/ # 回呼函式執行器 + ├── exception/ # 自訂例外類別 + ├── executor/ # 動作執行引擎 + ├── file_process/ # 檔案工具 + ├── generate_report/ # HTML/JSON/XML 報告產生器 + ├── json/ # JSON 檔案操作 + ├── logging/ # 日誌設定 + ├── package_manager/ # 動態套件載入 + ├── project/ # 專案範本產生器 + ├── selenium_utils_wrapper/ # Selenium 工具(Keys、Capabilities) + ├── socket_server/ # TCP Socket 伺服器(遠端控制) + ├── test_object/ # 測試物件與紀錄類別 + ├── test_record/ # 動作紀錄 + └── xml/ # XML 工具 +``` + +## 核心元件 + +### WebDriver 管理器 + +`WebdriverManager` 管理多個 WebDriver 實例,支援並行瀏覽器自動化。 + +```python +from je_web_runner import get_webdriver_manager + +# 建立管理器(使用 Chrome) +manager = get_webdriver_manager("chrome") + +# 新增另一個瀏覽器實例 +manager.new_driver("firefox") + +# 切換瀏覽器實例 +manager.change_webdriver(0) # 切換至 Chrome +manager.change_webdriver(1) # 切換至 Firefox + +# 關閉特定驅動程式 +manager.close_choose_webdriver(1) # 關閉 Firefox + +# 關閉所有驅動程式 +manager.quit() +``` + +### WebDriver 包裝器 + +`WebDriverWrapper` 是核心元件,包裝了 Selenium WebDriver 並提供全面的方法。 + +#### 導航 + +```python +wrapper = manager.webdriver_wrapper + +wrapper.to_url("https://example.com") +wrapper.forward() +wrapper.back() +wrapper.refresh() +``` + +#### 元素定位 + +```python +from je_web_runner import TestObject + +# 定位策略:id、name、xpath、css selector、class name、tag name、link text、partial link text +element = TestObject("search-input", "id") +wrapper.find_element(element) # 尋找單一元素 +wrapper.find_elements(element) # 尋找多個元素 +``` + +#### 等待方法 + +```python +wrapper.implicitly_wait(5) # 隱式等待(秒) +wrapper.explict_wait(10, method=some_func) # 顯式等待(WebDriverWait) +wrapper.set_script_timeout(30) # 非同步腳本逾時 +wrapper.set_page_load_timeout(60) # 頁面載入逾時 +``` + +#### 滑鼠與鍵盤操作 + +```python +wrapper.left_click() # 左鍵點擊 +wrapper.right_click() # 右鍵點擊 +wrapper.left_double_click() # 雙擊 +wrapper.left_click_and_hold() # 按住不放 +wrapper.release() # 釋放 +wrapper.drag_and_drop(source, target) # 拖放 +wrapper.drag_and_drop_offset(element, x=100, y=50) # 偏移拖放 +wrapper.move_to_element(element) # 滑鼠懸停 +wrapper.move_by_offset(100, 200) # 偏移移動 +wrapper.press_key(keycode) # 按下按鍵 +wrapper.release_key(keycode) # 釋放按鍵 +wrapper.send_keys("文字") # 發送按鍵 +wrapper.send_keys_to_element(element, "文字") # 對元素發送按鍵 +wrapper.perform() # 執行佇列中的動作 +wrapper.reset_actions() # 清除動作佇列 +wrapper.pause(2) # 暫停 +``` + +#### Cookie 管理 + +```python +wrapper.get_cookies() # 取得所有 Cookie +wrapper.get_cookie("session_id") # 取得特定 Cookie +wrapper.add_cookie({"name": "key", "value": "val"}) +wrapper.delete_cookie("session_id") +wrapper.delete_all_cookies() +``` + +#### JavaScript 執行 + +```python +wrapper.execute_script("document.title") +wrapper.execute_async_script("arguments[0]('done')", callback) +``` + +#### 視窗管理 + +```python +wrapper.maximize_window() # 最大化 +wrapper.minimize_window() # 最小化 +wrapper.fullscreen_window() # 全螢幕 +wrapper.set_window_size(1920, 1080) # 設定大小 +wrapper.set_window_position(0, 0) # 設定位置 +wrapper.get_window_position() # 取得位置 +wrapper.get_window_rect() # 取得矩形資訊 +wrapper.set_window_rect(x=0, y=0, width=1920, height=1080) +``` + +#### 螢幕截圖與捲動 + +```python +wrapper.get_screenshot_as_png() # 回傳 bytes +wrapper.get_screenshot_as_base64() # 回傳 base64 字串 +wrapper.scroll(0, 500) # 捲動頁面 +``` + +#### Frame / 視窗 / Alert 切換 + +```python +wrapper.switch("frame", "frame_name") +wrapper.switch("window", "window_handle") +wrapper.switch("default_content") +``` + +#### 瀏覽器日誌 + +```python +wrapper.get_log("browser") +``` + +### 網頁元素包裝器 + +`WebElementWrapper` 提供與已定位元素互動的方法。 + +```python +from je_web_runner import web_element_wrapper + +web_element_wrapper.click_element() # 點擊 +web_element_wrapper.input_to_element("Hello World") # 輸入 +web_element_wrapper.clear() # 清除 +web_element_wrapper.submit() # 提交 + +# 檢查屬性 +web_element_wrapper.get_attribute("href") +web_element_wrapper.get_property("checked") +web_element_wrapper.get_dom_attribute("data-id") +web_element_wrapper.is_displayed() # 是否可見 +web_element_wrapper.is_enabled() # 是否啟用 +web_element_wrapper.is_selected() # 是否選取 +web_element_wrapper.value_of_css_property("color") # CSS 屬性值 + +# 下拉選單 +select = web_element_wrapper.get_select() + +# 元素截圖 +web_element_wrapper.screenshot("element.png") + +# 從列表切換活動元素 +web_element_wrapper.change_web_element(2) + +# 驗證元素屬性 +web_element_wrapper.check_current_web_element({"tag_name": "input"}) +``` + +### 測試物件 + +`TestObject` 封裝元素定位資訊,可重複使用。 + +```python +from je_web_runner import TestObject, create_test_object, get_test_object_type_list + +# 兩種建立方式 +obj1 = TestObject("search", "name") +obj2 = create_test_object("id", "submit-btn") + +# 檢視可用的定位類型 +print(get_test_object_type_list()) +# ['ID', 'NAME', 'XPATH', 'CSS_SELECTOR', 'CLASS_NAME', 'TAG_NAME', 'LINK_TEXT', 'PARTIAL_LINK_TEXT'] +``` + +## 動作執行器 + +動作執行器是一個強大的引擎,將指令字串對應到可呼叫的函式。它允許您以 JSON 動作列表定義自動化腳本。 + +### 動作格式 + +每個動作是一個列表,包含指令名稱和可選參數: + +```python +["指令名稱"] # 無參數 +["指令名稱", {"key": "value"}] # 關鍵字參數 +["指令名稱", [arg1, arg2]] # 位置參數 +``` + +### 可用指令 + +| 類別 | 指令 | +|------|------| +| **管理器** | `WR_get_webdriver_manager`、`WR_change_index_of_webdriver`、`WR_quit` | +| **導航** | `WR_to_url`、`WR_forward`、`WR_back`、`WR_refresh` | +| **元素** | `WR_find_element`、`WR_find_elements`、`WR_find_element_with_test_object_record`、`WR_find_elements_with_test_object_record` | +| **等待** | `WR_implicitly_wait`、`WR_explict_wait`、`WR_set_script_timeout`、`WR_set_page_load_timeout` | +| **點擊** | `WR_left_click`、`WR_right_click`、`WR_left_double_click`、`WR_left_click_and_hold`、`WR_release` | +| **拖放** | `WR_drag_and_drop`、`WR_drag_and_drop_offset`、`WR_drag_and_drop_with_test_object`、`WR_drag_and_drop_offset_with_test_object` | +| **懸停** | `WR_move_to_element`、`WR_move_to_element_with_offset`、`WR_move_by_offset` | +| **鍵盤** | `WR_press_key`、`WR_release_key`、`WR_send_keys`、`WR_send_keys_to_element` | +| **動作鏈** | `WR_perform`、`WR_reset_actions`、`WR_pause` | +| **Cookie** | `WR_get_cookies`、`WR_get_cookie`、`WR_add_cookie`、`WR_delete_cookie`、`WR_delete_all_cookies` | +| **JavaScript** | `WR_execute_script`、`WR_execute_async_script` | +| **視窗** | `WR_maximize_window`、`WR_minimize_window`、`WR_fullscreen_window`、`WR_set_window_size`、`WR_set_window_position`、`WR_set_window_rect` | +| **截圖** | `WR_get_screenshot_as_png`、`WR_get_screenshot_as_base64` | +| **元素操作** | `WR_click_element`、`WR_input_to_element`、`WR_element_clear`、`WR_element_submit`、`WR_element_get_attribute`、`WR_element_is_displayed`、`WR_element_is_enabled`、`WR_element_is_selected` | +| **測試物件** | `WR_SaveTestObject`、`WR_CleanTestObject` | +| **報告** | `WR_generate_html_report`、`WR_generate_json_report`、`WR_generate_xml_report` | +| **套件** | `WR_add_package_to_executor` | +| **巢狀執行** | `WR_execute_action`、`WR_execute_files` | + +### 從 JSON 檔案執行 + +```python +from je_web_runner import execute_files + +# 從 JSON 檔案執行動作 +results = execute_files(["actions1.json", "actions2.json"]) +``` + +JSON 檔案格式: + +```json +[ + ["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], + ["WR_to_url", {"url": "https://example.com"}], + ["WR_quit"] +] +``` + +### 新增自訂指令 + +```python +from je_web_runner import add_command_to_executor + +def my_custom_function(param1, param2): + print(f"自訂:{param1}、{param2}") + +add_command_to_executor({"my_command": my_custom_function}) +``` + +## 報告產生 + +WebRunner 可自動記錄所有動作,並以三種格式產生報告。 + +### 啟用紀錄 + +```python +from je_web_runner import test_record_instance + +test_record_instance.set_record_enable(True) +``` + +### HTML 報告 + +```python +from je_web_runner import generate_html, generate_html_report + +# 產生 HTML 字串 +html_content = generate_html() + +# 儲存至檔案(建立 test_results.html) +generate_html_report("test_results") +``` + +HTML 報告包含顏色標記的表格:成功為**青色**,失敗為**紅色**。每列顯示函式名稱、參數、時間戳記及例外資訊(如有)。 + +### JSON 報告 + +```python +from je_web_runner import generate_json, generate_json_report + +# 產生字典 +success_dict, failure_dict = generate_json() + +# 儲存至檔案(建立 test_results_success.json 和 test_results_failure.json) +generate_json_report("test_results") +``` + +### XML 報告 + +```python +from je_web_runner import generate_xml, generate_xml_report + +# 產生 XML 字串 +success_xml, failure_xml = generate_xml() + +# 儲存至檔案(建立 test_results_success.xml 和 test_results_failure.xml) +generate_xml_report("test_results") +``` + +## 遠端自動化(Socket 伺服器) + +WebRunner 內建多執行緒 TCP Socket 伺服器,支援遠端自動化控制。 + +### 啟動伺服器 + +```python +from je_web_runner import start_web_runner_socket_server + +server = start_web_runner_socket_server(host="localhost", port=9941) +``` + +### 客戶端連線 + +```python +import socket +import json + +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.connect(("localhost", 9941)) + +# 以 JSON 格式發送動作 +actions = [ + ["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], + ["WR_to_url", {"url": "https://example.com"}], + ["WR_quit"] +] +sock.send(json.dumps(actions).encode("utf-8")) + +# 接收結果(以 "Return_Data_Over_JE\n" 結尾) +response = sock.recv(4096).decode("utf-8") +print(response) + +# 關閉伺服器 +sock.send("quit_server".encode("utf-8")) +``` + +## 回呼執行器 + +執行自動化指令並在完成後觸發回呼函式。 + +```python +from je_web_runner import callback_executor + +def on_complete(): + print("導航完成!") + +callback_executor.callback_function( + trigger_function_name="WR_to_url", + callback_function=on_complete, + url="https://example.com" +) +``` + +附帶參數: + +```python +def on_element_found(result=None): + print(f"元素已找到:{result}") + +callback_executor.callback_function( + trigger_function_name="WR_find_element", + callback_function=on_element_found, + callback_function_param={"result": "search_box"}, + callback_param_method="kwargs", + element_name="search_box" +) +``` + +## 套件管理器 + +於執行期間動態載入外部 Python 套件至執行器。 + +```python +from je_web_runner import execute_action + +actions = [ + # 載入 'time' 套件 + ["WR_add_package_to_executor", {"package": "time"}], + # 現在可以使用 time.sleep + ["time_sleep", [2]] +] + +execute_action(actions) +``` + +## 專案範本 + +快速建立專案結構及範例檔案。 + +```python +from je_web_runner import create_project_dir + +create_project_dir(project_path="./my_project", parent_name="WebRunner") +``` + +產生的結構: + +``` +my_project/WebRunner/ +├── keyword/ +│ ├── keyword1.json +│ ├── keyword2.json +│ └── bad_keyword_1.json +└── executor/ + ├── executor_one_file.py + ├── executor_folder.py + └── executor_bad_file.py +``` + +## 命令列介面 + +WebRunner 可直接從命令列執行。 + +```bash +# 執行單一 JSON 動作檔案 +python -m je_web_runner -e actions.json + +# 執行目錄中所有 JSON 檔案 +python -m je_web_runner -d ./actions/ + +# 直接執行 JSON 字串 +python -m je_web_runner --execute_str '[["WR_get_webdriver_manager", {"webdriver_name": "chrome"}], ["WR_quit"]]' +``` + +## WebDriver 選項設定 + +於啟動前設定瀏覽器選項。 + +```python +from je_web_runner import set_webdriver_options_argument, get_webdriver_manager + +# 設定瀏覽器參數(例如:無頭模式) +options = set_webdriver_options_argument("chrome", [ + "--headless", + "--disable-gpu", + "--no-sandbox", + "--window-size=1920,1080" +]) + +# 以選項啟動 +manager = get_webdriver_manager("chrome", options=["--headless", "--disable-gpu"]) +``` + +### DesiredCapabilities + +```python +from je_web_runner import get_desired_capabilities, get_desired_capabilities_keys + +# 檢視可用的功能 +keys = get_desired_capabilities_keys() + +# 取得瀏覽器的功能 +caps = get_desired_capabilities("CHROME") +``` + +## 測試紀錄 + +所有 WebRunner 動作會自動記錄,用於稽核追蹤及報告產生。 + +```python +from je_web_runner import test_record_instance + +# 啟用紀錄 +test_record_instance.set_record_enable(True) + +# ... 執行自動化操作 ... + +# 存取紀錄 +records = test_record_instance.test_record_list + +# 每筆紀錄包含: +# { +# "function_name": "to_url", +# "local_param": {"url": "https://example.com"}, +# "time": "2025-01-01 12:00:00", +# "program_exception": "None" +# } + +# 清除紀錄 +test_record_instance.clean_record() +``` + +## 例外處理 + +WebRunner 提供完整的自訂例外階層: + +| 例外 | 說明 | +|------|------| +| `WebRunnerException` | 基礎例外 | +| `WebRunnerWebDriverNotFoundException` | 找不到 WebDriver | +| `WebRunnerOptionsWrongTypeException` | 選項類型錯誤 | +| `WebRunnerArgumentWrongTypeException` | 參數類型錯誤 | +| `WebRunnerWebDriverIsNoneException` | WebDriver 為 None | +| `WebRunnerExecuteException` | 執行錯誤 | +| `WebRunnerJsonException` | JSON 處理錯誤 | +| `WebRunnerGenerateJsonReportException` | JSON 報告產生錯誤 | +| `WebRunnerAssertException` | 斷言失敗 | +| `WebRunnerHTMLException` | HTML 報告錯誤 | +| `WebRunnerAddCommandException` | 指令註冊錯誤 | +| `XMLException` / `XMLTypeException` | XML 處理錯誤 | +| `CallbackExecutorException` | 回呼執行錯誤 | + +## 日誌記錄 + +WebRunner 使用旋轉式檔案處理器記錄日誌。 + +- **日誌檔案:** `WEBRunner.log` +- **日誌等級:** WARNING 及以上 +- **檔案大小上限:** 1 GB +- **格式:** `%(asctime)s | %(name)s | %(levelname)s | %(message)s` + +## 支援的瀏覽器 + +| 瀏覽器 | 識別碼 | +|--------|--------| +| Google Chrome | `chrome` | +| Chromium | `chromium` | +| Mozilla Firefox | `firefox` | +| Microsoft Edge | `edge` | +| Internet Explorer | `ie` | +| Apple Safari | `safari` | + +## 支援的平台 + +- Windows +- macOS +- Ubuntu / Linux +- Raspberry Pi + +## 授權條款 + +本專案採用 [MIT 授權條款](../LICENSE)。 + +Copyright (c) 2021~2023 JE-Chen