uiautomator2 App自动化测试框架【三】

2023-12-22 02:40

本文主要是介绍uiautomator2 App自动化测试框架【三】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文为博主原创,未经授权,严禁转载及使用。
本文链接:https://blog.csdn.net/zyooooxie/article/details/124176686

之前分享过 使用uiautomator2 来搞APP自动化,分别是 https://blog.csdn.net/zyooooxie/article/details/124415385、 https://blog.csdn.net/zyooooxie/article/details/123916767,现在把 剩下的做个分享。

【实际这篇博客推迟发布N个月】

个人博客:https://blog.csdn.net/zyooooxie

【以下所有内容仅为个人项目经历,如有不同,纯属正常】

本期内容

本期主要是说 测试用例.py、元素定位.py、执行结果。

代码

下面是 按着 pageElements + testCases 来讲述的。

(代码有删改)

@filename: page_membership_interests_1.py

"""
@blog: https://blog.csdn.net/zyooooxie
"""class PageMembershipInterests1(object):"""大陆APP"""SHAOHOU = dict(text="稍后")GENGXIN1 = dict(resourceId="android:id/button1")QUXIAO = dict(description="取消,按钮")QUXIAO2 = '//*[@resource-id="zyooooxie:id/rnRootLayout"]/android.view.ViewGroup[2]/android.view.ViewGroup[2]/android.view.ViewGroup[2]'WO = dict(text="我")TANNENGLIANG = dict(text="")HUIYUANZHONGXIN = dict(text="会员中心")TANCHUANG = dict(text="close")HUIYUANZHONGXIN_BIAOTI = dict(descriptionContains="标题")HUITYANQUANYI = '//*[@resource-id="root"]/android.view.View[1]/android.view.View[1]'JIFENSHANGCHENG = dict(text="积分商城")WODEZHUANGXIANGTEQUAN = dict(text="我的专享特权")CHENGZHANGTIXI = dict(textStartsWith="成长体")ZANKAI = dict(text="展开")BAOJIAYOUHUI = dict(text="")SHOUJIANDUIJIANG = dict(text="")QUANYIJIESHAO = dict(text="权益介绍")QUANYINEIRONG = dict(text="权益内容")LIJIQIANWANG = dict(text="立即前往")LINGQUYOUHUIQUAN = dict(text="领取优惠券")GONGXILINGQUCHENGGONG = dict(textStartsWith='恭喜领取成')TOAST_WUCILIBAO = dict(text="无此礼包或库存不足")TOAST_HUODONGBUCUNZAI = dict(text="活动不存在")if __name__ == '__main__':pass

@filename: test_membership_interests_1.py

"""
@blog: https://blog.csdn.net/zyooooxie
"""import pytest
import allure
import os
import time
import cv2
import random
from pypinyin import lazy_pinyin
from uiautomator2 import Direction
from uiautomator2 import Devicefrom membership_interests_app_autotest.page_membership_interests_1 import PageMembershipInterests1
from membership_interests_app_autotest.common_function import my_element, my_assert, my_assert_toast
from membership_interests_app_autotest.common_function import kill_button, screenshot_decorator, get_user_id
from membership_interests_app_autotest.common_variable import dl, common_serial_number, dl_account
from membership_interests_app_autotest.common_variable import diff_pictures_path, now_pictures_path
from membership_interests_app_autotest.common_variable import pictures_path
from membership_interests_app_autotest.yy_function import crop_images, pic_diff
from membership_interests_app_autotest.common_mysql import exe_sql
from membership_interests_app_autotest.user_log import Logprint(dl_account, 'test_membership_interests_1.py')def delete_award_packet_records():# 做数据清理user_id = get_user_id(mobile=dl_account)sql1 = """DELETE FROM table_aprs WHERE USER_ID = '{}';""".format(user_id)sql2 = """DELETE FROM table_aprsd WHERE USER_ID = '{}';""".format(user_id)for s in [sql1, sql2]:exe_sql(sql=s, db_name='zyooooxie_db')# @pytest.mark.skip
@allure.feature('大陆APP')
@pytest.mark.parametrize('device_dl', dl,indirect=True)  # dl传给 device(fixture): indirect=True 表示将参数'before_after'当做一个函数去执行(即参数名要和定义的fixture的函数名一致),而不是一个参数变量,并且将 dl 当做参数传递给该函数
class TestMembershipInterests1(PageMembershipInterests1):@staticmethoddef setup_method():delete_award_packet_records()@staticmethoddef teardown_method():# 为了方便 看日志时确定 报错属于哪条用例Log.info('---------')def in_member_center(self, device: Device):device.sleep(5)  # 有时不稳定【某个升级弹窗 会弹多次】,加个强制等待with allure.step('关闭升级弹窗'):kill_button(device, self.SHAOHOU)kill_button(device, self.QUXIAO)kill_button(device, self.QUXIAO2, wait_time=2)with allure.step('点击会员中心'):my_element(device, self.WO).click()my_assert(device, self.TANNENGLIANG, 'exists', True, 'is_', assert_time=5)my_element(device, self.HUIYUANZHONGXIN).click()with allure.step('关闭会员中心-弹窗'):kill_button(device, self.TANCHUANG, wait_time=8)my_assert(device, self.HUIYUANZHONGXIN_BIAOTI, 'exists', True, 'is_', assert_time=5)with allure.step('进入会员权益'):my_element(device, self.HUITYANQUANYI).click()with allure.step('断言方法 my_assert()'):my_assert(device, self.WODEZHUANGXIANGTEQUAN, 'exists', True, 'is_')my_assert(device, self.CHENGZHANGTIXI, 'get_text', '成长体系', 'eq')# my_assert(device, self.QUXIAO, no_exists=True)# @pytest.mark.skip@screenshot_decorator(connect_addr=common_serial_number)@allure.description('会员权益领取某个权益')@allure.title('会员中心-会员权益-领取')def test_1(self, device_dl: Device):self.in_member_center(device=device_dl)my_element(device_dl, self.ZANKAI).click()device_dl.swipe_ext(Direction.UP)with allure.step(''):my_element(device_dl, self.BAOJIAYOUHUI).click()with allure.step('领取优惠券、断言'):my_element(device_dl, self.LINGQUYOUHUIQUAN).click()# # 现在2是:礼包不足 -> (toast)无此礼包或库存不足# my_assert_toast(device_dl, '包或库', 'contains', element=self.LINGQUYOUHUIQUAN, toast_text='无此礼')# my_assert_toast(device_dl, '库存不足', 'contains', x=0.5, y=0.92, toast_text='无此礼')# 以前1是:活动已正常 -> 正常领取my_assert(device_dl, self.GONGXILINGQUCHENGGONG, 'exists', True, 'is_')# # 以前0是:礼包配置有问题  -> (toast)礼包不存在# # device_dl.double_click(x=0.5, y=0.92)  # 传百分比# # my_assert(device_dl, cls.TOAST_HUODONGBUCUNZAI, 'exists', True, 'is_')  # 断言toast存在,有时成功、有时失败# my_assert_toast(device_dl, '不存', 'contains', element=self.LINGQUYOUHUIQUAN, toast_text='礼包不')# my_assert_toast(device_dl, '存在', 'contains', x=0.5, y=0.92, toast_text='礼包不')if __name__ == '__main__':passpytest.main(['-s', '-v', '{}'.format(__file__)])# pytest.main(['-s', '-m', 'smoke', '-v', '{}'.format(__file__)])

----------------------------------------------

@filename: page_membership_interests_2.py

"""
@blog: https://blog.csdn.net/zyooooxie
"""class PageMembershipInterests2(object):"""香港APP"""vConsole = dict(resourceId="__vconsole")HUIYUAN = dict(text="會員")JIFENZONGSHULIANG = '//*[@resource-id="app"]/android.view.View[4]'HUIYUANDUXIANG = dict(text="會員獨享")JIFENGUIZE = dict(text="積分規則")ZHUYI = dict(text="注意")SHUNFENGDIANZITAOPIAOYOUHUI = dict(text="")QUQIANGGOU = dict(text='去搶購')SHUNFENGDIANZITAOPIAOXIANGQING = dict(text='')LIJIGOUMAI = dict(text="立即購買")WODELIPIN = dict(text="my-gift.9c48adc5")KUAIGUOQI = dict(text="快過期")XINLINGQU = dict(text="新領取")JIFENHUANLING = dict(text="積分換領")LIJIDUIHUAN = dict(text='立即兌換')LIPINXIANGQING = dict(text='禮品詳情')LIPINJIANJIE = dict(text="禮 品 簡 介")YINGYESHIJIAN = dict(textStartsWith='營業時間')QUEDINGDUIHUAN = dict(text="確定兌換")SUOXUJIFEN = dict(textStartsWith='所需積分')QUEDINGSHIYONG = dict(textStartsWith='確定使用')QUXIAO = dict(text="取消")QUEREN = dict(text="確認")DUIHUANCHENGGONG = dict(text="兌換成功")JIXUDUIHUAN = dict(text="繼續兌換")KEYONG = dict(textStartsWith='可用')JIAZAIGENGDUO = dict(text="加載更多")CHANPIN_QUQIANGGOU = '//*[@text="不要下架要跑APP自动化的谢谢"]/../android.view.View[5]'CHANPIN_1 = dict(text="不要下架要跑APP自动化的谢谢")TONGYI = dict(text="同意")GOUMAITONGYI = '//android.widget.CheckBox'SHUNFENGCHUZHIKA = dict(text="")QUERENFUKUAN = dict(text="確認付款")ZHIFUJINE = dict(text="支付金額")ZHIFUCHENGGONG = dict(text="支付成功")WANCHENG = dict(text="完成")LIJISHIYONG = dict(text="立即使用")TEST = dict(text="TEST")if __name__ == '__main__':pass

@filename: test_membership_interests_2.py

"""
@blog: https://blog.csdn.net/zyooooxie
"""import pytest
import allure
import random
import string
import re
import osfrom uiautomator2 import Device
from uiautomator2 import Directionfrom membership_interests_app_autotest.user_log import Logfrom membership_interests_app_autotest.common_variable import xg, common_serial_number, xg_account, request_headers
from membership_interests_app_autotest.common_variable import pictures_path
from membership_interests_app_autotest.common_function import screenshot_decorator, my_element, my_assert, get_user_id
from membership_interests_app_autotest.common_function import kill_button, send_request, join_url
from membership_interests_app_autotest.common_mysql import fetch_sql
from membership_interests_app_autotest.page_membership_interests_2 import PageMembershipInterests2print(xg_account, 'test_membership_interests_2.py')def update_user_point(available_points: str, login_account: str):"""修改用户的积分:param available_points::param login_account::return:"""add_point_url = '/zyooooxie/addPointOperate'if int(available_points) <= 100:user_id = get_user_id(login_account)if user_id:source = ''.join(random.sample(string.zy, 10))data = {'userId': user_id, 'mobile': login_account, 'pointValue': 100}send_request('post', url=join_url(add_point_url), json=data, headers=request_headers)Log.info('addPoint-100')return str(int(available_points) + 100)else:return available_points# @pytest.mark.skip
@allure.feature('香港APP')
@pytest.mark.parametrize('before_after_xgtw_module', xg, indirect=True)
@pytest.mark.parametrize('device_xgtw', xg, indirect=True)
class TestMembershipInterests2(PageMembershipInterests2):@staticmethoddef teardown_method():Log.info('---------')@pytest.mark.skip@screenshot_decorator(common_serial_number)@allure.description('积分规则')@allure.title('香港会员2')def test_2(self, device_xgtw: Device):my_element(device_xgtw, self.HUIYUAN).click()my_element(device_xgtw, self.JIFENGUIZE).click()my_assert(device_xgtw, self.ZHUYI, 'exists', True, 'is_')my_assert(device_xgtw, self.TEST, 'exists', True, 'is_')  # 不存在的元素@pytest.mark.smoke@screenshot_decorator(common_serial_number)@allure.description('积分换领-兑换礼品')@allure.title('香港会员10')def test_10(self, device_xgtw: Device):my_element(device_xgtw, self.HUIYUAN).click()my_assert(device_xgtw, self.HUIYUANDUXIANG, 'exists', True, 'is_')with allure.step('可用积分'):available_points = my_element(device_xgtw, self.JIFENZONGSHULIANG).get_text()Log.info(available_points)# 可用积分 有bug,所以每次都截个图img_name = ''.join(['available_points', '.png'])fn = os.path.join(pictures_path, img_name)device_xgtw.screenshot(filename=fn)allure.attach.file(source=fn, name=img_name, attachment_type=allure.attachment_type.PNG)available_points = update_user_point(available_points=available_points, login_account=xg_account)Log.info(available_points)with allure.step('某商品-立即兑换'):device_xgtw.swipe_ext(Direction.UP)device_xgtw.swipe_ext(Direction.UP)my_element(device_xgtw, self.LIJIDUIHUAN).click()my_assert(device_xgtw, self.LIPINXIANGQING, 'exists', True, 'is_')my_assert(device_xgtw, self.LIPINJIANJIE, 'exists', True, 'is_')with allure.step('vConsole'):my_element(device_xgtw, self.vConsole).drag_to(x=0.35, y=0.15, duration=0.5)with allure.step('某商品详情-获取point'):point0 = my_element(device_xgtw, self.SUOXUJIFEN).get_text()re_str = r'\d+'res0 = re.findall(re_str, point0)Log.info(res0)assert len(res0) == 1ke_yong_points1 = my_element(device_xgtw, self.KEYONG).get_text()ava1 = re.findall(re_str, ke_yong_points1)Log.info(ava1)assert len(ava1) == 1assert ava1[0].startswith(available_points) is Truewith allure.step('某商品兑换'):my_element(device_xgtw, self.LIJIDUIHUAN).click()kill_button(device_xgtw, self.YINGYESHIJIAN, wait_time=5)kill_button(device_xgtw, self.QUEDINGDUIHUAN, wait_time=5)my_assert(device_xgtw, self.QUXIAO, 'exists', True, 'is_')point1 = my_element(device_xgtw, self.QUEDINGSHIYONG).get_text()res1 = re.findall(re_str, point1)Log.info(res1)assert len(res1) == 1assert res1[0] == res0[0]with allure.step('某商品兑换-确认'):my_element(device_xgtw, self.QUEREN).click()my_assert(device_xgtw, self.DUIHUANCHENGGONG, 'exists', True, 'is_')my_assert(device_xgtw, self.JIXUDUIHUAN, 'exists', True, 'is_')device_xgtw.press('back')with allure.step('某商品兑换后-断言'):ke_yong_points2 = my_element(device_xgtw, self.KEYONG).get_text()ava2 = re.findall(re_str, ke_yong_points2)Log.info(ava2)assert len(ava2) == 1assert ava2[0] == str(int(available_points) - int(res1[0]))@pytest.mark.smoke@screenshot_decorator(common_serial_number)@allure.description('购买超值福利-特定产品')@allure.title('香港会员11')def test_11(self, device_xgtw: Device):user = get_user_id(xg_account)with allure.step('特定产品-获取购买记录'):sql = """SELECT  COUNT(order_code) FROM table_oo WHERE user_id = '{}' AND commodity_name = '不要下架要跑APP自动化的谢谢' ORDER BY order_time DESC;""".format(user)res = fetch_sql(sql, db_name='zyooooxie_db', fetch_mode='fetchone')Log.info(res)sql2 = """SELECT COUNT(id) FROM table_oppr WHERE user_id = '{}' AND pay_status = '1' ORDER BY create_tm DESC;""".format(user)res2 = fetch_sql(sql2, db_name='zyooooxie_db', fetch_mode='fetchone')Log.info(res2)my_element(device_xgtw, self.HUIYUAN).click()my_element(device_xgtw, self.WODELIPIN).drag_to(x=0.35, y=0.15, duration=0.5)device_xgtw.swipe_ext(Direction.UP)with allure.step('特定产品-购买、付款'):my_element(device_xgtw, self.JIAZAIGENGDUO).click()my_element(device_xgtw, self.CHANPIN_QUQIANGGOU).click()my_assert(device_xgtw, self.CHANPIN_1, 'exists', True, 'is_')my_assert(device_xgtw, self.TONGYI, 'exists', True, 'is_')my_element(device_xgtw, self.GOUMAITONGYI).click()my_element(device_xgtw, self.LIJIGOUMAI).click()my_assert(device_xgtw, self.SHUNFENGCHUZHIKA, 'exists', True, 'is_')# 確認付款 有时候不稳定my_element(device_xgtw, self.QUERENFUKUAN).click()kill_button(device_xgtw, self.QUERENFUKUAN, wait_time=2)with allure.step('特定产品-输入支付密码'):my_assert(device_xgtw, self.ZHIFUJINE, 'exists', True, 'is_')# 支付密码1234my_element(device_xgtw, dict(text="1")).click()my_element(device_xgtw, dict(text="2")).click()my_element(device_xgtw, dict(text="3")).click()my_element(device_xgtw, dict(text="4")).click()with allure.step('特定产品-支付完成'):my_assert(device_xgtw, self.ZHIFUCHENGGONG, 'exists', True, 'is_')my_element(device_xgtw, self.WANCHENG).click()with allure.step('特定产品-购买后断言'):sql3 = """SELECT  COUNT(order_code) FROM table_oo WHERE user_id = '{}' AND commodity_name = '不要下架要跑APP自动化的谢谢' ORDER BY order_time DESC;""".format(user)res3 = fetch_sql(sql3, db_name='zyooooxie_db', fetch_mode='fetchone')Log.info(res3)assert res3[0] == res[0] + 1sql4 = """SELECT COUNT(id) FROM table_oppr WHERE user_id = '{}' AND pay_status = '1' ORDER BY create_tm DESC;""".format(user)res4 = fetch_sql(sql4, db_name='zyooooxie_db', fetch_mode='fetchone')Log.info(res4)assert res4[0] == res2[0] + 1if __name__ == '__main__':pass

----------------------------------------------

@filename: page_membership_interests_3.py

"""
@blog: https://blog.csdn.net/zyooooxie
"""class PageMembershipInterests3(object):"""台湾APP"""HUIYUAN = dict(text="會員")LiJILINGQU_close = dict(text="U+e1ILO3mKM256VjE9oujfgGk5zsYyFvRKAAAAABJRU5ErkJggg==")WODEHUIYUAN = dict(text="我的會員")HUIYUANGUIZE = dict(text="會員規則")

@filename: test_membership_interests_3.py

"""
@blog: https://blog.csdn.net/zyooooxie
"""import allure
import pytestfrom uiautomator2 import Devicefrom membership_interests_app_autotest.user_log import Log
from membership_interests_app_autotest.common_variable import tw, common_serial_number, tw_account
from membership_interests_app_autotest.common_function import my_element, my_assert, screenshot_decorator, kill_button
from membership_interests_app_autotest.page_membership_interests_3 import PageMembershipInterests3print(tw_account, 'test_membership_interests_3.py')# @pytest.mark.skip
@allure.feature('台湾APP')
@pytest.mark.parametrize('before_after_xgtw_module', tw, indirect=True)
@pytest.mark.parametrize('device_xgtw', tw, indirect=True)
class TestMembershipInterests3(PageMembershipInterests3):@staticmethoddef teardown_method():Log.info('---------')@pytest.mark.smoke@screenshot_decorator(common_serial_number)@allure.description('会员中心页面')@allure.title('台湾会员1')def test_1(self, device_xgtw: Device):my_element(device_xgtw, self.HUIYUAN).click()kill_button(device_xgtw, self.LiJILINGQU_close, wait_time=5)my_assert(device_xgtw, self.WODEHUIYUAN, 'exists', True, 'is_')my_assert(device_xgtw, self.HUIYUANGUIZE, 'exists', True, 'is_')if __name__ == '__main__':passpytest.main(['-s', '-v', '{}'.format(__file__)])

----------------------------------------------

@filename: page_membership_interests_4.py

"""
@blog: https://blog.csdn.net/zyooooxie
"""import time
import random
import datetime
import jsonpathfrom membership_interests_app_autotest.user_log import Logfrom membership_interests_app_autotest.common_function import my_element, send_request, join_url, get_user_id
from membership_interests_app_autotest.common_mysql import fetch_sql
from membership_interests_app_autotest.common_variable import dl_account, request_headersclass PageMembershipInterests4(object):QINGSHURUSHOUJIHAO = '//*[@resource-id="root"]//android.widget.EditText[1]'HUOQUYANZHENGMA = dict(text="获取验证码")QINGSHURUYANZHENGMA = '//*[@text="请输入发送至手机的验证码"]/../android.view.View[2]'QINGSHURUYANZHENGMA2 = dict(text="请输入发送至手机的验证码")TONGYIBENTIAOKUAN = dict(text="同意本条款,下次不再提醒")DENGLU = dict(text="登录")TANCHUANG = dict(text="close")@staticmethoddef add_task_and_open(action_type: str = '浏览'):url_add = '/task/add'abc = datetime.datetime.now().strftime('%y%m%d%H%M%S')task_id = "TASK{}{}".format(abc, random.randint(1000, 9999))if action_type == '浏览':add_dict = {"actionName": "浏览/浏览会员中心"}else:assert action_type == '点击'add_dict = {"actionName": "点击"}send_request('post', url=join_url(url_add), json=add_dict, headers=request_headers)Log.info('任务:{} 已新建'.format(task_id))return task_id@staticmethoddef get_visit_url(task_id: str):url_addTaskCodes = '/task/addTaskCodes'task_code_list = list()			# 暂不提供 task_code_list 生成逻辑user_id = get_user_id(dl_account)url_openTask = '/task/openTask'open_dict = {'mobile': dl_account, 'userId': user_id,'taskInfos': [{'taskCode': random.choice(task_code_list), 'callBackUrl': ''}]}res = send_request('post', json=open_dict, headers=request_headers, url=join_url(url_openTask))url = jsonpath.jsonpath(res, '$..jumpTo')Log.info('openTask返回的url:{}'.format(url))assert len(url) == 1return url[0]if __name__ == '__main__':pass

@filename: test_membership_interests_4.py

"""
@blog: https://blog.csdn.net/zyooooxie
"""import allure
import pytest
import uiautomator2 as u2from uiautomator2 import Devicefrom membership_interests_app_autotest.common_variable import dl_account, common_serial_number
from membership_interests_app_autotest.page_membership_interests_4 import PageMembershipInterests4
from membership_interests_app_autotest.common_function import my_element, screenshot_decorator
from membership_interests_app_autotest.common_function import my_assert, kill_button
from membership_interests_app_autotest.user_log import Logprint(dl_account, 'test_membership_interests_4.py')# @pytest.mark.skip
@allure.feature('大陆会员-任务相关')
class TestMembershipInterests4(PageMembershipInterests4):def h5_login(self, account: str, device: Device):login_url = 'https://zyooooxie/Login'with allure.step('浏览器打开login地址'):device.open_url(login_url)with allure.step('输入手机号、获取验证码'):my_element(device, self.QINGSHURUSHOUJIHAO).click()device.send_keys(account, clear=True)my_element(device, self.HUOQUYANZHENGMA).click()with allure.step('输入验证码'):my_element(device, self.QINGSHURUYANZHENGMA).set_text('123456')with allure.step('登录'):my_element(device, self.TONGYIBENTIAOKUAN).click()my_element(device, self.DENGLU).click()kill_button(device, self.TANCHUANG, wait_time=5)my_assert(device, self.SHENGHUOTEQUAN, 'exists', True, 'is_')@classmethoddef setup_class(cls):print('setup_class')cls.device = u2.connect(addr=common_serial_number)cls.device.implicitly_wait(10)TestMembershipInterests4().h5_login(dl_account, cls.device)@classmethoddef teardown_class(cls):print('teardown_class')del cls.device@staticmethoddef setup_method():print(__class__.__name__)@staticmethoddef teardown_method():Log.info('---------')@pytest.mark.smoke@screenshot_decorator(common_serial_number)@allure.description('用户领取任务、完成任务、断言')@allure.title('用户领取页面浏览任务')def test_1(self):task_id = self.add_task_and_open()url = self.get_visit_url(task_id=task_id)self.device.open_url(url=url)self.device.sleep(3)  # 看下效果# TODO 因为不是白名单,始终没法跑通if __name__ == '__main__':pass

执行结果

allure报告

在这里插入图片描述

日志文件、手机截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

本文链接:https://blog.csdn.net/zyooooxie/article/details/124176686

uiautomator2的这3篇博客,应该是真实分享时 代码‘马赛克’ 最少的几次。

此外,我这也用了 图像对比:有些用例是 某些H5页面 想做文案对比。我是不想一个一个字去对 + 大佬本就写了这些方法,我就‘拿来主义’ 优化下,搞了搞。 (非我原创 所以就没有做任何展示)

交流技术 欢迎+QQ 153132336 zy
个人博客 https://blog.csdn.net/zyooooxie

这篇关于uiautomator2 App自动化测试框架【三】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/zyooooxie/article/details/124176686
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/522332

相关文章

修改若依框架Token的过期时间问题

《修改若依框架Token的过期时间问题》本文介绍了如何修改若依框架中Token的过期时间,通过修改`application.yml`文件中的配置来实现,默认单位为分钟,希望此经验对大家有所帮助,也欢迎... 目录修改若依框架Token的过期时间修改Token的过期时间关闭Token的过期时js间总结修改若依

10个Python自动化办公的脚本分享

《10个Python自动化办公的脚本分享》在日常办公中,我们常常会被繁琐、重复的任务占据大量时间,本文为大家分享了10个实用的Python自动化办公案例及源码,希望对大家有所帮助... 目录1. 批量处理 Excel 文件2. 自动发送邮件3. 批量重命名文件4. 数据清洗5. 生成 PPT6. 自动化测试

10个Python Excel自动化脚本分享

《10个PythonExcel自动化脚本分享》在数据处理和分析的过程中,Excel文件是我们日常工作中常见的格式,本文将分享10个实用的Excel自动化脚本,希望可以帮助大家更轻松地掌握这些技能... 目录1. Excel单元格批量填充2. 设置行高与列宽3. 根据条件删除行4. 创建新的Excel工作表5

MySQL分表自动化创建的实现方案

《MySQL分表自动化创建的实现方案》在数据库应用场景中,随着数据量的不断增长,单表存储数据可能会面临性能瓶颈,例如查询、插入、更新等操作的效率会逐渐降低,分表是一种有效的优化策略,它将数据分散存储在... 目录一、项目目的二、实现过程(一)mysql 事件调度器结合存储过程方式1. 开启事件调度器2. 创

Python Invoke自动化任务库的使用

《PythonInvoke自动化任务库的使用》Invoke是一个强大的Python库,用于编写自动化脚本,本文就来介绍一下PythonInvoke自动化任务库的使用,具有一定的参考价值,感兴趣的可以... 目录什么是 Invoke?如何安装 Invoke?Invoke 基础1. 运行测试2. 构建文档3.

macOS怎么轻松更换App图标? Mac电脑图标更换指南

《macOS怎么轻松更换App图标?Mac电脑图标更换指南》想要给你的Mac电脑按照自己的喜好来更换App图标?其实非常简单,只需要两步就能搞定,下面我来详细讲解一下... 虽然 MACOS 的个性化定制选项已经「缩水」,不如早期版本那么丰富,www.chinasem.cn但我们仍然可以按照自己的喜好来更换

Windows自动化Python pyautogui RPA操作实现

《Windows自动化PythonpyautoguiRPA操作实现》本文详细介绍了使用Python的pyautogui库进行Windows自动化操作的实现方法,文中通过示例代码介绍的非常详细,对大... 目录依赖包睡眠:鼠标事件:杀死进程:获取所有窗口的名称:显示窗口:根据图片找元素:输入文字:打开应用:依

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

Jenkins中自动化部署Spring Boot项目的全过程

《Jenkins中自动化部署SpringBoot项目的全过程》:本文主要介绍如何使用Jenkins从Git仓库拉取SpringBoot项目并进行自动化部署,通过配置Jenkins任务,实现项目的... 目录准备工作启动 Jenkins配置 Jenkins创建及配置任务源码管理构建触发器构建构建后操作构建任务

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11