kuto
Advanced tools
@@ -5,4 +5,3 @@ """ | ||
| """ | ||
| import kuto | ||
| from kuto.android import Elem | ||
| from kuto.android import Page, Elem | ||
@@ -19,3 +18,3 @@ """ | ||
| class HomePage(kuto.Page): | ||
| class HomePage(Page): | ||
| """APP首页""" | ||
@@ -27,3 +26,3 @@ adBtn = Elem(rid='bottom_btn', desc='广告关闭按钮') | ||
| class MyPage(kuto.Page): | ||
| class MyPage(Page): | ||
| """我的页""" | ||
@@ -33,5 +32,5 @@ settingBtn = Elem(rid='me_top_bar_setting_iv', desc='设置按钮') | ||
| class SettingPage(kuto.Page): | ||
| class SettingPage(Page): | ||
| """设置页""" | ||
| title = Elem(rid='tv_actionbar_title', desc='设置页标题') | ||
| agreementText = Elem(rid='agreement_tv_2', desc='服务协议链接') |
@@ -5,5 +5,3 @@ """ | ||
| """ | ||
| import kuto | ||
| from kuto.android import Elem | ||
| from kuto.image import ImageElem | ||
| from kuto.android import Page, Elem | ||
@@ -15,8 +13,8 @@ """ | ||
| class ImagePage(kuto.Page): | ||
| class ImagePage(Page): | ||
| searchEntry = Elem(rid="com.tencent.mm:id/j5t", desc='搜索框入口') | ||
| searchInput = Elem(rid="com.tencent.mm:id/cd7", desc='搜索框') | ||
| searchResult = Elem(rid="com.tencent.mm:id/kpm", desc="搜索结果") | ||
| schoolEntry = ImageElem(image="../static/校园场馆.png", desc='校园场馆入口') | ||
| schoolEntry = Elem(image="../static/校园场馆.png", desc='校园场馆入口') | ||
@@ -6,4 +6,3 @@ """ | ||
| """ | ||
| import kuto | ||
| from kuto.ios import Elem | ||
| from kuto.ios import Page, Elem | ||
@@ -23,3 +22,3 @@ | ||
| class IndexPage(kuto.Page): | ||
| class IndexPage(Page): | ||
| """首页""" | ||
@@ -30,3 +29,3 @@ adBtn = Elem(label='close white big', desc='广告关闭按钮') | ||
| class MyPage(kuto.Page): | ||
| class MyPage(Page): | ||
| """我的页""" | ||
@@ -36,4 +35,4 @@ settingBtn = Elem(label='settings navi', desc='设置按钮') | ||
| class SettingPage(kuto.Page): | ||
| class SettingPage(Page): | ||
| """设置页""" | ||
| about = Elem(text="关于企知道", desc='关于企知道文本') |
@@ -5,7 +5,6 @@ """ | ||
| """ | ||
| import kuto | ||
| from kuto.mac import ImageElem | ||
| from kuto.mac import Page, ImageElem | ||
| class MacPage(kuto.Page): | ||
| class MacPage(Page): | ||
| """根据图片定位,建议使用系统自带截图(shift+command+4)""" | ||
@@ -12,0 +11,0 @@ |
@@ -5,5 +5,3 @@ """ | ||
| """ | ||
| import kuto | ||
| from kuto.ios import Elem | ||
| from kuto.ocr import OCRElem | ||
| from kuto.ios import Page, Elem | ||
@@ -15,7 +13,7 @@ """ | ||
| class OcrPage(kuto.Page): | ||
| class OcrPage(Page): | ||
| searchBtn = Elem(text="搜索", className="XCUIElementTypeSearchField", desc='搜索框入口') | ||
| searchInput = Elem(className="XCUIElementTypeSearchField", desc='搜索框') | ||
| searchResult = Elem(xpath="//Table/Cell[2]", desc='搜索结果') | ||
| schoolEntry = OCRElem(text="校园场馆", pos=12, scale=3) | ||
| schoolEntry = Elem(ocr="校园场馆", pos=12, desc="校园场馆入口") | ||
@@ -5,4 +5,3 @@ """ | ||
| """ | ||
| import kuto | ||
| from kuto.web import Elem | ||
| from kuto.web import Page, Elem | ||
@@ -19,3 +18,3 @@ """ | ||
| class IndexPage(kuto.Page): | ||
| class IndexPage(Page): | ||
| """首页""" | ||
@@ -26,3 +25,3 @@ loginBtn = Elem(text='登录/注册', desc='登录/注册按钮') | ||
| class LoginPage(kuto.Page): | ||
| class LoginPage(Page): | ||
| """登录页""" | ||
@@ -29,0 +28,0 @@ pwdLoginTab = Elem(text='帐号密码登录', desc='账号密码登录tab') |
@@ -5,7 +5,6 @@ """ | ||
| """ | ||
| import kuto | ||
| from kuto.win import Elem | ||
| from kuto.win import Page, Elem | ||
| class WinPage(kuto.Page): | ||
| class WinPage(Page): | ||
| num_3 = Elem(image='../static/calculator_3_win.png', desc="数字3") | ||
@@ -12,0 +11,0 @@ x = Elem(image='../static/calculator_x_win.png', desc="乘以号") |
+11
-15
@@ -5,20 +5,16 @@ """ | ||
| """ | ||
| from kuto import AndroidDriver, AdrElem | ||
| from kuto.android import Driver, Elem | ||
| driver = AndroidDriver(device_id='UJK0220521066836', | ||
| pkg_name='com.qizhidao.clientapp') | ||
| driver = Driver(device_id='UJK0220521066836', pkg_name='com.qizhidao.clientapp') | ||
| driver.start_app() | ||
| AdrElem(driver, rid='com.qizhidao.clientapp:id/btn_login').click() | ||
| AdrElem(driver, text='其他手机号码登录').click() | ||
| AdrElem(driver, text='帐号密码登录').click() | ||
| AdrElem(driver, rid='com.qizhidao.clientapp:id/phone_et').input_exists("13652435335") | ||
| AdrElem(driver, rid='com.qizhidao.clientapp:id/clear_edit_text').input_pwd("wz123456@QZD") | ||
| AdrElem(driver, rid='com.qizhidao.clientapp:id/pwd_check_box_layout').click_exists() | ||
| AdrElem(driver, text='登录').click() | ||
| AdrElem(driver, rid='com.qizhidao.clientapp:id/common_list_rv').click_exists() | ||
| AdrElem(driver, rid='com.qizhidao.clientapp:id/skip_btn').click_exists() | ||
| Elem(driver, rid='com.qizhidao.clientapp:id/btn_login').click() | ||
| Elem(driver, text='其他手机号码登录').click() | ||
| Elem(driver, text='帐号密码登录').click() | ||
| Elem(driver, rid='com.qizhidao.clientapp:id/phone_et').input_exists("13652435335") | ||
| Elem(driver, rid='com.qizhidao.clientapp:id/clear_edit_text').input_pwd("wz123456@QZD") | ||
| Elem(driver, rid='com.qizhidao.clientapp:id/pwd_check_box_layout').click_exists() | ||
| Elem(driver, text='登录').click() | ||
| Elem(driver, rid='com.qizhidao.clientapp:id/common_list_rv').click_exists() | ||
| Elem(driver, rid='com.qizhidao.clientapp:id/skip_btn').click_exists() | ||
| driver.assert_act('.main.HomeActivity') | ||
| driver.stop_app() | ||
| import kuto | ||
| from kuto.android import Case | ||
| from page.adr_page import HomePage, \ | ||
@@ -32,3 +32,3 @@ MyPage, SettingPage | ||
| kuto.main( | ||
| devices=["85WKMBHQFEK76T8D"], | ||
| devices=["UJK0220521066836"], | ||
| pkg_name='com.qizhidao.clientapp', | ||
@@ -35,0 +35,0 @@ ) |
@@ -7,4 +7,4 @@ """ | ||
| import kuto | ||
| from kuto.android import Case | ||
| from page.image_page import ImagePage | ||
@@ -11,0 +11,0 @@ |
| import kuto | ||
| from kuto.ios import Case | ||
| from page.ios_page import IndexPage, MyPage, SettingPage | ||
@@ -5,0 +5,0 @@ |
@@ -6,4 +6,4 @@ """ | ||
| import kuto | ||
| from kuto.mac import Case | ||
| from page.mac_page import MacPage | ||
@@ -10,0 +10,0 @@ |
@@ -6,4 +6,4 @@ """ | ||
| import kuto | ||
| from kuto.ios import Case | ||
| from page.ocr_page import OcrPage | ||
@@ -10,0 +10,0 @@ |
| import kuto | ||
| from kuto import logger | ||
@@ -3,0 +4,0 @@ |
@@ -6,4 +6,4 @@ """ | ||
| import kuto | ||
| from kuto.web import Case | ||
| from pub import Pub | ||
@@ -10,0 +10,0 @@ |
@@ -6,4 +6,4 @@ """ | ||
| import kuto | ||
| from kuto.win import Case | ||
| from page.win_page import WinPage | ||
@@ -10,0 +10,0 @@ |
| Metadata-Version: 2.1 | ||
| Name: kuto | ||
| Version: 0.0.66 | ||
| Version: 0.0.67 | ||
| Summary: 全平台自动化测试框架 | ||
@@ -16,8 +16,6 @@ Home-page: https://gitee.com/bluepang2021/kuto | ||
| Requires-Python: >=3.9 | ||
| Provides-Extra: web | ||
| Provides-Extra: pc | ||
| Provides-Extra: app | ||
| Provides-Extra: excel | ||
| Provides-Extra: encrypt | ||
| Provides-Extra: android | ||
| Provides-Extra: ios | ||
| Provides-Extra: web | ||
| Provides-Extra: pc | ||
| Provides-Extra: ocr |
@@ -11,9 +11,12 @@ requests-toolbelt==0.10.1 | ||
| urllib3==1.26.15 | ||
| filelock==3.12.2 | ||
| psutil==5.9.5 | ||
| PyYAML~=6.0 | ||
| [android] | ||
| [app] | ||
| uiautomator2==2.16.23 | ||
| tidevice==0.6.1 | ||
| facebook-wda==1.4.6 | ||
| opencv-python==4.6.0.66 | ||
| easyocr==1.7.0 | ||
| Pillow==9.5.0 | ||
| filelock==3.12.2 | ||
@@ -28,11 +31,2 @@ [encrypt] | ||
| [ios] | ||
| tidevice==0.6.1 | ||
| facebook-wda==1.4.6 | ||
| opencv-python==4.6.0.66 | ||
| [ocr] | ||
| easyocr==1.7.0 | ||
| Pillow==9.5.0 | ||
| [pc] | ||
@@ -44,2 +38,1 @@ PyAutoGUI==0.9.54 | ||
| playwright==1.33.0 | ||
| opencv-python==4.6.0.66 |
+1
-1
@@ -13,3 +13,3 @@ from allure import * | ||
| __version__ = "0.0.66" | ||
| __version__ = "0.0.67" | ||
| __description__ = "全平台自动化测试框架" |
| from kuto.android.element import Elem | ||
| from kuto.android.driver import Driver | ||
| from kuto.android.case import Case | ||
| from kuto.page import Page | ||
| from kuto.android.common import get_connected | ||
@@ -9,3 +11,5 @@ | ||
| "Driver", | ||
| "Case" | ||
| "Case", | ||
| "Page", | ||
| "get_connected" | ||
| ] |
@@ -12,2 +12,3 @@ import os | ||
| from kuto.utils.exceptions import KError | ||
| from kuto.android.common import get_connected | ||
@@ -25,2 +26,5 @@ | ||
| raise KError("设备id不能为空") | ||
| else: | ||
| if self.device_id not in get_connected(): | ||
| raise KeyError("设备未连接") | ||
@@ -27,0 +31,0 @@ self.d = u2.connect(self.device_id) |
+36
-14
@@ -11,2 +11,4 @@ import typing | ||
| draw_red_by_coordinate | ||
| from kuto.image.element import ImageElem | ||
| from kuto.ocr.element import OCRElem | ||
@@ -27,2 +29,6 @@ | ||
| xpath: str = None, | ||
| image: str = None, | ||
| ocr: str = None, | ||
| pos: int = None, | ||
| grade: float = 0.8, | ||
| index: int = None, | ||
@@ -63,2 +69,6 @@ debug: bool = False): | ||
| self._debug = debug | ||
| self._image = image | ||
| self._ocr = ocr | ||
| self._pos = pos | ||
| self._grade = grade | ||
@@ -154,12 +164,18 @@ def __get__(self, instance, owner): | ||
| logger.info(f"检查 {self._desc} 是否存在") | ||
| result = False | ||
| try: | ||
| _element = self.find(timeout=timeout) | ||
| result = True | ||
| except Exception as e: | ||
| logger.debug(str(e)) | ||
| if self._image is not None: | ||
| return ImageElem(self._driver, file=self._image, desc=self._desc).exists(timeout=timeout) | ||
| elif self._ocr is not None: | ||
| return OCRElem(self._driver, text=self._ocr, pos=self._pos, grade=self._grade, scale=self._driver.d.scale)\ | ||
| .exists(timeout=timeout) | ||
| else: | ||
| result = False | ||
| finally: | ||
| logger.info(result) | ||
| return result | ||
| try: | ||
| _element = self.find(timeout=timeout) | ||
| result = True | ||
| except Exception as e: | ||
| logger.debug(str(e)) | ||
| result = False | ||
| finally: | ||
| logger.info(result) | ||
| return result | ||
@@ -179,7 +195,13 @@ @staticmethod | ||
| logger.info(f"点击 {self._desc}") | ||
| element = self.find(timeout=timeout, watch=watch) | ||
| # 这种方式经常点击不成功,感觉是页面刷新有影响 | ||
| # element.click() | ||
| x, y = self._adapt_center(element) | ||
| self._driver.d.click(x, y) | ||
| if self._image is not None: | ||
| return ImageElem(self._driver, file=self._image, desc=self._desc).click(timeout=timeout) | ||
| elif self._ocr is not None: | ||
| return OCRElem(self._driver, text=self._ocr, pos=self._pos, grade=self._grade, scale=self._driver.d.scale)\ | ||
| .click(timeout=timeout) | ||
| else: | ||
| element = self.find(timeout=timeout, watch=watch) | ||
| # 这种方式经常点击不成功,感觉是页面刷新有影响 | ||
| # element.click() | ||
| x, y = self._adapt_center(element) | ||
| self._driver.d.click(x, y) | ||
@@ -186,0 +208,0 @@ def click_exists(self, timeout=3, watch=None): |
| import time | ||
| # from kuto.ios.driver import Driver | ||
| from kuto.utils.exceptions import KError | ||
@@ -16,4 +15,6 @@ from kuto.utils.log import logger | ||
| desc: str = None, | ||
| image: str = None, | ||
| file: str = None, | ||
| scale: int = None, | ||
| grade=0.9, | ||
| gauss_num=111, | ||
| debug: bool = False): | ||
@@ -25,5 +26,7 @@ self.driver = driver | ||
| self._desc = desc | ||
| self.target_image = image | ||
| self.target_image = file | ||
| self._debug = debug | ||
| self._scale = scale | ||
| self._grade = grade | ||
| self._gauss_num = gauss_num | ||
@@ -37,3 +40,3 @@ def __get__(self, instance, owner): | ||
| def exists(self, retry=3, timeout=3, grade=0.9, gauss_num=111): | ||
| def exists(self, retry=3, timeout=3): | ||
| logger.info(f'图像识别判断: {self._desc} 是否存在') | ||
@@ -44,3 +47,3 @@ time.sleep(3) | ||
| source_image = self.driver.screenshot(self._desc + f"_第{i+1}次识别") | ||
| res = ImageDiscern(self.target_image, source_image, grade, gauss_num).get_coordinate() | ||
| res = ImageDiscern(self.target_image, source_image, self._grade, self._gauss_num).get_coordinate() | ||
| logger.debug(res) | ||
@@ -54,3 +57,3 @@ if isinstance(res, tuple): | ||
| def click(self, retry=3, timeout=3, grade=0.9, gauss_num=111): | ||
| def click(self, retry=3, timeout=3): | ||
| logger.info(f'图像识别点击图片: {self._desc}') | ||
@@ -61,3 +64,3 @@ time.sleep(3) | ||
| source_image = self.driver.screenshot(self._desc) | ||
| res = ImageDiscern(self.target_image, source_image, grade, gauss_num).get_coordinate() | ||
| res = ImageDiscern(self.target_image, source_image, self._grade, self._gauss_num).get_coordinate() | ||
| if isinstance(res, tuple): | ||
@@ -64,0 +67,0 @@ logger.info(f'识别坐标为: {res}') |
| from kuto.ios.case import Case | ||
| from kuto.ios.element import Elem | ||
| from kuto.ios.driver import Driver | ||
| from kuto.page import Page | ||
| from kuto.ios.common import get_connected | ||
| __all__ = ["Case", "Elem", "Driver"] | ||
| __all__ = ["Case", "Elem", "Driver", "Page", "get_connected"] | ||
@@ -9,3 +9,3 @@ import shutil | ||
| from kuto.utils.common import screenshot_util | ||
| from kuto.ios.common import TideviceUtil | ||
| from kuto.ios.common import TideviceUtil, get_connected | ||
@@ -44,2 +44,4 @@ | ||
| else: | ||
| if self.device_id not in get_connected(): | ||
| raise KError("设备未连接") | ||
| self.port = self.device_id.split("-")[0][-4:] | ||
@@ -46,0 +48,0 @@ self.wda_url = f"http://localhost:{self.port}" |
+38
-16
@@ -6,4 +6,7 @@ import time | ||
| from kuto.ios.driver import Driver | ||
| from kuto.utils.common import calculate_time, draw_red_by_rect | ||
| from kuto.utils.common import calculate_time, \ | ||
| draw_red_by_rect | ||
| from kuto.utils.exceptions import KError | ||
| from kuto.image.element import ImageElem | ||
| from kuto.ocr.element import OCRElem | ||
@@ -31,2 +34,6 @@ | ||
| xpath: str = None, | ||
| image: str = None, | ||
| ocr: str = None, | ||
| pos: int = None, | ||
| grade: float = 0.8, | ||
| index: int = None, | ||
@@ -74,2 +81,6 @@ debug: bool = False): | ||
| self._debug = debug | ||
| self._image = image | ||
| self._ocr = ocr | ||
| self._pos = pos | ||
| self._grade = grade | ||
@@ -173,6 +184,5 @@ def __get__(self, instance, owner): | ||
| self._watch(watch) | ||
| return _find() | ||
| else: | ||
| return _find() | ||
| return _find() | ||
| @property | ||
@@ -193,11 +203,17 @@ def text(self): | ||
| logger.info(f"检查 {self._desc} 是否存在") | ||
| result = False | ||
| try: | ||
| _element = self.find(timeout=timeout) | ||
| result = True | ||
| except: | ||
| if self._image is not None: | ||
| return ImageElem(self._driver, file=self._image, desc=self._desc).exists(timeout=timeout) | ||
| elif self._ocr is not None: | ||
| return OCRElem(self._driver, text=self._ocr, pos=self._pos, grade=self._grade, scale=self._driver.d.scale)\ | ||
| .exists(timeout=timeout) | ||
| else: | ||
| result = False | ||
| finally: | ||
| logger.info(result) | ||
| return result | ||
| try: | ||
| _element = self.find(timeout=timeout) | ||
| result = True | ||
| except: | ||
| result = False | ||
| finally: | ||
| logger.info(result) | ||
| return result | ||
@@ -223,6 +239,12 @@ def _adapt_center(self, timeout=5, watch=None): | ||
| logger.info(f'点击 {self._desc}') | ||
| x, y = self._adapt_center(timeout=timeout, watch=watch) | ||
| self._driver.d.appium_settings({"snapshotMaxDepth": 0}) | ||
| self._driver.d.tap(x, y) | ||
| self._driver.d.appium_settings({"snapshotMaxDepth": 50}) | ||
| if self._image is not None: | ||
| ImageElem(self._driver, file=self._image, desc=self._desc).click(timeout=timeout) | ||
| elif self._ocr is not None: | ||
| OCRElem(self._driver, text=self._ocr, pos=self._pos, grade=self._grade, scale=self._driver.d.scale)\ | ||
| .click(timeout=timeout) | ||
| else: | ||
| x, y = self._adapt_center(timeout=timeout, watch=watch) | ||
| self._driver.d.appium_settings({"snapshotMaxDepth": 0}) | ||
| self._driver.d.tap(x, y) | ||
| self._driver.d.appium_settings({"snapshotMaxDepth": 50}) | ||
@@ -229,0 +251,0 @@ def click_exists(self, timeout=3): |
@@ -8,4 +8,5 @@ """ | ||
| from kuto.mac.case import Case | ||
| from kuto.page import Page | ||
| __all__ = ["Case", "Driver", "CoorElem", "ImageElem"] | ||
| __all__ = ["Case", "Driver", "CoorElem", "ImageElem", "Page"] |
| import time | ||
| # from kuto.ios.driver import Driver | ||
| from kuto.utils.log import logger | ||
@@ -5,0 +4,0 @@ from kuto.ocr.driver import OCRDiscern |
| from kuto.web.driver import Driver | ||
| from kuto.web.element import Elem | ||
| from kuto.web.case import Case | ||
| from kuto.page import Page | ||
| __all__ = ["Case", "Driver", "Elem"] | ||
| __all__ = ["Case", "Driver", "Elem", "Page"] |
@@ -5,2 +5,4 @@ """ | ||
| """ | ||
| import time | ||
| from playwright.sync_api import expect | ||
@@ -7,0 +9,0 @@ |
@@ -8,1 +8,5 @@ """ | ||
| from kuto.win.element import Elem | ||
| from kuto.page import Page | ||
| __all__ = ["Case", "Driver", "Elem", "Page"] |
+4
-6
| Metadata-Version: 2.1 | ||
| Name: kuto | ||
| Version: 0.0.66 | ||
| Version: 0.0.67 | ||
| Summary: 全平台自动化测试框架 | ||
@@ -16,8 +16,6 @@ Home-page: https://gitee.com/bluepang2021/kuto | ||
| Requires-Python: >=3.9 | ||
| Provides-Extra: web | ||
| Provides-Extra: pc | ||
| Provides-Extra: app | ||
| Provides-Extra: excel | ||
| Provides-Extra: encrypt | ||
| Provides-Extra: android | ||
| Provides-Extra: ios | ||
| Provides-Extra: web | ||
| Provides-Extra: pc | ||
| Provides-Extra: ocr |
+4
-7
@@ -40,14 +40,11 @@ # -*- coding: utf-8 -*- | ||
| 'urllib3==1.26.15', | ||
| 'filelock==3.12.2', | ||
| 'psutil==5.9.5', | ||
| 'PyYAML~=6.0' | ||
| ], | ||
| extras_require={ | ||
| "web": ['playwright==1.33.0'], | ||
| "pc": ['PyAutoGUI==0.9.54', 'opencv-python==4.6.0.66'], | ||
| "app": ['uiautomator2==2.16.23', 'tidevice==0.6.1', 'facebook-wda==1.4.6', | ||
| 'opencv-python==4.6.0.66', 'easyocr==1.7.0', 'Pillow==9.5.0', 'filelock==3.12.2'], | ||
| "excel": ['pandas==1.3.4', 'openpyxl==3.0.9', 'XlsxWriter==3.0.2'], | ||
| "encrypt": ["pycryptodome==3.14.1"], | ||
| "android": ['uiautomator2==2.16.23', 'opencv-python==4.6.0.66'], | ||
| "ios": ['tidevice==0.6.1', 'facebook-wda==1.4.6', 'opencv-python==4.6.0.66'], | ||
| "web": ['playwright==1.33.0', 'opencv-python==4.6.0.66'], | ||
| "pc": ['PyAutoGUI==0.9.54', 'opencv-python==4.6.0.66'], | ||
| "ocr": ['easyocr==1.7.0', 'Pillow==9.5.0'] | ||
| }, | ||
@@ -54,0 +51,0 @@ |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
223283
1.02%5369
0.92%