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自动化测试框架【三】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/522332

相关文章

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

如何使用Ansible实现CI/CD流水线的自动化

如何使用Ansible实现CI/CD流水线的自动化 持续集成(CI)和持续交付(CD)是现代软件开发过程中的核心实践,它们帮助团队更快地交付高质量的软件。Ansible,作为一个强大的自动化工具,可以在CI/CD流水线中发挥关键作用。本文将详细介绍如何使用Ansible实现CI/CD流水线的自动化,包括设计流水线的结构、配置管理、自动化测试、部署、以及集成Ansible与CI/CD工具(如Jen

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细介绍 Curator 框架,包括它的设计哲学、核心组件以及如何使用 Curator 来简化 ZooKeeper 的操作。 1