当前位置: 首页 > news >正文

物业系统自主研发接口测试框架

1、自主研发框架整体设计

1.1、什么是测试框架?

在了解什么是自动化测试框架之前,先了解一下什么叫框架?框架是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面,而后者是从目的方面给出的定义。从框架的定义可以了解,框架可以是被重用的基础平台;框架也可以是组织架构类的东西。其实后者更为贴切,因为框和架本来就是组织和归类所用的。

所以自动化测试框架的定义为:由一个或多个自动化测试基础模块、自动化测试管理模块自动化测试统计模块等组成的工具集合。

框架的定义来分,自动化测试框架可以分为:基础功能测试框架、管理执行框架;按不同的测试类型来分,可以分为:功能自动化测试框架、性能自动化测试框架;按测试阶段来分,可以分为:单元自动化测试框架、接口自动化测试框架、系统自动化测试框架;按组成结构来分,可以分为:单一自动化测试框架、综合自动化测试框架;按部署方式来分,可以分为:单机自动化测试框架、分布式自动化测试框架。

看到这里,也许大家看完也不清楚上面到底讲的是什么。因为没有实际接触过,不知道具体功用,只是用一种抽象解释另一种抽象,另外只是描述了结论,没有描述推演的过程。

1.2、那么如何打破阻碍呢?

方法如下:

1、工作遇到了什么问题,需要使用XX技术?

2、这个技术能解决当下的工作问题吗?解决到什么程度呢?

3、这个技术能做什么,不能做什么?

4、具体如何实现的过程?

当前有下面的脚本需要接入到框架中。

要有以终为始的逆向思维方式,从最下面往上面分析。

1.3、框架测试报告初期规划:

执行时间,执行人,执行环境..

XXX时间:执行了XXX接口,接口执行结果

XXX时间:脚本报错信息

框架脚本整体执行情况统计

把框架测试结果发给相关责任人

1.4测试框架驱动设计

1、设置全局环境数据结构

2、读取测试框架配置文件

3、按照配置文件制定内容执行对应的测试脚本

4、创建测试报告,并写入总体初始化内容

5、若执行完所有的测试脚本,输出最终的测试报告,否则继续执行下一个脚本

6、写入新的测试报告内容

7、保存测试报告。

1.5 测试框架整体结构

本次测试框架分为三个层。分别为驱动层test_driver,报告层test_report,测试脚本层test_script。

其中config.csv是存放的测试脚本及路径 。

driverV1.py是驱动的执行程序。

report1.py存放的是测试报告

testcase_report1.txt存放的是单个用例不同数据的执行结果。

2、登录接口自研框架实践_global+csv+system文件

driver通过读取config.csv里面的信息,读取脚本名,再到test_script下面去找对应的脚本执行。

驱动读取框架配置文件

3、自研框架类图及流程图设计梳理

框架整体流程图:

config.csv内容

3.1 驱动类设计

进行实例化对象

#导入类库
import csv,os
import datetime
# 试验1:普通全局变量的使用
import pymysqlglobal glob_url
glob_url='https://svr-6-9009.share.51env.net/prod-api'
print(glob_url)
# 封装成一个驱动类
class driver_run():#读取配置文件,获取py文件名def run_testpy(self):# 设置脚本程序对应的路径path = "..\\test_script\\"csvfile=open("config.csv",'r')rows=csv.reader(csvfile)# 跳过标题行next(rows)# 逐行读取配置文件内容for row in rows:print(row[2])self.number=row[0]self.name = row[1]# 判断是否创建测试用例报告头部if row[4]=='Y':if row[3] == '1':self.create_testcase_report()# 调用指定的接口脚本文件os.system("python "+path+row[2])# return row[0],row[1]  不能用面向过程的方法,要用面向对象的方法# 调用报告写入内容方法self.write_report()self.endtime=datetime.datetime.now()# 获取当前框架程序运行的总时长,如果时长已经大于50分钟了,# 主动调用登录接口,重新更新tokenrtime = self.endtime - self.starttime# 判断时间差是否超过50分钟if (rtime.seconds // 60) >= 50:# 调用登录接口os.system("..\\test_script\\loginV4.py")# 定义创建测试报告并写入头部公共信息def create_report(self):self.starttime = datetime.datetime.now()# print(self.starttime)# 时间进行格式化starttime = self.starttime.strftime("%Y-%m-%d %H:%M:%S")print(starttime)# 将时间戳写入txt文件txtReport = open('..\\test_report\\report1.txt', "w")txtReport.write("*****************************************************************""\n")txtReport.write("智慧物业系统接口测试框架"+"\n")txtReport.write(starttime+"         shangshang"+"       "+"\n")txtReport.write("接口测试执行环境说明:"+glob_url+"\n")txtReport.write("*****************************************************************"+"\n")txtReport.close()# 定义创建测试用例报告并写入头部公共信息def create_testcase_report(self):starttime = datetime.datetime.now()print(starttime)# 时间进行格式化starttime = starttime.strftime("%Y-%m-%d %H:%M:%S")print(starttime)# 将时间戳写入txt文件txttestReport = open('..\\test_report\\testcase_report1.txt', "w")txttestReport.write("*****************************************************************""\n")txttestReport.write("该测试用例运行开始时间:"+starttime+"\n")txttestReport.write("接口编号"+self.number+"          ")txttestReport.write('接口名称'+self.name+"\n")txttestReport.write("*****************************************************************"+"\n")txttestReport.close()def write_report(self):txtReport = open('..\\test_report\\report1.txt', "a")txtReport.write("接口编号:"+self.number+"    接口名称:"+self.name)# 读取comresult文件中的测试结果comfile=open("commonresult.txt", 'r')for result in comfile:txtReport.write("       接口测试结果:"+result+"\n")comfile.close()txtReport.close()def write_commonresult(self,result):# 写入接口测试结果到公共文件中comfile = open("..\\test_driver\\commonresult.txt", 'w')# 把result存入data文件中comfile.write(result)comfile.close()#取出token文件中的token的值def get_token(self):tokenfile=open("..\\test_driver\\token.txt","r")for token in tokenfile:tokenvalue=tokenreturn tokenvalue#连接数据库进行查询返回查询结果def db_connect(self,sql):# 打开数据库连接db=pymysql.connect(host='vip.51env.net',user='readonly',password='******',port=30001,db='******',charset='utf8')# 用cursor()方法获取操作游标cursor = db.cursor()# 使用execute方法执行SQL语句cursor.execute(sql)# 使用fetchall()方法获取一条数据db_result=cursor.fetchall()# 关闭数据库连接db.close()# 返回查询结果return db_resultif __name__ == '__main__':#实例化驱动类的对象objdriver=driver_run()# 创建测试报告头部objdriver.create_report()# 调用接口文件objdriver.run_testpy()

3.2 登录类

实例化登录类

# ********************************************************************************
# 登录接口V5.0脚本实现
# 功能:1、调用图片验证码接口获取uuid
#      2、将获取到的uuid传入登录接口中
#       3、分别对两个功能进行面向对象封装
# 修改内容: 增加token属性,为其他接口提供验证
# ********************************************************************************
#  导入类库
import requests
import json
# 定义一个类:包含两个方法和一个属性
from test_driver.driverV1 import driver_run,glob_urlclass login_interface():# 定义一个属性def __init__(self):self.uuid=''#增加token属性self.token=''#方法1:获取验证码对应的uuiddef getuuid(self):# 取验证码图片接口uuid# 定义获取验证码接口地址CaptchaURL = 'https://svr-6-9009.share.51env.net/prod-api/captchaImage'# 发送请求response = requests.get(CaptchaURL).json()# 获取uuid# print(type(response))# 全局uuid引用说明# global uuidself.uuid = response['uuid']# print(self.uuid)# return uuid# 执行登录接口的测试def login_test(self):# 定义接口地址url = "https://svr-6-9009.share.51env.net/prod-api/login"# 定义接口参数# print("登录方法中", self.uuid)userinfo = {"username": "admin","password": "admin123","code": "51testing","uuid": self.uuid}# print(type(userinfo))# 将字典类型转化为json类型userjson = json.dumps(userinfo)# print(type(userjson))# 发送接口请求response = requests.post(url, data=userjson, headers={"Content-Type": "application/json"}).json()# print(response)# print(response["msg"])# 对比实际和预期结果if response["msg"] == '操作成功' and response["username"] == 'admin':result="登录接口成功"self.token=response["token"]tokenfile=open("..\\test_driver\\token.txt","w")tokenfile.write(self.token)tokenfile.close()else:result="登录接口失败"return result# 进行实例化调用
if __name__ == '__main__':# 实例化对象loginObj=login_interface()# 调用其中的方法loginObj.getuuid()result=loginObj.login_test()print(result)# 实例化驱动类对象objdriver=driver_run()# 调用写入公共文件方法objdriver.write_commonresult(result)

3.3 获取用户信息接口

代码:

# **********************************************************
# 获取登录用户信息接口V3.0脚本实现
# 功能:常量参数传递
# 问题1:引用登录接口类
# 问题2:运行登录接口类,并获取最新的token
# 问题3:用面向对象的方法将获取到的最新的token传入获取用户信息接口
# ***********************************************************
# 引入登录接口类
from test_driver.driverV1 import glob_url,driver_run
# 导入类库
import requests# **************************************************class GetUserInfo():def getuser_test(self,token):# 定义接口地址url=glob_url+'/getInfo'header={'Authorization':'Bearer '+token}# 发送请求并获取self.response=requests.get(url,headers=header).json()print(self.response)def getuser_check(self):# 进行检查点的验证# 提取msgmsg=self.response['msg']# print(msg)# 通过assert断言进行msg的验证# 提取电话phone=self.response['user']['phonenumber']# print(phone)# 提取邮箱email=self.response['user']['email']# print(email)# 提取用户名username=self.response['user']['userName']# print(username)#对assert进行异常捕获try:assert msg == '操作成功'assert phone=='13800138000'assert email=='13800138000@139.com'assert username=='admin'except:result="获取用户信息接口测试失败"else:result = "获取用户信息接口测试成功"return  resultif __name__ == '__main__':objdriver=driver_run()token=objdriver.get_token()print(token)#实例化获取用户信息对象类objgetuser=GetUserInfo()objgetuser.getuser_test(token)result=objgetuser.getuser_check()# 将测试执行结论放入comresult.txt中objdriver.write_commonresult(result)

3.4 创建商铺接口

#创建商铺接口V1.0接口脚本实现
#功能:常量参数传递
#*************************************************************************
# 导入类库
import datetime
import jsonimport requests
import pymysqlfrom test_driver.driverV1 import glob_url, driver_runclass createhouse_interface():def createhouse_test(self,token):# 打开测试用例报告文件txttestReport = open('..\\test_report\\testcase_report1.txt', "a")# 定义接口地址url=glob_url+'/baseconfig/House'for i in range(1,3):# 传入接口参数,获取实际返回值self.code='05-09-'+str(i)housedata={"block": "01","code": self.code,"buildingsquare": "100","usesquare": "50","state": "empty","floor": "12","rentFee": "12000","remark": "test"}housejson=json.dumps(housedata)# 传入token参数header = {'Authorization': 'Bearer ' + token,"Content-Type":"application/json"}# 比对结果1:接口返回值response=requests.post(url,data=housejson,headers=header).json()print(response['msg'])# 比对结果:直接比对接口返回msgself.msg=response['msg']if self.msg=='新建成功':result='创建商铺接口测试用例'+self.code+"接口测试用例成功"else:result = '创建商铺接口测试用例' + self.code + "接口测试用例失败"# 将接口测试用例的执行结果及数据内容写入对应的测试用例报告中# 写入是第几次测试,测试商铺编号,测试结论txttestReport.write('测试用例编号:'+str(i))txttestReport.write("    创建商铺的编号为:"+self.code)txttestReport.write("    测试用例执行结果:"+result+"\n")txttestReport.write("*****************************************************************" + "\n")#共执行多少条数据txttestReport.write("共执行" + str(i) +"条测试用例"+ "\n")# 获取系统时间,来写入结束时间endtime = datetime.datetime.now()# 时间进行格式化endtime = endtime.strftime("%Y-%m-%d %H:%M:%S")# 时间格式进行格式化txttestReport.write('该接口测试执行结束时间:'+endtime+"\n")txttestReport.close()#连接后台数据库进行ID的检查,并给出测试结论def createhouse_checkCode(self):id='5c7100ce60d044768223daf1546b3b61'sql="SELECT * FROM `config_house` WHERE id ='"+id+"'"dbresult=objdriver.db_connect(sql)print(dbresult)db_code=dbresult[0][1]print(db_code)# #判断是否执行成功if db_code==self.code and self.msg=='新建成功':result="创建商铺列表接口测试通过"print(self.code)else:result="创建商铺列表接口测试失败"print(self.code)return resultif __name__ == '__main__':objdriver = driver_run()token = objdriver.get_token()print(token)# 实例化创建商铺接口类对象objcreatehouse = createhouse_interface()objcreatehouse.createhouse_test(token)# 调用数据库检查点result=objcreatehouse.createhouse_checkCode()# 将测试执行结论放入comresult.txt中objdriver.write_commonresult(result)

4、框架报告+测试用例报告

愿每个测试都能成为测试开发,提高职业技能,成为前1%的存在,为社会创造更大的价值,为公司节约更多的成本,为自己和家庭谋求更高的收入,所有人不受职业年龄限制,越老越吃香,直至财富自由;愿测试技术越来越进步,软件质量进一步得到提高,效率提高。愿祖国更加美好,人民更加幸福。多喜乐,常安宁。

相关文章:

物业系统自主研发接口测试框架

1、自主研发框架整体设计 1.1、什么是测试框架? 在了解什么是自动化测试框架之前,先了解一下什么叫框架?框架是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架…...

手机和电脑通过TCP传输

一.工具 手机端:网络调试精灵 电脑端:野火网络调试助手 在开始通信之前,千万要查看一下电脑的防火墙是否关闭,否则可能会无法通信 在开始通信之前,千万要查看一下电脑的防火墙是否关闭,否则可能会无法通信…...

Git 在commit后,撤销commit

1. 撤销已经add,但是没有commit的问题 git reset HEAD 2. 撤销已经commit,但是没有push到远端的文件(仅撤销commit 保留add操作) 撤销上一次的提交 git reset --soft HEAD^windows 系统使用提示 more,需要多加一个…...

多模态大模型 - MM1

1. 摘要 本文主要通过分析模型结构和数据选择讨论如何构建一个好的多模态大模型(MLLM),并同时提出了MM1模型,包括30B dense版本和64B的MoE版本。 具体贡献: 模型层面:影响效果的重要性排序为:…...

FPGA设计之跨时钟域(CDC)设计篇(2)----如何科学地设计复位信号?

1、复位是干嘛的? 时钟信号和复位信号应该是一个数字系统最重要和最常用的两个信号了。时钟的重要性大家都懂,没有时钟整个系统就无法同步,自然也就谈不上运行了。那么复位(reset)到底是干嘛的? 所有的数字系统在上电的时候都会进行复位,这样才能确保该系统的初始运行状…...

GPS北斗标准时钟同步服务器结构是什么?安徽京准

GPS北斗标准时钟同步服务器结构是什么?安徽京准 GPS北斗标准时钟同步服务器结构是什么?安徽京准 电厂时钟同步系统组成及配置 随着计算机和网络通信技术的飞速发展,火电厂热工自动化系统数字化、网络化的时代已经到来。一方面它为控制和信息系…...

9.5 栅格图层符号化多波段彩色渲染

文章目录 前言多波段彩色渲染QGis设置为多波段彩色二次开发代码实现多波段彩色 总结 前言 介绍栅格图层数据渲染之多波段彩色渲染说明:文章中的示例代码均来自开源项目qgis_cpp_api_apps 多波段彩色渲染 以“3420C_2010_327_RGB_LATLNG.tif”数据为例&#xff0c…...

力扣第九题

回文数 提示: 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 代码展示&#…...

鞭炮插画:成都亚恒丰创教育科技有限公司

鞭炮插画:年味里的绚烂记忆 在岁末年初的温柔时光里,总有一抹色彩,能瞬间唤醒沉睡的年味——那便是鞭炮插画中跃动的红与金,成都亚恒丰创教育科技有限公司 它们不仅仅是纸与墨的交织,更是情感与记忆的桥梁&#xff0c…...

python 循环

循环 while语句 for语句 循环控制语句 break 立即退出循环。 continue 跳过当前循环的剩余部分,并开始下一次迭代。 else for 和 while 循环都可以有一个可选的 else 子句,当循环正常结束时执行。 嵌套 占位符pass pass 是一个空操作语句。当你需要在代…...

映美精黑白相机IFrameQueueBuffer转halcon的HObject

映美精黑白相机&#xff0c;用wpfhalcon开发取图 1.到官网下载&#xff0c;开发包 1sdk 2c开发例子 3c#开发例子 引入TIS.Imaging.ICImagingControl35.dll 3.ICImagingControl使用这个类控制相机 /// <summary> /// 相机控制 /// </summary> public ICImagingC…...

Linux的load(负载)

负载(load)是Linux机器的一个重要指标&#xff0c;直观了反应了机器当前的状态。 在Linux系统中&#xff0c;系统负载是对当前CPU工作量的度量&#xff0c;被定义为特定时间间隔内运行队列中的平均线程数。 Linux的负载高&#xff0c;主要是由于CPU使用、内存使用、10消…...

杜比全景声——空间音频技术

什么是杜比&#xff1f;是否是标清、高清、超清之上的更清晰的格式&#xff1f;杜比全景声 和传统多声道立体声的差别&#xff1f;杜比全景声音频的渲染方式&#xff1f;车载平台上杜比技术的应用&#xff1f; 杜比技术的起源 杜比实验室&#xff08;Dolby Laboratories&…...

C 语言指针进阶

1.0 指针的定义 指针是内存中一个最小单元的编号&#xff08;内存单元的编号称之为地址【地址就是指针指针就是地址】&#xff09;指针通常是用来存放内存地址的一个变量。本质上指针就是地址&#xff1a;口语上说的指针起始是指针变量&#xff0c;指针变量就是一个变量&#…...

SpringBootWeb 篇-入门了解 Swagger 的具体使用

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Swagger 介绍 1.1 Swagger 和 Yapi 的使用场景 2.0 Swagger 的使用方式 2.1 导入 knife4j 的 maven 坐标 2.2 在配置类中加入 knife4j 相关配置 2.3 设置静态资源…...

Python面试题:如何在 Python 中处理大数据集?

在 Python 中处理大数据集可能面临许多挑战&#xff0c;包括内存限制、计算性能和数据处理效率等。以下是一些处理大数据集的常见方法和技术&#xff1a; 1. 使用高效的数据处理库 1.1 Pandas Pandas 是一个强大的数据分析库&#xff0c;可以处理中等大小的数据集&#xff0…...

C++:入门基础

1.命名空间 1.1namespace的价值 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称都将存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c;避免命名冲突或者名字…...

微信小游戏 彩色试管 倒水游戏 逻辑 (二)

最近开始研究微信小游戏&#xff0c;有兴趣的 可以关注一下 公众号&#xff0c; 记录一些心路历程和源代码。 定义一个 Water class 1. **定义接口和枚举**&#xff1a; - WaterInfo 接口定义了水的颜色、高度等信息。 - PourAction 枚举定义了水的倒动状态&#xff0c;…...

【链表】算法题(一) ---- 力扣 / 牛客

一、移除链表元素 移除链表中值为val的元素&#xff0c;并返回新的头节点 思路&#xff1a; 题目上这样说&#xff0c;我们就可以创建一个新的链表&#xff0c;将值不为val的节点&#xff0c;尾插到新的链表当中&#xff0c;最后返回新链表的头节点。 typedef struct ListNo…...

Linux系统之部署盖楼小游戏

Linux系统之部署盖楼小游戏 一、小游戏介绍1.1 小游戏简介1.2 小游戏玩法基本介绍1.3 项目预览二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍2.3 版本要求三、检查本地环境3.1 检查本地操作系统版本3.2 检查系统内核版本四、安装node.js4.1 安装nvm4.2 查看nvm版本4.3 安装…...

“金山-讯飞”杯2024年武汉理工大学程序设计竞赛 A. Mobiusp败走***(思维题-点双连通分量、连通性)

题目 思路来源 官方题解 题解 手玩发现&#xff0c;能换的话&#xff0c;当且仅当.和1在一个环里&#xff0c;而这就是点双连通分量 所以最优策略是先把.换到(x,y)的位置&#xff0c;然后判断.和1在不在一个环里 也就是&#xff1a; 1. 判断删掉1时&#xff0c;.和(x,y)联…...

【机器翻译】基于术语词典干预的机器翻译挑战赛

文章目录 一、赛题链接二、安装库1.spacy2.torch_text 三、数据预处理赛题数据类定义 TranslationDataset批量处理函数 collate_fn 四、编码器和解码器Encoder 类Decoder 类Seq2Seq 类注意事项 五、主函数1. load_terminology_dictionary(dict_file)2. train(model, iterator, …...

推荐系统:从协同过滤到深度学习

目录 一、协同过滤&#xff08;Collaborative Filtering, CF&#xff09;1. 基于用户的协同过滤2. 基于物品的协同过滤 二、深度学习在推荐系统中的应用1. 深度学习模型的优势2. 深度学习在推荐系统中的应用实例 三、总结与展望 推荐系统是现代信息处理和传播中不可或缺的技术&…...

记录些Spring+题集(1)

接口防刷机制 接口被刷指的是同一接口被频繁调用&#xff0c;可能是由于以下原因导致&#xff1a; 恶意攻击&#xff1a;攻击者利用自动化脚本或工具对接口进行大量请求&#xff0c;以消耗系统资源、拖慢系统响应速度或达到其他恶意目的。误操作或程序错误&#xff1a;某些情…...

SpringBoot 解决 getSession().getAttribute() 在负载均衡环境下无法获取session的问题

在Spring Boot中&#xff0c;使用getSession().getAttribute()方法时遇到在负载均衡环境下无法正确获取session属性的问题&#xff0c;通常是由于session属性存储在单个服务器的内存中&#xff0c;而负载均衡会导致用户的请求被分配到不同的服务器上&#xff0c;因此无法找到在…...

Jmeter常用组件及执行顺序

一 常用组件 1.线程组 Thread Group 线程组是一系列线程的集合&#xff0c;每一个线程代表着一个正在使用应用程序的用户。在 jmeter 中&#xff0c;每个线程意味着模拟一个真实用户向服务器发起请求。 在 jmeter 中&#xff0c;线程组组件运行用户设置线程数量、初始化方式等…...

PTrade常见问题系列10

get_ashares获取list为空。 get_Ashares函数目前都是向行情服务器进行获取的 如果请求数过多&#xff0c;应答返回偶现为空现象&#xff0c; 后续版本内进行优化从服务器缓存内取&#xff0c;需求单号&#xff1a;202303213922&#xff0c;于PTradeQT1.0V202202.01.023内发布…...

数据结构(4.4)——求next数组

next数组的作用:当模式串的第j个字符失配时&#xff0c;从模式串的第next[j]的继续往后匹配 求模式串的next数组(手算) next[1] 任何模式串都一样&#xff0c;第一个字符不匹配时&#xff0c;只能匹配下一个子串&#xff0c;因此&#xff0c;往后&#xff0c;next[1]都无脑写…...

《mysql篇》--JDBC编程

JDBC是什么 JDBC就是Java DataBase Connectivity的缩写&#xff0c;翻译过来就很好理解了&#xff0c;就是java连接数据库。所以顾名思义&#xff0c;JDBC就是一种用于执行SQL语句的JavaApl&#xff0c;是Java中的数据库连接规范。为了可以方便的用Java连接各种数据库&#xff…...

android studio 怎么下载 buildTool

在Android Studio中下载Build Tools&#xff0c;通常可以通过Android Studio内置的SDK Manager来完成。以下是详细的步骤&#xff1a; 一、通过Android Studio的SDK Manager下载Build Tools 启动Android Studio&#xff1a;首先&#xff0c;确保你已经安装了Android Studio&am…...