Skip to content

Commit

Permalink
实例化顺序修复
Browse files Browse the repository at this point in the history
  • Loading branch information
1103837067 committed Oct 20, 2024
1 parent c59a90f commit 97060bb
Show file tree
Hide file tree
Showing 14 changed files with 191 additions and 130 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,5 @@ dmypy.json
# Pyre type checker
.pyre/
.idea/

debug.py
40 changes: 37 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# HA4T 🐍

[![PyPI version](https://badge.fury.io/py/ha4t.svg)](https://badge.fury.io/py/ha4t)
[![Documentation Status](https://img.shields.io/badge/docs-latest-brightgreen)](exuils.github.io/HA4T/)
[![Documentation Status](https://img.shields.io/badge/docs-latest-brightgreen)](https://exuils.github.io/HA4T/)

HA4T (Hybrid App For Testing Tool)
是一个跨平台的UI自动化框架,适用于混合型app、web和原生app等。该框架基于airtest、飞浆OCR、WS、uiautomator2和facebook_wda进行开发。
Expand All @@ -25,13 +25,47 @@ pip install ha4t
以下是一个简单的示例,展示如何使用HA4T进行基本操作:

```python

# 原生定位
from ha4t import connect
...
from ha4t.api import *

connect(platform="android")

# 启动应用
start_app(activity="com.xxx.xxx.MainActivity",app_name="com.xxx.xxx")

# 等待
wait(text="添加新项目",timeout=30)

# orc 文字识别定位 中/英
click("添加新项目")
# 图像匹配定位
click(image = "./添加新项目.png")
from ha4t.aircv.cv import Template
click(Template("./添加新项目.png"))
# u2 元素定位
click(text="添加新项目")


# webview 定位
from ha4t.cdp.cdp import CDP
from ha4t.cdp.server import CdpServer
from ha4t.cdp.by import By

cdp_server = CdpServer()
cdp_server.start_server_for_android_app(device.driver.adb_device)
cdp = CDP(cdp_server.ws_endpoint)


window = cdp.get_page(["homePage"])
time.sleep(3)
window.click((By.TEXT, "新建项目"))
```

## 详细文档(未完善)

查看我们的[详细文档](exuils.github.io/HA4T/)以获取更多信息,包括:
查看我们的[详细文档](https://exuils.github.io/HA4T/)以获取更多信息,包括:

- 完整的API参考
- 高级用法指南
Expand Down
54 changes: 35 additions & 19 deletions docs/source/README_MORE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,38 @@ You can also install it from Git repository.
------------
.. code-block:: python
from ha4t.api import *
# 连接设备
device = Device("android")
# 启动应用
start_app("com.example.app")
# 点击元素
click("登录")
# 输入文本
input("用户名", "testuser")
# 等待元素出现
wait("登录成功")
# 断言文本存在
assert "欢迎回来" in get_page_text()
# 原生定位
from ha4t import connect
from ha4t.api import *
connect(platform="android")
# 启动应用
start_app(activity="com.xxx.xxx.MainActivity",app_name="com.xxx.xxx")
# 等待
wait(text="添加新项目",timeout=30)
# orc 文字识别定位 中/英
click("添加新项目")
# 图像匹配定位
click(image = "./添加新项目.png")
from ha4t.aircv.cv import Template
click(Template("./添加新项目.png"))
# u2 元素定位
click(text="添加新项目")
# webview 定位
from ha4t.cdp.cdp import CDP
from ha4t.cdp.server import CdpServer
from ha4t.cdp.by import By
cdp_server = CdpServer()
cdp_server.start_server_for_android_app(device.driver.adb_device)
cdp = CDP(cdp_server.ws_endpoint)
window = cdp.get_page(["homePage"])
time.sleep(3)
window.click((By.TEXT, "新建项目"))
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ HA4T 是一个强大的 UI 自动化测试框架,支持 Android 和 iOS 平台

modules/ha4t.cdp.cdp
modules/ha4t.cdp.server
modules/ha4t.cdp.by

================================

Expand Down
7 changes: 0 additions & 7 deletions docs/source/modules/ha4t.by.rst

This file was deleted.

7 changes: 7 additions & 0 deletions docs/source/modules/ha4t.cdp.by.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ha4t.cdp.by module
==================

.. automodule:: ha4t.cdp.by
:members:
:undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions docs/source/modules/ha4t.cdp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Submodules
.. toctree::
:maxdepth: 4

ha4t.cdp.by
ha4t.cdp.cdp
ha4t.cdp.jsCode
ha4t.cdp.server
Expand Down
1 change: 0 additions & 1 deletion docs/source/modules/ha4t.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ Submodules
:maxdepth: 4

ha4t.api
ha4t.by
ha4t.config
ha4t.orc

Expand Down
27 changes: 17 additions & 10 deletions ha4t/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,38 @@
from ha4t.config import Config as _CF

class Device:
def __init__(self, platform: str, device_id: Optional[str] = None, port: int = 8100):
def __init__(self):
self.driver = None

def connect(self, platform: str, device_serial: Optional[str] = None, port: int = 8100):
self.adb: Optional[Any] = None
if platform == "ios":
try:
_CF.DEVICE_SERIAL = device_id or wda.list_devices()[0].serial
_CF.DEVICE_SERIAL = device_serial or wda.list_devices()[0].serial
except IndexError:
raise IndexError("未找到设备,请检查连接")
self.driver: wda.Client = wda.USBClient(udid=_CF.DEVICE_SERIAL, port=port)
else:
self.driver: u2.Device = u2.connect(serial=device_id)
self.driver: u2.Device = u2.connect(serial=device_serial)
self.adb = self.driver.adb_device
_CF.DEVICE_SERIAL = self.adb.serial
self.device_info = json.dumps(self.driver.info, ensure_ascii=False, indent=4)
log_out(f"设备信息:{self.device_info}")

device: Device = None
driver: Union[u2.Device, wda.Client] = None
device: Device = Device()
screen_size: Tuple[int, int] = (0, 0)

def connect(device_serial="", android_package_name=None, android_activity_name=None, platform="android"):
device.__dict__.update(Device(_CF.PLATFORM, device_id=_CF.DEVICE_SERIAL).__dict__)
driver.__dict__.update(device.driver.__dict__)
screen_size.__dict__.update(driver.window_size().__dict__)
_CF.SCREEN_WIDTH, _CF.SCREEN_HEIGHT = screen_size
def connect(device_serial=_CF.DEVICE_SERIAL, android_package_name=_CF.ANDROID_PACKAGE_NAME, android_activity_name=_CF.ANDROID_ACTIVITY_NAME, platform=_CF.PLATFORM):
"""
连接设备
"""
global device, driver, screen_size
_CF.PLATFORM = platform
_CF.DEVICE_SERIAL = device_serial
device.connect(platform, device_serial)
screen_size = device.driver.window_size()
_CF.SCREEN_WIDTH, _CF.SCREEN_HEIGHT = screen_size
_CF.ANDROID_PACKAGE_NAME = android_package_name
_CF.ANDROID_ACTIVITY_NAME = android_activity_name
_CF.DEVICE_SERIAL = device.driver.serial

42 changes: 21 additions & 21 deletions ha4t/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from ha4t.orc import OCR
from ha4t.utils.files_operat import get_file_list as _get_file_list
from ha4t.utils.log_utils import log_out, cost_time
from ha4t import screen_size,driver
from ha4t import screen_size, device

logreset.reset_logging() # paddleocr 会污染 logging
ocr = OCR()
Expand Down Expand Up @@ -50,9 +50,9 @@ def perform_click(x, y, duration):
:param duration: 点击持续时间
"""
if _CF.PLATFORM == "ios":
driver.tap_hold(x, y, duration=duration)
device.driver.tap_hold(x, y, duration=duration)
else:
driver.long_click(x, y, duration=duration)
device.driver.long_click(x, y, duration=duration)

if args:
if isinstance(args[0], tuple):
Expand All @@ -61,27 +61,27 @@ def perform_click(x, y, duration):
elif isinstance(args[0][0], str):
raise NotImplementedError("webview点击暂不支持")
elif isinstance(args[0], str):
pos = ocr.get_text_pos(args[0], driver.screenshot, index=args[1] if len(args) > 1 else 0)
pos = ocr.get_text_pos(args[0], device.driver.screenshot, index=args[1] if len(args) > 1 else 0)
perform_click(*pos, duration)
elif isinstance(args[0], dict):
path = os.path.join(_CF.CURRENT_PATH, args[0]["image"])
pos = match_loop(screenshot_func=driver.screenshot, template=path, timeout=kwargs.get("timeout", 10),
pos = match_loop(screenshot_func=device.driver.screenshot, template=path, timeout=kwargs.get("timeout", 10),
threshold=kwargs.get("threshold", 0.8))
perform_click(*pos, duration)
elif isinstance(args[0], Template):
pos = match_loop(screenshot_func=driver.screenshot, template=args[0].filepath,
pos = match_loop(screenshot_func=device.driver.screenshot, template=args[0].filepath,
timeout=kwargs.get("timeout", 10), threshold=kwargs.get("threshold", 0.8))
perform_click(*pos, duration)
elif kwargs.get("image"):
path = os.path.join(_CF.CURRENT_PATH, kwargs["image"])
pos = match_loop(screenshot_func=driver.screenshot, template=path, timeout=kwargs.get("timeout", 10),
pos = match_loop(screenshot_func=device.driver.screenshot, template=path, timeout=kwargs.get("timeout", 10),
threshold=kwargs.get("threshold", 0.8))
perform_click(*pos, duration)
else:
if _CF.PLATFORM == "ios":
driver(**kwargs).tap_hold(duration=duration)
device.driver.tap_hold(duration=duration)
else:
driver(**kwargs).long_click(duration=duration)
device.driver.long_click(duration=duration)


def _exists(*args, **kwargs) -> bool:
Expand All @@ -105,22 +105,22 @@ def _exists(*args, **kwargs) -> bool:
raise NotImplementedError("webview点击暂不支持")
elif isinstance(args[0], str):
try:
pos = ocr.get_text_pos(args[0], driver.screenshot, index=args[1] if len(args) > 1 else 0, timeout=1)
pos = ocr.get_text_pos(args[0], device.driver.screenshot, index=args[1] if len(args) > 1 else 0, timeout=1)
return True
except:
return False

elif isinstance(args[0], dict):
path = os.path.join(_CF.CURRENT_PATH, args[0]["image"])
try:
match_loop(screenshot_func=driver.screenshot, template=path, timeout=kwargs.get("timeout", 10),
match_loop(screenshot_func=device.driver.screenshot, template=path, timeout=kwargs.get("timeout", 10),
threshold=kwargs.get("threshold", 0.8))
return True
except:
return False
elif isinstance(args[0], Template):
try:
match_loop(screenshot_func=driver.screenshot, template=args[0].filepath,
match_loop(screenshot_func=device.driver.screenshot, template=args[0].filepath,
timeout=kwargs.get("timeout", 10),
threshold=kwargs.get("threshold", 0.8))
return True
Expand All @@ -129,14 +129,14 @@ def _exists(*args, **kwargs) -> bool:
else:
if kwargs.get("image"):
path = os.path.join(_CF.CURRENT_PATH, kwargs["image"])
pos = match_loop(screenshot_func=driver.screenshot, template=path, timeout=kwargs.get("timeout", 10),
pos = match_loop(screenshot_func=device.driver.screenshot, template=path, timeout=kwargs.get("timeout", 10),
threshold=kwargs.get("threshold", 0.8))
if pos:
return True
else:
return False
else:
return driver(**kwargs).exists
return device.driver(**kwargs).exists


@cost_time
Expand Down Expand Up @@ -226,7 +226,7 @@ def calculate_position(p):

pos1 = calculate_position(p1)
pos2 = calculate_position(p2)
driver.swipe(*pos1, *pos2, duration=duration, steps=steps)
device.driver.swipe(*pos1, *pos2, duration=duration, steps=steps)


def get_page_text() -> str:
Expand All @@ -236,7 +236,7 @@ def get_page_text() -> str:
:return: 页面上的所有文字拼接成的字符串
"""
return ocr.get_page_text(driver.screenshot)
return ocr.get_page_text(device.driver.screenshot)


@cost_time
Expand Down Expand Up @@ -310,7 +310,7 @@ def screenshot(filename: Optional[str] = None) -> PIL.Image.Image:
>>> img = screenshot() # 截图并不保存
>>> screenshot("screenshot.png") # 截图并保存为文件
"""
img = driver.screenshot()
img = device.driver.screenshot()
img = PIL.Image.fromarray(img) if isinstance(img, np.ndarray) else img
if filename:
img.save(filename)
Expand All @@ -336,7 +336,7 @@ def home() -> None:
:Example:
>>> home() # 返回主屏幕
"""
driver.press("home")
device.driver.press("home")


@cost_time
Expand Down Expand Up @@ -487,12 +487,12 @@ def start_app(app_name: Optional[str] = None, activity: Optional[str] = None) ->
app_name = app_name or _CF.APP_NAME

if _CF.PLATFORM == "ios":
driver.app_start(app_name)
device.driver.app_start(app_name)
else:
activity = activity or _CF.ANDROID_ACTIVITY_NAME
if activity is None:
raise ValueError("Android平台必须提供activity参数")
driver.adb_device.app_start(app_name, activity)
device.driver.adb_device.app_start(app_name, activity)


def restart_app(app_name: Optional[str] = None, activity: Optional[str] = None) -> None:
Expand All @@ -502,7 +502,7 @@ def restart_app(app_name: Optional[str] = None, activity: Optional[str] = None)
:Example:
>>> restart_app() # 重启当前应用
"""
driver.app_stop(app_name)
device.driver.app_stop(app_name)
start_app(app_name, activity)


Expand Down
File renamed without changes.
Loading

0 comments on commit 97060bb

Please sign in to comment.