0


【python】windows客户端的ui自动化框架搭建及使用(winappdriver)

0.环境准备

  1. 安装jdk(8以上版本)及其环境配置
  2. 安装python3.10.4及其对应的三方包
  3. 安装winappdriver,下载地址:https://github.com/microsoft/WinAppDriver/releases/tag/v1.2.1
  4. windows开启开发者模式,本地开启服务:https://jingyan.baidu.com/article/91f5db1bfc57df5d7e05e31d.html

1.思路

整体思路:
1、封装appdriver服务、客户端启动关闭
2、封装鼠标基础行为 bat
3、封装元素定位基础行为 baseFunc
4、conftest中调用appdriver服务、客户端启动关闭,将driver暴露
5、调用

2.初试用

# -*- encoding: utf-8 -*-""""
@File: driver_win.py
@Author: cyl
@Desc: 对winappdriver服务、app的开启关闭进行封装
"""import os
import time
import psutil
import platform
from selenium import webdriver
from settings import op_dir

WinAppDriver:str="WinAppDriver.exe"
MyAppEXE:str="xxx.exe"# noinspection PyMethodMayBeStaticclassWinModelDriver:def__init__(self, host='localhost', port=4723)->None:
        self.open_app_driver()# 配置信息
        self.desired_caps:dict={'platform_fame': platform.system(),# 平台名: 'Linux', 'Windows' or 'Java''deviceName':'WindowsPC',# 系统'app': op_dir,# 应用程序绝对路径'pageLoadStrategy':'none',# 加载策略'disable-popup-blocking':True,# 禁用弹窗}
        self.host = host
        self.port = port
        self.driver =Nonedefopen_app_driver(self)->None:"""启用winappdriver服务"""
        result = os.system(r'start "" /d "C:\Program Files (x86)\Windows Application Driver\"  "WinAppDriver.exe"')if result ==1:raise"开启服务失败, 确保启动WinAppDriver服务的地址正确!"# noinspection HttpUrlsUsagedefopen_platform(self)-> webdriver:"""打开"""try:
            self.driver = webdriver.Remote('http://{}:{}'.format(self.host, self.port), self.desired_caps)except Exception as e:raise AssertionError(e)# self.driver.implicitly_wait(3)# self.driver.maximize_window()# print("全部元素-> ", self.driver.page_source)return self.driver

    defclose_platform(self)->None:"""关闭"""
        self.driver.close()
        self.driver.quit()# 关闭所有客户端进程
        time.sleep(1.5)for proc in psutil.process_iter():
            p_info = proc.as_dict(attrs=['pid','name'])if p_info.get("name")== MyAppEXE:
                _kill ='taskkill -f -pid %s'% p_info.get("pid")
                os.popen(_kill)
# -*- encoding: utf-8 -*-""""
@File: driver_impl.py.py
@Author: cyl
@Desc: 定义公共的driver实例
"""classDriverImpl:def__init__(self):
        self.driver =None
        self.module =""# 公共的driver类实例
driverImpl: DriverImpl = DriverImpl()
# -*- encoding: utf-8 -*-"""
@File: base.py
@Author: cyl
@Desc: 鼠标事件pyautogui库的一些基础行为
"""import pyautogui
from typing import Any
from pyautogui import Point

# noinspection PyMethodMayBeStatic,PyPep8NamingclassBaseAutoGui:"""pyautogui基础封装"""defposition(self)-> Point:return pyautogui.position()defsize(self)->tuple:"""获取屏幕的分辨率(高度、宽度)"""
        wight, height = pyautogui.size()return wight, height

    defonScreen(self, x: Any, y: Any)->bool:"""判断坐标是否在屏幕上"""
        res:bool= pyautogui.onScreen(x, y)return res

    defkeyboard_keys(self)->list:"""返回所有支持的按键名称"""return pyautogui.KEYBOARD_KEYS
    
    defclick(
            self,
            x:int|float,
            y:int|float,
            duration:int|float=0.2,
            _type:str="single",**kwargs
    ):"""点击
        Args:
            x (int | float): x轴坐标点
            y (int | float): y轴坐标点
            duration (int | float, optional): 周期
            _type (str, optional): single单击左键 right右键 double双击左键 three三击右键
        """match _type:case"single":
                pyautogui.click(x, y, duration=duration,**kwargs)case"right":
                pyautogui.click(button="right",**kwargs)case"double":
                pyautogui.click(clicks=2,**kwargs)case"three":
                pyautogui.click(button='right', clicks=2, interval=0.25,**kwargs)case_:
                pyautogui.click(x, y, duration=duration,**kwargs)return self

    defdoubleClick(self, x:int|float, y:int|float, duration:int|float=0.5,**kwargs):"""双击"""
        pyautogui.doubleClick(x, y, duration=duration,**kwargs)return self

    deftripleClicks(self, x:int=0, y:int=0,**kwargs):"""当前位置左击三下
        Args:
            x (int, optional): 指定位置x轴坐标点
            y (int, optional): 指定位置y轴坐标点
        """
        pyautogui.tripleClick(x=x, y=y,**kwargs)return self

    defpress(self, keys:str):"""按键
        Args:
            keys (str): 键名, eg: enter, esc, space
        """if keys in self.keyboard_keys():
            pyautogui.press(keys)else:raise"当前按键不在指定键程内!"return self

3.结合pytest

# -*- encoding: utf-8 -*-"""
@File: conftest.py
@Author: cyl
@Desc: ...
"""import pytest
from common.driver_impl import driverImpl
from common.driver_win import WinModelDriver, webdriver

@pytest.fixture(scope="function", autouse=True)defdriver():
    wl: WinModelDriver = WinModelDriver()
    test_driver: webdriver = wl.open_platform()
    driverImpl.driver = test_driver
    logger.info("app启动~~~!")yield test_driver
    
    wl.close_platform()
    driverImpl.driver =None
    logger.info("app关闭~~~!")
# -*- encoding: utf-8 -*-"""
@File: base_func.py
@Author: cyl
@Desc: driver以及基础行为封装
"""import time
import win32api
import win32con
from utils.my_types import T, List
from common.driver_impl import driverImpl
from common.m_eles import getModelElement
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec

# noinspection PyMethodMayBeStaticclassBaseModelFunc:"""driver以及基础行为封装"""defelement_wait(self, driver=None, by_type:str="xpath", formula:str="", timeout:int=3)-> T:"""
        显示等待, 默认xpath
        :param driver: Windows driver
        :param by_type: _id xpath name className linkTest tagName partialLinkText css
        :param formula: elements.key
        :param timeout: wait time setting, default 3s
        """# 获取xpath(根据自己实际业务封装,如果没有可以直接将xptah作为形参传入)
        xpath:str|int= getModelElement(formula)
        driver = driverImpl.driver if driver isNoneelse...
        handles:list= driver.window_handles
        ifnot handles:returniflen(handles)>=1:
            driver.switch_to.window(handles[0])match by_type:case"_id":
                ele = WebDriverWait(driver, timeout,0.5).until(ec.presence_of_element_located((By.ID, xpath)))case"xpath":
                ele = WebDriverWait(driver, timeout,0.5).until(ec.presence_of_element_located((By.XPATH, xpath)))case"name":
                ele = WebDriverWait(driver, timeout,0.5).until(ec.presence_of_element_located((By.NAME, xpath)))case"className":
                ele = WebDriverWait(driver, timeout,0.5).until(ec.presence_of_element_located((By.CLASS_NAME, xpath)))case"linkTest":
                ele = WebDriverWait(driver, timeout,0.5).until(ec.presence_of_element_located((By.LINK_TEXT, xpath)))case"tagName":
                ele = WebDriverWait(driver, timeout,0.5).until(ec.presence_of_element_located((By.TAG_NAME, xpath)))case"partialLinkText":
                ele = WebDriverWait(driver, timeout,0.5).until(ec.presence_of_element_located((By.PARTIAL_LINK_TEXT, xpath)))case"css":
                ele = WebDriverWait(driver, timeout,0.5).until(ec.presence_of_element_located((By.CSS_SELECTOR, xpath)))case_:
                ele = WebDriverWait(driver, timeout,0.5).until(ec.presence_of_element_located((By.XPATH, xpath)))
        driver.switch_to.window(handles[-1])return ele

baseFunc: BaseModelFunc = BaseModelFunc()
# -*- encoding: utf-8 -*-"""
@File: m_eles_setting.py
@Author: cyl
@Desc: 实际应用中的方法调用
"""from settings import app_cof
from utils.base_gui import bat
from utils.base_func import baseFunc

# noinspection PyMethodMayBeStaticclassModuleElesSetting:"""设置"""defapply_and_determine(
            self,
            x_point:tuple=(1763,852),
            y_point:tuple=(1627,855),
            is_point:bool= app_cof.isPoint):"""
        设置-应用并确定
        :param x_point: 应用
        :param y_point: 确认
        :param is_point: 是否使用坐标点
        """if is_point:
            bat.click(*x_point).click(*y_point)else:
            baseFunc.element_wait(formula="SETUP_APPLICATION").click()
            baseFunc.element_wait(formula="POLYLINE_OK").click()
标签: python ui 自动化

本文转载自: https://blog.csdn.net/test_cyl/article/details/129044450
版权归原作者 三人行ylc 所有, 如有侵权,请联系我们删除。

“【python】windows客户端的ui自动化框架搭建及使用(winappdriver)”的评论:

还没有评论