全网最牛,Appium自动化测试框架-关键字驱动+数据驱动实战(二)

目录:导读

    • 前言
    • 一、Python编程入门到精通
    • 二、接口自动化项目实战
    • 三、Web自动化项目实战
    • 四、App自动化项目实战
    • 五、一线大厂简历
    • 六、测试开发DevOps体系
    • 七、常用自动化测试工具
    • 八、JMeter性能测试
    • 九、总结(尾部小惊喜)


前言

util 包

util 包属于第一层的测试工具层:用于实现测试过程中调用的工具类方法,例如读取配置文件、页面元素的操作方法、操作 Excel 文件、生成测试报告、发送邮件等。

global_var.py
本模块用于定义测试过程中所需的全局变量。

import osPROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# APP配置信息路径
INI_FILE_PATH = os.path.join(PROJECT_DIR, "conf", "desired_caps_config.ini")# 异常截图路径
EXCEPION_PIC_PATH = os.path.join(PROJECT_DIR, "exception_pic")# 日志配置文件路径
LOG_CONF_FILE_PATH = os.path.join(PROJECT_DIR, "conf", "logger.conf")# 测试数据文件路径
TEST_DATA_FILE_PATH = os.path.join(PROJECT_DIR, "test_data", "test_case.xlsx")# 测试报告存放路径
TEST_REPORT_FILE_DIR = os.path.join(PROJECT_DIR, "test_report")# Appium server地址
APPIUM_SERVER = 'http://localhost:4723/wd/hub'# 测试数据文件中,测试用例sheet中部分列对应的数字序号
TESTCASE_CASE_NAME_COL_NO = 0
TESTCASE_FRAMEWORK_TYPE_COL_NO = 1
TESTCASE_CASE_STEP_SHEET_NAME_COL_NO = 2
TESTCASE_DATA_SOURCE_SHEET_NAME_COL_NO = 3
TESTCASE_IS_EXECUTE_COL_NO = 4
TESTCASE_TEST_TIME_COL_NO = 5
TESTCASE_TEST_RESULT_COL_NO = 6# 用例步骤sheet中,部分列对应的数字序号
CASESTEP_NAME_COL_NO = 0
CASESTEP_ACTION_COL_NO = 1
CASESTEP_LOCATE_METHOD_COL_NO = 2
CASESTEP_LOCATE_EXPRESSION_COL_NO = 3
CASESTEP_OPERATION_VALUE_COL_NO = 4
CASESTEP_IS_EXECUTE_COL_NO = 5
CASESTEP_TEST_TIME_COL_NO = 6
CASESTEP_TEST_RESULT_COL_NO = 7
CASESTEP_EXCEPTION_INFO_COL_NO = 8
CASESTEP_EXCEPTION_PIC_DIR_COL_NO = 9# 数据源sheet中,是否执行列对应的数字编号
DATASOURCE_DATA = 0
DATASOURCE_KEYWORD = 1
DATASOURCE_IS_EXECUTE = 2
DATASOURCE_TEST_TIME = 3
DATASOURCE_TEST_RESULT = 4# 测试执行结果统计
TOTAL_CASE = 0
PASS_CASE = 0
FAIL_CASE = 0if __name__ == "__main__":print(PROJECT_DIR)

find_element_util.py

本模块封装了基于显式等待的界面元素定位方法。

from selenium.webdriver.support.ui import WebDriverWait# 显式等待一个元素
def find_element(driver, locate_method, locate_exp):# 显式等待对象(最多等10秒,每0.2秒判断一次等待的条件)return WebDriverWait(driver, 10, 0.2).until(lambda x: x.find_element(locate_method, locate_exp))# 显式等待一组元素
def find_elements(driver, locate_method, locate_exp):# 显式等待对象(最多等10秒,每0.2秒判断一次等待的条件)return WebDriverWait(driver, 10, 0.2).until(lambda x: x.find_elements(locate_method, locate_exp))

excel_util.py

本模块封装了对 excel 的读写操作(openpyxl 版本:3.0.4)。

import os
from openpyxl import load_workbook
from openpyxl.styles import PatternFill, Font, Side, Border
from util.datetime_util import *
from util.global_var import *
from util.log_util import *# 支持excel读写操作的工具类
class Excel:# 初始化读取excel文件def __init__(self, file_path):if not os.path.exists(file_path):returnself.wb = load_workbook(file_path)# 初始化默认sheetself.ws = self.wb.activeself.data_file_path = file_path# 初始化颜色字典,供设置样式用self.color_dict = {"red": "FFFF3030", "green": "FF008B00"}def get_all_sheet(self):return self.wb.get_sheet_names()# 打开指定sheetdef get_sheet(self, sheet_name):if sheet_name not in self.get_all_sheet():print("sheet名称【%s】不存在!" % sheet_name)returnself.ws = self.wb.get_sheet_by_name(sheet_name)return True# 获取最大行号def get_max_row_no(self):# openpyxl的API的行、列索引默认都从1开始return self.ws.max_row# 获取最大列号def get_max_col_no(self):return self.ws.max_column# 获取所有行数据def get_all_row_data(self, head_line=True):# 是否需要标题行数据的标识,默认需要if head_line:min_row = 1  # 行号从1开始,即1为标题行else:min_row = 2result = []# min_row=None:默认获取标题行数据for row in self.ws.iter_rows(min_row=min_row, max_row=self.get_max_row_no(), max_col=self.get_max_col_no()):result.append([cell.value for cell in row])return result# 获取指定行数据def get_row_data(self, row_num):# 0 为标题行return [cell.value for cell in self.ws[row_num+1]]# 获取指定列数据def get_col_data(self, col_num):# 索引从0开始return [cell.value for cell in tuple(self.ws.columns)[col_num]]# 追加行数据且可以设置样式def write_row_data(self, data, font_color=None, border=True, fill_color=None):if not isinstance(data, (list, tuple)):print("写入数据失败:数据不为列表或元组类型!【%s】" % data)self.ws.append(data)# 设置字体颜色if font_color:if font_color.lower() in self.color_dict.keys():font_color = self.color_dict[font_color]# 设置单元格填充颜色if fill_color:if fill_color.lower() in self.color_dict.keys():fill_color = self.color_dict[fill_color]# 设置单元格边框if border:bd = Side(style="thin", color="000000")# 记录数据长度(否则会默认与之前行最长数据行的长度相同,导致样式超过了该行实际长度)count = 0for cell in self.ws[self.get_max_row_no()]:# 设置完该行的实际数据长度样式后,则退出if count > len(data) - 1:breakif font_color:cell.font = Font(color=font_color)# 如果没有设置字体颜色,则默认给执行结果添加字体颜色else:if cell.value is not None and isinstance(cell.value, str):if cell.value.lower() == "pass" or cell.value == "成功":cell.font = Font(color=self.color_dict["green"])elif cell.value.lower() == "fail" or cell.value == "失败":cell.font = Font(color=self.color_dict["red"])if border:cell.border = Border(left=bd, right=bd, top=bd, bottom=bd)if fill_color:cell.fill = PatternFill(fill_type="solid", fgColor=fill_color)count += 1# 指定行插入数据(行索引从0开始)def insert_row_data(self, row_no, data, font_color=None, border=True, fill_color=None):if not isinstance(data, (list, tuple)):print("写入数据失败:数据不为列表或元组类型!【%s】" % data)for idx, cell in enumerate(self.ws[row_no+1]):  # 此处行索引从1开始cell.value = data[idx]# 生成写入了测试结果的excel数据文件def save(self, save_file_name, timestamp):save_dir = os.path.join(TEST_REPORT_FILE_DIR, get_chinese_date())if not os.path.exists(save_dir):os.mkdir(save_dir)save_file = os.path.join(save_dir, save_file_name + "_" + timestamp + ".xlsx")self.wb.save(save_file)info("生成测试结果文件:%s" % save_file)return save_fileif __name__ == "__main__":from util.global_var import *from util.datetime_util import *excel = Excel(TEST_DATA_FILE_PATH)excel.get_sheet("测试结果统计")# print(excel.get_all_row_data())# excel.write_row_data(["4", None, "嘻哈"], "green", True, "red")excel.insert_row_data(1, [1,2,3])excel.save(get_timestamp())

ini_reader.py

本模块封装了对 ini 配置文件的读取操作。

import os
import configparser# 读取ini文件的工具类
class IniParser:# 初始化打开ini文件def __init__(self, file_path):if not os.path.exists(file_path):print("ini文件【%s】不存在!" % file_path)returnself.cf = configparser.ConfigParser()self.cf.read(file_path, encoding="utf-8")# 获取所有分组def get_sections(self):return self.cf.sections()# 获取指定分组的所有键def get_options(self, section):return self.cf.options(section)  # 注意,获取的键会自动转小写# 获取指定分组的所有键值对def get_items(self, section):return dict(self.cf.items(section))  # 注意,获取的键会自动转小写# 获取指定分组指定键的值def get_value(self, section, option):return self.cf.get(section, option)if __name__ == "__main__":from util.global_var import *p = IniParser(INI_FILE_PATH)print(p.get_sections())print(p.get_options("desired_caps"))print(p.get_items("desired_caps"))print(p.get_value("desired_caps", "deviceName"))

email_util.py

本模块封装了邮件发送功能。(示例代码中的用户名/密码已隐藏)

import yagmail
import traceback
from util.log_util import *def send_mail(attachments_report_name, receiver, subject, content):try:# 连接邮箱服务器# 注意:若使用QQ邮箱,则password为授权码而非邮箱密码;使用其它邮箱则为邮箱密码# encoding设置为GBK,否则中文附件名会乱码yag = yagmail.SMTP(user="*****@163.com", password="*****", host="smtp.163.com", encoding='GBK')# 收件人、标题、正文、附件(若多个收件人或多个附件,则可使用列表)yag.send(to=receiver, subject=subject, contents=content, attachments=attachments_report_name)# 可简写:yag.send("****@163.com", subject, contents, report)info("测试报告邮件发送成功!【邮件标题:%s】【邮件附件:%s】【收件人:%s】" % (subject, attachments_report_name, receiver))except:error("测试报告邮件发送失败!【邮件标题:%s】【邮件附件:%s】【收件人:%s】" % (subject, attachments_report_name, receiver))error(traceback.format_exc())if __name__ == "__main__":send_mail("e:\\code.txt", "xxxxxx@qq.com", "测试邮件", "正文")

datetime_util.py

本模块实现了获取各种格式的当前日期时间。

import time# 返回中文格式的日期:xxxx年xx月xx日
def get_chinese_date():year = time.localtime().tm_yearif len(str(year)) == 1:year = "0" + str(year)month = time.localtime().tm_monif len(str(month)) == 1:month = "0" + str(month)day = time.localtime().tm_mdayif len(str(day)) == 1:day = "0" + str(day)return "{}年{}月{}日".format(year, month, day)# 返回英文格式的日期:xxxx/xx/xx
def get_english_date():year = time.localtime().tm_yearif len(str(year)) == 1:year = "0" + str(year)month = time.localtime().tm_monif len(str(month)) == 1:month = "0" + str(month)day = time.localtime().tm_mdayif len(str(day)) == 1:day = "0" + str(day)return "{}/{}/{}".format(year, month, day)# 返回中文格式的时间:xx时xx分xx秒
def get_chinese_time():hour = time.localtime().tm_hourif len(str(hour)) == 1:hour = "0" + str(hour)minute = time.localtime().tm_minif len(str(minute)) == 1:minute = "0" + str(minute)second = time.localtime().tm_secif len(str(second)) == 1:second = "0" + str(second)return "{}时{}分{}秒".format(hour, minute, second)# 返回英文格式的时间:xx:xx:xx
def get_english_time():hour = time.localtime().tm_hourif len(str(hour)) == 1:hour = "0" + str(hour)minute = time.localtime().tm_minif len(str(minute)) == 1:minute = "0" + str(minute)second = time.localtime().tm_secif len(str(second)) == 1:second = "0" + str(second)return "{}:{}:{}".format(hour, minute, second)# 返回中文格式的日期时间
def get_chinese_datetime():return get_chinese_date() + " " + get_chinese_time()# 返回英文格式的日期时间
def get_english_datetime():return get_english_date() + " " + get_english_time()# 返回时间戳
def get_timestamp():year = time.localtime().tm_yearif len(str(year)) == 1:year = "0" + str(year)month = time.localtime().tm_monif len(str(month)) == 1:month = "0" + str(month)day = time.localtime().tm_mdayif len(str(day)) == 1:day = "0" + str(day)hour = time.localtime().tm_hourif len(str(hour)) == 1:hour = "0" + str(hour)minute = time.localtime().tm_minif len(str(minute)) == 1:minute = "0" + str(minute)second = time.localtime().tm_secif len(str(second)) == 1:second = "0" + str(second)return "{}{}{}_{}{}{}".format(year, month, day, hour, minute, second)if __name__ == "__main__":print(get_chinese_datetime())print(get_english_datetime())

get_desired_caps.py

本模块实现了获取 ini 配置文件中的 Appium 创建 Session 的配置信息。

from util.ini_reader import IniParser
from util.global_var import INI_FILE_PATHdef get_desired_caps():pcf = IniParser(INI_FILE_PATH)items = pcf.get_items("desired_caps")  # 获取的键会自动转成小写desired_caps = {"platformName": items.get("platformname"),"platformVersion": items.get("platformversion"),"deviceName": items.get("devicename"),"appPackage": items.get("apppackage"),"appActivity": items.get("appactivity"),"unicodeKeyboard": items.get("unicodekeyboard"),"autoAcceptAlerts": items.get("autoacceptalerts"),"resetKeyboard": items.get("resetkeyboard"),"noReset": items.get("noreset"),"newCommandTimeout": items.get("newcommandtimeout")}return desired_capsif __name__ == "__main__":from util.global_var import *print(get_desired_caps())

log_util.py

封装了日志打印输出、级别设定等功能。

import logging
import logging.config
from util.global_var import *# 日志配置文件:多个logger,每个logger指定不同的handler
# handler:设定了日志输出行的格式
#          以及设定写日志到文件(是否回滚)?还是到屏幕
#          还定了打印日志的级别
logging.config.fileConfig(LOG_CONF_FILE_PATH)
logger = logging.getLogger("example01")def debug(message):logging.debug(message)def info(message):logging.info(message)def warning(message):logging.warning(message)def error(message):logging.error(message)if __name__ == "__main__":debug("hi")info("gloryroad")warning("hello")error("这是一个error日志")

report_util.py

生成测试结果文件并发送邮件。

from util.email_util import send_mail
from util.log_util import *
from util.datetime_util import *# 生成测试报告并发送邮件
def create_excel_report_and_send_email(excel_obj, receiver, subject, content):""":param excel_obj: excel对象用于保存文件:param timestamp: 用于文件命名的时间戳:return: 返回excel测试报告文件名"""time_stamp = get_timestamp()report_path = excel_obj.save(subject, time_stamp)send_mail(report_path, receiver, subject+"_"+time_stamp, content)

conf 目录

conf 目录属于第一层测试工具层,用于存储各配置文件。

desired_caps_config.ini
本配置文件存储了 Appium 创建 Session 的配置信息。

[desired_caps]
platformName=Android
platformVersion=6
deviceName=3DN6T16B26001805
appPackage=com.xsteach.appedu
appActivity=com.xsteach.appedu.StartActivity
unicodeKeyboard=True
autoAcceptAlerts=True
resetKeyboard=True
noReset=True
newCommandTimeout=6000

logger.conf
本配置文件用于日志功能的具体配置。

###############################################
[loggers]
keys=root,example01,example02
[logger_root]
level=DEBUG
handlers=hand01,hand02[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0[logger_example02]
handlers=hand01,hand03
qualname=example02
propagate=0###############################################
[handlers]
keys=hand01,hand02,hand03[handler_hand01]
class=StreamHandler
level=INFO
formatter=form01
args=(sys.stderr,)[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=('E:\\pycharm_project_dir\\AppAutoTest\\log\\app_test.log', 'a')[handler_hand03]
class=handlers.RotatingFileHandler
level=INFO
formatter=form01
args=('E:\\pycharm_project_dir\\AppAutoTest\\log\\app_test.log', 'a', 10*1024*1024, 5)###############################################
[formatters]
keys=form01,form02[formatter_form01]
format=%(asctime)s [%(levelname)s] %(message)s
datefmt=%Y-%m-%d %H:%M:%S[formatter_form02]
format=%(name)-12s: [%(levelname)-8s] %(message)s
datefmt=%Y-%m-%d %H:%M:%S

test_data 目录

test_data 目录用于存放测试数据文件(Excel),存储了用例步骤、用例执行关键字、数据源等测试数据。

31

32

33

main.py

本模块是本框架的运行主入口,属于第四层“测试场景层”,将测试用例组织成测试场景,实现各种级别 cases 的管理,如冒烟,回归等测试场景。

基于 business_process/main_process.py 中的模块用例 sheet 执行函数或主 sheet 执行函数,组装测试场景。

可直接用代码组装测试场景,也可根据 excel 数据文件的用例集合和用例步骤的维护来设定测试场景。
完成测试执行后生成测试结果文件并发送邮件。

from bussiness_process.main_process import *
from util.report_util import *# 组装测试场景
# 冒烟测试
def smoke_test(report_name):excel, _ = suite_process(TEST_DATA_FILE_PATH, "进入主页")excel, _ = suite_process(excel, "登录")excel, _ = suite_process(excel, "退出")# 生成测试报告并发送邮件create_excel_report_and_send_email(excel, ['xxxxxxxxx@163.com', 'xxxxxxxx@qq.com'], report_name, "请查收附件:app自动化测试报告")# 全量测试:执行主sheet的用例集
def suite_test(report_name):excel = main_suite_process(TEST_DATA_FILE_PATH, "测试用例集")create_excel_report_and_send_email(excel, ['xxxxxxx@163.com', 'xxxxxxx@qq.com'], report_name, "请查收附件:app自动化测试报告")if __name__ == "__main__":# smoke_test("APP自动化测试报告_冒烟测试")suite_test("APP自动化测试报告_全量测试")

test_report 目录

本目录用于存放测试结果文件。

34

35

36

exception_pic 目录

本目录用于存放失败用例的截图。

37

log 目录

本目录用于存放日志输出文件(日志内容同时也会输出到控制台)。
log/app_test.log:

38

下面是我整理的2023年最全的软件测试工程师学习知识架构体系图

一、Python编程入门到精通

请添加图片描述

二、接口自动化项目实战

请添加图片描述

三、Web自动化项目实战

请添加图片描述

四、App自动化项目实战

请添加图片描述

五、一线大厂简历

请添加图片描述

六、测试开发DevOps体系

请添加图片描述

七、常用自动化测试工具

请添加图片描述

八、JMeter性能测试

请添加图片描述

九、总结(尾部小惊喜)

不论起点如何,只要拥有激情与毅力,奋斗就是通往成功的道路;不论困难多大,只要心怀信念与勇气,挑战就是成长的机会。努力奋斗,追逐梦想,将创造属于自己的辉煌人生!

每一次努力,都是迈向辉煌的一步;每一次奋斗,都是砥砺前行的力量。不辜负青春,铭记初心,扬起梦想的风帆,执着追逐,终将驶向成功的彼岸。

不论身处何地,只要心怀梦想,就别停止追逐;不管困难多大,只要坚持奋斗,就能开创未来。披荆斩棘,勇往直前,舞动青春的旋律,绽放人生的辉煌!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/36698.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据可视化工具LightningChart .NET正式发布v10.5.1——拥有全新的3D新功能

LightningChart.NET完全由GPU加速,并且性能经过优化,可用于实时显示海量数据-超过10亿个数据点。 LightningChart包括广泛的2D,高级3D,Polar,Smith,3D饼/甜甜圈,地理地图和GIS图表以及适用于科学…

网络安全专业术语英文缩写对照表

因在阅读文献过程中经常遇到各种专业缩写,所以把各种缩写总结了一下。 因能力有限,错误在所难免,欢迎进行纠错与补充:https://github.com/piaolin/CSAbbr 渗透相关 缩写全称解释备注XSSCross Site Script Attack跨站脚本攻击为…

ResNet创新点总结

ResNet(Residual Networks)是深度学习中的一个重要架构,其创新点主要体现在解决了深层神经网络训练中的梯度消失和梯度爆炸问题,从而使得可以构建更深的神经网络。以下是 ResNet 的创新点总结:   1. 残差连接&#x…

nlohmann json:通过items遍历object/array

//官方的例子 #include <iostream> #include <nlohmann/json.hpp>using json = nlohmann::json;int main() {// create JSON valuesjson j_object = {{"one", 1}, {"two", 2}};json j_array = {1, 2, 4, 8, 16};// example for an objectfor (…

java毕业设计-智慧食堂管理系统-内容快览

首页 智慧食堂管理系统是一种可以提高食堂运营效率的管理系统。它将前端代码使用Vue实现&#xff0c;后端使用Spring Boot实现。这个系统的目的是简化食堂管理&#xff0c;提高食堂服务质量。在现代快节奏的生活中&#xff0c;人们对餐饮服务提出了更高的要求&#xff0c;食堂管…

Flink-间隔联结

间隔联结只支持事件时间间隔联结如果遇到迟到数据&#xff0c;则会关联不上&#xff0c;比如来了一个5秒的数据&#xff0c;它可以关联前2秒的数据&#xff0c;后3秒的数据&#xff0c;就是可以关联3秒到8秒的数据&#xff0c;然后又来了一个6秒的数据&#xff0c;可以关联4秒到…

Docker安装elasticsearch分布式搜索

文章目录 ☀️安装elasticsearch☀️1.部署单点es&#x1f338;1.1.创建网络&#x1f338;1.2.下载镜像&#x1f338;1.3.运行 ☀️2.部署kibana&#x1f338;2.1.部署&#x1f338;2.2.DevTools ☀️3.安装IK分词器&#x1f338;3.1.在线安装ik插件&#xff08;较慢&#xff0…

Rx.NET in Action 中文介绍 前言及序言

Rx 处理器目录 (Catalog of Rx operators) 目标可选方式Rx 处理器(Operator)创建 Observable Creating Observables直接创建 By explicit logicCreate Defer根据范围创建 By specificationRangeRepeatGenerateTimerInterval Return使用预设 Predefined primitivesThrow …

答疑:Arduino IDE配置其他开发板下载速度慢

基于案例&#xff1a;Linux环境Arduino IDE中配置ATOM S3 通常&#xff0c;网络问题较多&#xff0c;可以使用一些技巧。 https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json 没有配置&#xff0c;不支持M5Stack&#xff08;ESP32&…

HCIA静态路由与动态路由

目录 一、静态路由 定义&#xff1a; 适用环境 二、动态路由 定义&#xff1a; 特点&#xff1a; 动态路由协议: 三、缺点&#xff1a; 1&#xff09;静态路由缺点: 2&#xff09;动态路由的缺点: 四、静态路由与动态路由的区别 静态路由: 动态路由: 一、静态路…

字节原来这么容易进,是面试官放水,还是公司实在是太缺人?

本人211非科班&#xff0c;之前在字节和腾讯实习过&#xff0c;这次其实没抱着什么特别大的希望投递&#xff0c;没想到字节可以再给我一次机会&#xff0c;还是挺开心的。 本来以为有个机会就不错啦&#xff01;没想到能成功上岸&#xff0c;在这里要特别感谢帮我内推的同学&…

【Python】进阶之 MySQL入门教程

文章目录 数据库概述Mysql概述Mysql安装与使用Navicat安装和使用Mysql终端指令操作Mysql和python交互订单管理案例实现 数据库概述 数据库的由来 发展历程说明人工管理阶段用纸带等进行数据的存储文件系统阶段数据存储在文件中数据库阶段解决了文件系统问题高级数据库阶段分布式…

IDEA 设置字体大小无效

设置字体大小&#xff0c;一般都是从file>settings>editor>font>Size里设置&#xff0c;一般都有效。 但是&#xff0c;如果是更换了主体&#xff0c;则需要从主体颜色菜单那里这是&#xff0c;你看这个页面&#xff0c;上面黄色三角也提示你了&#xff0c;要去颜色…

学习笔记整理-DOM-03-定时器

一、定时器 1. setInterval()函数 setInterval()函数可以重复调用一个函数&#xff0c;在每次调用之间具有固定的时间间隔。 setInterval(function () { // 这个函数将自动被以固定间隔时间调用 }, 2000);第一个参数是函数第二个参数是间隔时间&#xff0c;以毫秒为单位&…

SpringBoot中间件使用之EventBus、Metric、CommandLineRunner

1、EventBus 使用EventBus 事件总线的方式可以实现消息的发布/订阅功能&#xff0c;EventBus是一个轻量级的消息服务组件&#xff0c;适用于Android和Java。 // 1.注册事件通过 EventBus.getDefault().register(); // 2.发布事件 EventBus.getDefault().post(“事件内容”); …

深入理解spring面经

1 了解SpringMVC的处理流程吗&#xff1f; 用户发送请求至前端控制器DispatcherServlet。DispatcherServlet通过处理器映射器HandlerMapping找到对应的处理器。DispatcherServlet将请求提交给对应的处理器Controller。Controller处理完请求后返回ModelAndView。DispatcherServ…

面试攻略,Java 基础面试 100 问(十三)

什么时候用 assert&#xff1f; assertion(断言)在软件开发中是一种常用的调试方式&#xff0c;很多开发语言中都支持这种机制。一般来说&#xff0c;assertion 用于保证程序最基本、关键的正确性。assertion 检查通常在开发和测试时开启。为了提高性能&#xff0c;在软件发布…

支持对接鸿蒙系统的无线模块及其常见应用介绍

近距离的无线通信得益于万物互联网的快速发展&#xff0c;基于集成部近距离无线连接&#xff0c;为固定和移动设备建立通信的蓝牙技术也已经广泛应用于汽车领域、工业生产及医疗领域。为协助物联网企业终端产品能快速接入鸿蒙生态系统&#xff0c;SKYLAB联手国产芯片厂家研发推…

找不到mfc140u.dll怎么办?mfc140u.dll丢失怎样修复?简单三招搞定

最近我遇到了一个问题&#xff0c;发现我的电脑上出现了mfc140u.dll文件丢失的错误提示。这个错误导致一些应用程序无法正常运行&#xff0c;让我感到非常困扰。经过一番研究和尝试&#xff0c;我终于成功修复了这个问题&#xff0c;并从中总结出了一些心得。 mfc140u.dll丢失原…

财报解读:继续押注Disney+,迪士尼距离盈利还有多远?

迪士尼最新一季的“答卷”&#xff0c;透露着不小的寒气。 近日&#xff0c;迪士尼披露了2023财年第三季度&#xff08;自然年2023年Q2&#xff09;业绩报告&#xff0c;营收223.3亿美元&#xff0c;同比仅增长4%&#xff0c;低于市场预期的225.1亿美元&#xff1b;归母净亏损…