Provide Basic Interface to conrol Mobile UI.
Project description
Nico - Cross-Platform Mobile Automation Framework
For iOS, you need to compile nico_dump and install it on your iPhone device.
📖 Full Documentation Table of Contents
- Background
- Chinese Version
- Installation
- Element Locators
- User Guide
- NicoElement API
- ADB Toolset
- IDB Toolset
- Command Line Shortcuts
- Best Practices
- Contribution Guidelines
🌟 Core Features
- Cross-Platform Support: Works with both Android (UIAutomation2) and iOS (XCUITest)
- Background Execution: Runs tests in the background without interrupting user interactions
- Intelligent Element Locators: Supports attribute queries, regex matching, and fuzzy search
- Rich Operation Library: Over 30 methods for clicks, swipes, inputs, screenshots, and more
- Visual Debugging: Built-in UI Inspector for real-time interface structure inspection
🚀 Quick Start
1. Installation
pip install AutoNico
2. Launch UI Inspector
nico_ui -s {udid} # View real-time interface structure
3. Basic Test Script
# Android Example
from auto_nico.android.nico_android import NicoAndroid
nico = NicoAndroid("emulator-5554")
nico(text="Add network").wait_for_appearance()
nico(text="Add network").click()
nico(class_name="EditText").set_text("TestSSID")
nico(text="Save").click()
# iOS Example
from auto_nico.ios.nico_ios import NicoIOS
nico = NicoIOS("00008020-00105C883A42001E")
nico(identifier="login_button").wait_for_appearance()
nico(identifier="login_button").click()
nico(xpath="//XCUIElementTypeTextField").set_text("user@example.com")
📄 Full Feature Documentation
🔍 Element Locators
Launch UI Inspector
nico_ui -s {udid}
Supported Query Parameters
| Parameter Type | Android Supported Fields | iOS Supported Fields |
|---|---|---|
| Basic Attributes | text, resource_id, class_name | text, identifier, class_name |
| State Attributes | clickable, enabled, checked | value, xpath |
| Layout Attributes | index, package, content_desc | index |
Query Examples
# Fuzzy match
nico(text_contains="WiFi").wait_for_appearance()
# Regex match
nico(text_matches="^Search.*").click()
# Combined conditions
nico(class_name="Button", enabled=True).all()
📱 User Guide
Initialize Device
# Android initialization
from auto_nico.android.nico_android import NicoAndroid
nico_android = NicoAndroid("emulator-5554")
# iOS initialization
from auto_nico.ios.nico_ios import NicoIOS
nico_ios = NicoIOS("00008020-00105C883A42001E")
Element Waiting Strategies
# Wait for element appearance
nico(text="Login").wait_for_appearance(timeout=10)
# Wait for element disappearance
nico(class_name="Loading").wait_for_disappearance()
# Wait for any condition
index = nico().wait_for_any([
nico(text="Success"),
nico(text="Error")
], timeout=15)
🛠️ NicoElement API
Property Access
element = nico(text="Username")
print(element.get_text()) # Get text content
print(element.get_resource_id()) # Get resource ID
print(element.get_enabled()) # Get enabled state
Element Relationships
parent = element.parent()
sibling = element.next_sibling(2)
child = element.child(0)
Action Methods
# Click operation
element.click(x_offset=10, y_offset=20)
# Input operation
element.set_text("password", append=True)
# Swipe operation
element.swipe(to_x=500, to_y=1000, duration=1.5)
# Scroll operation
element.scroll(direction="vertical_down")
🧰 ADB Toolset (Android Only)
Complete Android device control through AdbUtils:
Initialization
from auto_nico.android.adb_utils import AdbUtils
adb = AdbUtils("emulator-5554") # Initialize with UDID
# Or get from Nico instance
nico = NicoAndroid("emulator-5554")
adb = nico.adb_utils
Full Interface List
| Method Name | Description | Parameters | Return Value |
|---|---|---|---|
get_tcp_forward_port() |
Get TCP forward port | None | int/None |
get_screen_size() |
Get screen dimensions | None | tuple(width, height) |
start_app(package_name) |
Launch application | package_name: App package ID |
None |
stop_app(package_name) |
Stop application | package_name: App package ID |
None |
restart_app(package_name) |
Restart application | package_name: App package ID |
None |
qucik_shell(cmd) |
Execute ADB shell command | cmd: Command string |
str output |
cmd(cmd) |
Execute full ADB command | cmd: Command string |
str output |
is_keyboard_shown() |
Check keyboard visibility | None | bool |
is_screenon() |
Check screen status | None | bool |
is_locked() |
Check screen lock status | None | bool |
unlock() |
Unlock device | None | None |
back() |
Simulate back button | None | None |
menu() |
Simulate menu button | None | None |
home() |
Simulate home button | None | None |
snapshot(name, path) |
Capture and save screenshot | name: File name, path: Save path |
None |
Advanced Example
# Check device status
if adb.is_screenon() and not adb.is_locked():
print("Device unlocked and active")
else:
adb.unlock()
# Launch app and wait for element
adb.start_app("com.android.settings")
nico(text="Wi-Fi").wait_for_appearance()
# Execute custom command
result = adb.cmd("shell dumpsys window displays")
print("Display info:", result)
🧰 IDB Toolset (iOS Only)
Complete iOS device control through IdbUtils:
Initialization
from auto_nico.ios.idb_utils import IdbUtils
idb = IdbUtils("00008020-00105C883A42001E") # Initialize with UDID
# Or get from Nico instance
nico = NicoIOS("00008020-00105C883A42001E")
idb = nico.idb_utils
Full Interface List
| Method Name | Description | Parameters | Return Value |
|---|---|---|---|
get_tcp_forward_port() |
Get TCP forward port | None | int/None |
is_greater_than_ios_17() |
Check iOS version ≥17 | None | bool |
device_list() |
Get connected devices | None | str device list |
set_port_forward(port) |
Set port forwarding | port: Target port |
None |
get_app_list() |
Get installed apps | None | List[str] app list |
get_test_server_package() |
Get test server package info | None | dict with test_server and main_package |
get_wda_server_package() |
Get WDA server package name | None | str WDA package name |
start_app(package_name) |
Launch application | package_name: App bundle ID |
None |
stop_app(package_name) |
Stop application | package_name: App bundle ID |
None |
restart_app(package_name) |
Restart application | package_name: App bundle ID |
None |
start_recording() |
Start screen recording | None | None |
stop_recording(path) |
Stop recording and save video | path: Save location (default: output.mp4) |
None |
get_output_device_name() |
Get device name | None | str device name |
get_system_info() |
Get system information | None | dict system info |
cmd(cmd) |
Execute tidevice command | cmd: Command string |
str output |
activate_app(package_name) |
Activate application | package_name: App bundle ID |
None |
terminate_app(package_name) |
Terminate application | package_name: App bundle ID |
None |
home() |
Simulate home button | None | None |
get_volume() |
Get current volume | None | int volume percentage |
turn_volume_up() |
Increase volume | None | None |
turn_volume_down() |
Decrease volume | None | None |
snapshot(name, path) |
Capture and save screenshot | name: File name, path: Save path |
None |
get_pic(quality=1.0) |
Get screen image (binary data) | quality: Image quality (0.0-1.0) |
bytes image data |
get_image_object(quality=100) |
Get OpenCV image object | quality: Image quality (0-100) |
numpy.ndarray image |
click(x, y) |
Simulate tap at coordinates | x: X position, y: Y position |
None |
get_current_bundleIdentifier(port) |
Get current app bundle ID | port: Service port |
str bundle ID |
Advanced Example
# Screen recording
idb.start_recording()
idb.click(100, 200) # Perform test action
idb.stop_recording("./test.mp4")
# High-quality screenshot
image_data = idb.get_pic(0.9)
with open("high_quality.jpg", "wb") as f:
f.write(image_data)
# Volume control
current_volume = idb.get_volume()
print(f"Current volume: {current_volume}%")
idb.turn_volume_up()
🤝 Contribution Guidelines
- Code submission standards:
# Follow PEP8 guidelines def my_function(): """This is a docstring example""" pass
- Issue reporting: GitHub Issues
- Contribution guide: CONTRIBUTING.md
📄 License
MIT License - See LICENSE file for details.
Nico - 跨平台移动自动化测试框架
对于iOS, 需要自行编译nico_dump 安装到iPhone设备上
📖 完整文档目录
🌟 核心特性
- 跨平台支持:同时支持Android (UIAutomation2)和iOS (XCUITest)
- 后台运行:测试全程在后台执行,不干扰用户操作
- 智能元素定位:支持属性查询、正则匹配、模糊匹配
- 丰富操作库:点击/滑动/输入/截图等30+操作方法
- 可视化调试:内置UI Inspector实时查看界面结构
🚀 快速开始
1. 安装
pip install AutoNico
2. 启动UI Inspector
nico_ui -s {udid} # 查看实时界面结构
3. 基础测试脚本
# Android示例
from auto_nico.android.nico_android import NicoAndroid
nico = NicoAndroid("emulator-5554")
nico(text="Add network").wait_for_appearance()
nico(identifier="login_button").click()
nico(class_name="EditText").set_text("TestSSID")
nico(text="Save").click()
# iOS示例
from auto_nico.ios.nico_ios import NicoIOS
nico = NicoIOS("00008020-00105C883A42001E")
nico(identifier="login_button").wait_for_appearance()
nico(identifier="login_button").click()
nico(xpath="//XCUIElementTypeTextField").set_text("user@example.com")
📄 完整功能文档
🔍 元素定位
启动UI Inspector
nico_ui -s {udid}
支持的查询参数
| 参数类型 | Android支持字段 | iOS支持字段 |
|---|---|---|
| 基础属性 | text, resource_id, class_name | text, identifier, class_name |
| 状态属性 | clickable, enabled, checked | value, xpath |
| 布局属性 | index, package, content_desc | index |
查询示例
# 模糊匹配
nico(text_contains="WiFi").wait_for_appearance()
# 正则匹配
nico(text_matches="^Search.*").click()
# 组合条件
nico(class_name="Button", enabled=True).all()
📱 使用指南
初始化设备
# Android初始化
from auto_nico.android.nico_android import NicoAndroid
nico_android = NicoAndroid("emulator-5554")
# iOS初始化
from auto_nico.ios.nico_ios import NicoIOS
nico_ios = NicoIOS("00008020-00105C883A42001E")
元素等待策略
# 等待元素出现
nico(text="Login").wait_for_appearance(timeout=10)
# 等待元素消失
nico(class_name="Loading").wait_for_disappearance()
# 等待任一条件
index = nico().wait_for_any([
nico(text="Success"),
nico(text="Error")
], timeout=15)
🛠️ NicoElement API
属性访问
element = nico(text="Username")
print(element.get_text()) # 获取文本
print(element.get_resource_id()) # 获取资源ID
print(element.get_enabled()) # 获取启用状态
元素关系
parent = element.parent()
sibling = element.next_sibling(2)
child = element.child(0)
操作方法
# 点击操作
element.click(x_offset=10, y_offset=20)
# 输入操作
element.set_text("password", append=True)
# 滑动操作
element.swipe(to_x=500, to_y=1000, duration=1.5)
# 滚动操作
element.scroll(direction="vertical_down")
🧰 ADB工具集(Android专用)
通过AdbUtils类提供完整的Android设备控制能力:
初始化方式
from auto_nico.android.adb_utils import AdbUtils
adb = AdbUtils("emulator-5554") # 通过udid初始化
# 或通过Nico实例获取
nico = NicoAndroid("emulator-5554")
adb = nico.adb_utils
完整接口列表
| 方法名 | 功能描述 | 参数说明 | 返回值 |
|---|---|---|---|
get_tcp_forward_port() |
获取TCP转发端口 | 无 | int 端口号 / None |
get_screen_size() |
获取屏幕尺寸 | 无 | tuple(width, height) |
start_app(package_name) |
启动应用 | package_name: 应用包名 |
无 |
stop_app(package_name) |
停止应用 | package_name: 应用包名 |
无 |
restart_app(package_name) |
重启应用 | package_name: 应用包名 |
无 |
qucik_shell(cmd) |
执行adb shell命令 | cmd: 命令字符串 |
str 命令输出 |
cmd(cmd) |
执行完整adb命令 | cmd: 命令字符串 |
str 命令输出 |
is_keyboard_shown() |
检查键盘是否弹出 | 无 | bool |
is_screenon() |
检查屏幕是否亮起 | 无 | bool |
is_locked() |
检查屏幕是否锁定 | 无 | bool |
unlock() |
解锁屏幕 | 无 | 无 |
back() |
模拟返回键 | 无 | 无 |
menu() |
模拟菜单键 | 无 | 无 |
home() |
模拟Home键 | 无 | 无 |
snapshot(name, path) |
截图并保存 | name: 文件名, path: 保存路径 |
无 |
高级用法示例
# 检查设备状态
if adb.is_screenon() and not adb.is_locked():
print("设备已解锁并处于亮屏状态")
else:
adb.unlock()
# 启动应用并等待元素出现
adb.start_app("com.android.settings")
nico(text="Wi-Fi").wait_for_appearance()
# 执行自定义adb命令
result = adb.cmd("shell dumpsys window displays")
print("Display信息:", result)
🧰 IDB工具集(iOS专用)
通过IdbUtils类提供完整的iOS设备控制能力:
初始化方式
from auto_nico.ios.idb_utils import IdbUtils
idb = IdbUtils("00008020-00105C883A42001E") # 通过udid初始化
# 或通过Nico实例获取
nico = NicoIOS("00008020-00105C883A42001E")
idb = nico.idb_utils
完整接口列表
| 方法名 | 功能描述 | 参数说明 | 返回值 |
|---|---|---|---|
get_tcp_forward_port() |
获取TCP转发端口 | 无 | int 端口号 / None |
is_greater_than_ios_17() |
检查iOS版本是否≥17 | 无 | bool |
device_list() |
获取设备列表 | 无 | str 设备信息列表 |
set_port_forward(port) |
设置端口转发 | port: 目标端口 |
无 |
get_app_list() |
获取已安装应用列表 | 无 | List[str] 应用信息列表 |
get_test_server_package() |
获取测试服务器包名 | 无 | dict 包含test_server和main_package |
get_wda_server_package() |
获取WDA服务器包名 | 无 | str WDA包名 |
start_app(package_name) |
启动应用 | package_name: 应用包名 |
无 |
stop_app(package_name) |
停止应用 | package_name: 应用包名 |
无 |
restart_app(package_name) |
重启应用 | package_name: 应用包名 |
无 |
start_recording() |
开始屏幕录制 | 无 | 无 |
stop_recording(path) |
停止录制并保存视频 | path: 保存路径(默认output.mp4) |
无 |
get_output_device_name() |
获取设备名称 | 无 | str 设备名称 |
get_system_info() |
获取系统信息 | 无 | dict 系统信息字典 |
cmd(cmd) |
执行tidevice命令 | cmd: 命令字符串 |
str 命令输出 |
activate_app(package_name) |
激活应用 | package_name: 应用包名 |
无 |
terminate_app(package_name) |
终止应用 | package_name: 应用包名 |
无 |
home() |
模拟Home键 | 无 | 无 |
get_volume() |
获取音量 | 无 | int 音量值 |
turn_volume_up() |
调高音量 | 无 | 无 |
turn_volume_down() |
调低音量 | 无 | 无 |
snapshot(name, path) |
截图并保存 | name: 文件名, path: 保存路径 |
无 |
get_pic(quality=1.0) |
获取屏幕图片(二进制数据) | quality: 图片质量(0.0-1.0) |
bytes 图片数据 |
get_image_object(quality=100) |
获取OpenCV格式图片对象 | quality: 图片质量(0-100) |
numpy.ndarray 图片对象 |
click(x, y) |
模拟点击坐标 | x: X坐标, y: Y坐标 |
无 |
get_current_bundleIdentifier(port) |
获取当前应用包名 | port: 服务端口 |
str 包名 |
高级用法示例
# 屏幕录制
idb.start_recording()
# 执行测试操作
idb.click(100, 200)
idb.stop_recording("./test.mp4")
# 获取高质量截图
image_data = idb.get_pic(0.9)
with open("high_quality.jpg", "wb") as f:
f.write(image_data)
# 系统音量控制
current_volume = idb.get_volume()
print(f"当前音量: {current_volume}%")
idb.turn_volume_up()
🤝 参与贡献
- 提交代码规范:
# 遵循PEP8规范 def my_function(): """This is a docstring example""" pass
- 问题反馈:GitHub Issues
- 贡献指南:CONTRIBUTING.md
📄 许可证
MIT License - 请查看 LICENSE 文件
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file autonico-1.3.6-py3-none-any.whl.
File metadata
- Download URL: autonico-1.3.6-py3-none-any.whl
- Upload date:
- Size: 58.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.21
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa3f5de6dc9e7f021f1565b9690c2433dbc66f1fa18dc5447d1e859479af4c3d
|
|
| MD5 |
951841a49aabec96f48d901e3cc872e6
|
|
| BLAKE2b-256 |
e31bdf282e523d0e12d89ab6c3a744a429319554b9d6ef87f4d1d3ccd2366264
|