软测八股集
自我介绍
尊敬的面试官您好!我叫xxx,毕业于xxx计算机专业,24年通过校招加入xxx担任测试工程师。
在xxx担任测试工程师期间,我参与APP/WEB双端核心模块功能测试,负责平板、apk、手表、口袋机的测试并执行全流程质量保障。熟悉自动化测试,构建学科诊断和登录以及发布试卷的自动化体系,提升回归效率50%。完成多设备兼容性测试,Monkey稳定性测试72+小时。通过公司缺陷管理系统提交400+有效缺陷(95%确认率),推动缺陷平均解决周期5天内,闭环10+高隐蔽崩溃。主导第三方专项测试百度的AI精准学pro。
在专业技能方面,我具备扎实的软件测试理论基础,熟悉测试流程和测试用例设计方法以及测试总结报告的编写。熟悉使用禅道和JIRA进行缺陷管理和跟踪。
在接口测试方面,我熟练使用Postman和Jmeter进行接口功能测试以及使用JMeter进行性能测试;
熟练MySQL数据库的CRUD操作。在移动端测试方面熟悉adb命令以及使用monkey命令进行冒烟测试和稳定性测试;
在工作中,我注重团队合作,善于从用户角度设计测试用例。
最后,我对自己有清晰的职业规划,愿意不断学习和提升自己,期待能够加入贵公司,与团队一起成长和进步
谢谢!
面试官您好,我是XXX,毕业于XXX学院计算机专业。非常荣幸能获得这次面试机会。
我曾在读书郎担任测试工程师,这段经历锻炼了我跨部门沟通、理解需求和表达能力,也为我打下了扎实的数据处理基础。我深知数据分析在跨境电商运营中的核心作用——无论是商品选品、广告投放优化,还是用户行为分析,都离不开数据的驱动。
在我的工作与项目中,我积累了具体的数据分析实践经验。例如,在一次产品功能测试中,我曾通过Python的Pandas库对用户操作日志进行清洗与分析,提出界面优化建议,最终协助产品团队将用户关键路径完成率提升了5%。
此外,我熟练运用Excel(如sum、VLOOKUP、筛选)进行快速数据处理,了解AI工具应用。英语方面,我具备良好的听说读写能力,可通过无障碍阅读海外电商平台资讯、用户评论及行业报告,持续跟踪市场动态。
我拥有快速的学习能力和强烈的进取心,曾通过短期自学完成实时监控系统的开发。我相信,这种快速吸收新知识、解决新问题的能力,能帮助我迅速适应跨境电商的节奏,为团队带来价值。
我期待能有机会在跨境电商领域发挥我的数据分析能力与学习热情。谢谢!
你为什么想从测试工程师转行做跨境电商运营?
虽然岗位不同,但底层都需要数据驱动决策和解决问题的逻辑。在测试中我用数据定位BUG,在运营中我用数据定位业务增长点。我享受通过分析让事物变得更好的过程,且跨境电商是能将技术、数据和商业结合的热门领域,符合我的兴趣和长远发展。
如何胜任运营(你有什么能力?)
①首先,良好的沟通和协调能力,因为这份工作经常需要与团队内部、供应商或客户沟通,确保信息流畅和问题及时解决。
②其次,数据分析能力,需要能监控销售数据、广告效果和库存水平,从中发现问题并提出优化建议,这需要一定的Excel能力。
③另外,学习能力和适应性,因为跨境电商规则和平台政策经常变化,必须快速掌握新知识并应用到日常工作中。
④同时,细心和责任心,毕竟工作涉及产品上架、订单处理和客户咨询,出小错都可能影响店铺表现。
⑤最后,团队合作精神也不可或缺,因为运营往往需要跨部门协作,共同推动销售目标。
有了解亚马逊平台吗?
我对亚马逊平台有比较系统的了解,并且我认为它是最能体现‘数据驱动’和‘规则驱动’的电商平台之一。我的理解主要分为两个层面:
第一,是它的核心商业模式与运营重心。 我知道亚马逊以“飞轮理论”为核心,极度重视客户体验。这直接决定了运营的终极目标不是单纯卖货,而是通过优化Listing质量、控制差评率、提升物流绩效(如采用FBA) 来获取平台信任,从而赢得更多免费流量。
第二,是它的规则与算法门槛。 我了解到亚马逊有非常严格的平台规则(如严禁刷单、严控侵权)和复杂的A9搜索算法。作为新手,我认为快速学习并严格遵守这些规则是生存底线。同时,我了解到A9算法的核心影响因素——比如关键词匹配、转化率、销量速度和用户停留时间。
亚马逊运营工作内容?
①产品上架和Listing优化。
②监控销售数据和广告情况,统计数据做报表,帮助团队分析趋势和问题,
③客户服务支持,包括回复买家咨询和处理售后问题。
④库存管理,要协助跟踪库存水平,避免缺货或积压,并参与促销活动的准备。
如何优化产品listing?
优化Listing是一个持续的过程,我会从这几个关键点入手:
图片: 确保主图高质、吸睛、符合平台要求,场景图展示使用效果和核心卖点,信息图清晰传达规格和优势。
标题:包含核心关键词、品牌名、关键属性(如尺寸、颜色、数量,适用人群环境),同时保持可读性和吸引力。
Bullet Points: 突出最重要的5个卖点,直击目标客户痛点 ('解决什么问题’),使用符号和加粗(平台允许范围内)。
产品描述:补充细节,讲述品牌故事,增强信任感。
Review&Q&A:积极维护高星评价,及时专业地回复买家问题,消除潜在疑虑。
价格:结合市场定位、成本和竞品定价,考虑促销策略。
A+页面:利用高质量图文和视频进一步提升品牌形象和转化。
我会通过A/B测试(如测试不同主图或Bullet Points顺序)和关注转化率数据来验证优化效果。
对我们公司有什么了解吗?
我一直关注贵公司在[目标市场,如欧美市场]的跨境电商业务,特别欣赏你们在[具体产品类目]领域的深耕和创新策略[如有具体例子更好]。同时,贵公司倡导[提及公司文化或价值观,如数据驱动、快速迭代],这也正是我认同并希望持续发展的方向。我相信加入贵公司能让我在跨境电商领域进一步成长,并为团队目标贡献力量。
我一直关注贵公司在欧美及中东市场的跨境电商业务,特别欣赏你们在运动服饰领域的深耕和创新策略,例如旗下品牌TELALEO通过数据驱动的爆品开发模型,在亚马逊细分市场中持续领跑。同时,贵公司倡导 “数据驱动与供应链整合”的双核理念及“合规运营+品牌出海”的战略,这也正是我认同并希望持续发展的方向。我相信加入贵公司能让我在跨境电商领域进一步成长,并为团队目标贡献力量。
你对TIKTOK这个平台有了解吗?该岗位的工作要求有了解吗?
我对TikTok平台有着比较系统的了解。它的核心是一个以“兴趣电商” 为驱动力的全球性内容生态。我的理解可以从一个核心逻辑和三个关键认知来阐述:
第一,核心逻辑:从“人找货”到“货找人”的范式革命。
这与亚马逊的搜索购物逻辑完全不同。TikTok是通过精准的算法推荐和极具感染力的短视频/直播内容,主动激发用户原本不存在的购物需求。这意味着,运营的成功关键不是优化关键词,而是创造能触发用户“冲动”和“认同”的内容。
第二,对平台生态的认知:内容是流量,信任是货币。
流量逻辑:流量分配完全基于内容互动数据(完播率、点赞、评论、分享)。我理解到,一个视频能否成为“爆款”,取决于它在前3-5秒能否抓住眼球,并在内容中自然融入“看点”(共鸣点、新奇点、价值点)。
信任建立:无论是达人还是店铺自播,成功的基础是与观众建立的真实感和信任感。
第三,对商业模式的认知:闭环与链路。
我关注到TikTok Shop正在全球加速推进,形成了“内容创作(短视频/直播)→ 用户互动 → 即时转化(小黄车)→ 复购与粉丝沉淀”的超短转化闭环。同时,我也了解到TikTok与独立站(如Shopify)的联动。
第四,我的技能与平台需求的连接点:数据驱动的“内容实验”。
这正是我的优势所在。虽然我尚未有直接经验,但我深知,在这个平台,内容本身就是需要被不断测试和优化的“产品”。我可以运用我的数据分析能力:
监测内容数据:分析不同视频的互动率、完播率与转化率的关系。
分析用户画像:通过评论和粉丝数据,理解核心受众,反哺内容创作。
1、协助TikTok账号的内容策划与执行,提升账号活跃
度和影响力;
2. 监控并分析TikTok平台数据,为内容优化提供有效建议;
3. 维护TikTok社区互动,增强粉丝黏性和品牌忠诚度;
4. 与团队协作,确保TikTok营销活动的顺利进行;
为什么选择做销售?
上半年做软件测试,下半年家里有事,如果我想找本专业的工作,重新上手的需要花点时间,之后想了想自己也不是很喜欢这行一直重复性的工作,然后考虑到销售岗初期可以提高自己各方面能力,然后如果自己有能力的话,相信自己是可以赚到钱的。
如何胜任销售工作?
“我理解销售工作需要强大的沟通能力和韧性以及学习能力。虽然我是应届生,但在项目答辩中,我通过自学python、sql、前端框架成功完成了疫情数据可视化实时监控系统,并取得了优秀毕业设计。我相信这种快速学习能力,可以迁移到销售岗位上。
你的职业规划是什么?
我的规划是分三步走:短期我先了解公司具体业务和工作流程并且加强工作技能点,在[产品类目]深耕,比如选品、listing撰写优化、广告基本认知等等,然后向精细化运营方向发展。
你怎么看待加班?
我更倾向于通过提高工作效率来减少不必要的加班,当在任务关键节点或紧急任务时,适当的加班是必要的。我愿意在必要时投入额外时间;
你的优缺点?
优点:快速学习的能力,在学校我都是在自学代码;在不懂问题方面,首先自己百度解决,然后寻求同学和老师的帮助;
缺点:在注重效率时,可能会忘记细节处理,容易被其他人的看法所干扰;
Dear interviewer,
Hello, I’m [Name], and I graduated from [College] with a degree in Computer Science.
I’d like to highlight three things about myself:
First, during my last role was as a Test Engineer at Readboy, I really sharpened my skills in cross-departmental communication and requirement analysis. I’ve developed a strong eye for data and a knack for explaining complex ideas clearly. I’m a fast learner and I take my work very seriously, so I’m confident I can hit the ground running here.
Second, I’m very comfortable with technical tools. I’m proficient in Excel, especially for data analysis using things like VLOOKUP, and I can use Python libraries to crunch numbers and gain insights.
Finally, regarding my English—while I have my CET-4, my actual communication skills go way beyond that. I use HelloTalk daily to practice, so I’m quite fluent in speaking, listening, and writing, and I’m always looking to keep improving.
I’m really eager to combine my tech background with my passion for connecting with people to create real value for your clients here.
Thank you for giving me this opportunity today. I look forward to learning more about the position and how I can add value to your company.
That’s all about me. Thank you for listening.
hometown
I come from Jiangxi Province in southeastern China. It's famous for its beautiful natural scenery, especially Lushan and Wugong Mountain, and Poyang Lake, the largest freshwater lake in China. It also has a rich cultural heritage, being the birthplace of many famous poets and an important center of porcelain production in Jingdezhen, often called the “Porcelain Capital of the World.” Growing up there, I’ve developed a deep appreciation for both tradition and innovation. And I think that the spicy dishes and dowry in my hometown are very famous
advantage
As a tester, I think my biggest strengths are being responsible, easy to talk to, and good at working with others. I always take my tasks seriously and pay close attention to details, which helps me make sure the testing is reliable. At the same time, I’m pretty outgoing and communicative, so I can easily connect with developers, product managers, and teammates. This makes it faster to spot issues and solve them together. I believe these qualities not only help me do my own work well but also make me a good team player
WeChat is basically the most popular social app in China. People use it not only to chat and make video calls, but also to share moments, pay bills, shop online, order food, book taxis, and even do work-related things through WeChat Work. It’s really an all-round app — in China, you can almost live your daily life just with WeChat
At XXX, I worked on testing core features for both APP and WEB platforms. I designed over 300 test cases and ensured full-process quality control. I'm familiar with automation testing and built automated systems for tasks like login and exam publishing, improving regression efficiency by 50%. I reported 400+ valid defects (95% approval rate) using the company’s bug management system and fixed 10+ highly hidden crashes.
功能测试
1、你们公司的功能测试流程
测试工程师拿到《产品需求规格说明书》、《测试计划》、《测试方案》等文档;
首先看需求规格说明书,理解被测软件的大概功能和模块;
看测试计划,找到自己负责的具体模块,熟悉用例级别的评判标准和缺陷提交的等级如何划分后;
参照测试方案,通过Xmind提取测试点,然后去编写测试用例;
执行用例之前,会有一个用例评审;
搭建和配置适合的测试环境;11
手工测功能(UI界面和平板兼容性);用Postman测接口;跑Monkey看稳定性;简单的性能压测;
发现bug,检查看是否能复现,然后提交缺陷到系统,最后描述复现步骤,指派给开发;
开发修复后重新测试确认
编写测试总结报告;项⽬上线后,根据反馈进⾏复盘和总结。
首先我拿到双师一对一需求规格说明书,详细阅读需求规格说明书,然后大致了解双十一对一的每个功能模块
查看测试计划,找到我负责的学科诊断和金牌直播模块,熟悉用例级别和缺陷提交的等级划分后;
参照测试方案,通过Xmind提取学科诊断和金牌直播的测试点,然后使用excel根据对应的测试点去编写测试用例;
在执行用例之前,会有一个用例评审;
然后去安装最新版本的双师1对1,找组长或者同事拿跟双师有关联的最新版的app并安装;
测功能,执行测试用例,同时关注UI界面和平板的兼容性;
发现bug,正常场景:左侧AI数字人说话,右侧显示文字;
诊断过程中,点击下一步,首先会显示正在思考中的字样,然后等待几秒就会显示相应的文字;
但是经过我手势左滑,弹出是否退出诊断的提示窗口,点击继续诊断回到诊断页面,但是等待一分钟以上一直显示正在思考中,
经过多次复现,然后将bug提交到缺陷管理系统,填写apk版本、严重级别和优先级、描述复现步骤、出现次数、机型、上传附件,指派给开发并提交;
开发将此bug修复后,通过企业微信私发给我后,重新验证该问题,验证是否已被修复,开发修改bug状态,显示已解决状态
编写测试总结报告;项目上线后,根据客户反馈,验证问题并提交bug让开发去修复;
自动化测试流程
详细阅读需求规格说明书,理解被测软件的大概功能和模块以及确定自动化测试范围
选择现有的工具和框架;使用xmind的提取测试点,编写测试用例以及开发测试脚本
准备测试数据和搭建测试环境;执行自动化测试,检查allure测试报告的总览页的通过率趋势图和失败用例分布
编写测试总结报告;项目上线后,根据反馈进⾏复盘和总结。
2、app测试和web测试区别
平台差异:
app运行在手机设备;web运行在浏览器
操作系统:
app主要测试ios和Android系统;web主要是测试不同浏览器(chrome、firefox、edge)
网络测试:
app关注网络切换、断网恢复;web关注网络延迟对页面加载的影响
安装与更新:
app需验证安装包兼容性、应用商店审核规则;web无需安装,访问url即可,服务端更新后用户立即生效
设备兼容性:
app要考虑(手机型号、屏幕尺寸、分辨率),web更多是不同浏览器的兼容性
交互与性能:
app则是手势和触摸反馈;web是鼠标和键盘操作
app性能测试考虑内存、CPU占用和电池消耗和冷启动速度;web性能测试主要是页面加载时间和资源优化(减少http请求时间)
安全性与权限管理:
app测试动态权限申请(ios隐私标签,Android运行时权限);web测试防御Web攻击(sql注入)和Cookie安全性
自动化测试工具差异:
app测试appium,需模拟真机环境(adb)或云测平台;web测试Selenium,依赖浏览器驱动和DOM元素操作
3、测试用例的组成,重点关注什么?
用例编号、用例标题、功能模块、重要级别、前置条件、测试步骤、预期结果、实际结果
应重点关注以下内容:
覆盖全面:确保测试用例覆盖所有功能点和边界条件。
清晰明确:步骤和预期结果应清晰、无歧义。
可重复性:测试用例应能在不同环境下重复执行并得到一致结果。
可维护性:测试用例应易于更新和维护,以适应需求变化。
4、缺陷报告流程
5、如果一个缺陷被提交后,开发人员认为不是问题,怎么处理?
1. 首先,将问题提交到缺陷管理系统,并打印日志和上传视频或截图
2. 对开发的理由进⾏校验,校验依据
a. 参照需求⽂档(如果没有文档依据,可以根据类似软件的一般特性来说明是否存在不一致的地方)
b. 与设计人员、开发人员和产品经理进⾏沟通确认
3. 校验结果不是bug,关闭bug,如果是bug提交给开发进⾏处理,确保产品质量
6、测试报告组成?测试的目的?重点关注什么?
1、测试概述
项目背景
测试目标:验证
2、测试范围
3、测试环境
硬件配置:设备
软件配置:工具
4、测试人员
4、测试执行详情
测试过程描述
测试执行统计
测试类型 用例数 执行数 通过率 失败原因TOP3
功能测试 150 150 96.7% 崩溃
兼容性测试 30 30 100% -
稳定性测试 20 20 95% 内存泄漏
总计 200 200 97%
5、缺陷分析
缺陷分布统计饼图
重点缺陷解决情况
未关闭缺陷
6、测试结论与建议
编写测试报告的目的是为了记录测试过程和结果,评估版本质量,并为后续的开发和测试提供参考。
应该重点关注的内容包括:
测试的覆盖范围是否全面。
缺陷的严重程度和修复情况。
测试结果的准确性和可靠性。
结论和建议的实用性和可操作性。
7、提交bug组成?需要注意什么?
Bug标题:简洁明了地描述问题。
Bug描述:详细描述问题的现象、步骤和预期结果。
重现步骤:清晰地列出重现Bug的步骤。
环境信息:包括操作系统、浏览器版本、设备型号等。
优先级和严重程度:评估Bug的影响和紧急程度。
附件:如截图、日志文件等,帮助开发人员理解问题。
8、做好测试需要具备哪些技能
熟悉软件测试基本概念、掌握测试生命周期
良好的文档编写能力、熟练用例设计方法
熟悉Windows/Linux常用命令
了解HTTP协议、TCP/IP模型
熟悉使用selenium、postman、jmeter工具,会写自动化脚本、熟悉数据库查询、抓包工具以及移动端专项测试(熟悉ADB命令、Monkey测试、兼容性测试)
做好测试一定要细心耐心和良好的沟通能力,在工作中,有问题及时和团队沟通,注重团队合作
持续学习新的测试技术,解决问题的能力
9、对于不可复现的bug
1、首先打印日志;思考刚才测试过程有什么差异的地方(测试步骤,测试账号、测试网络、测试环境)
2、尝试多次测试复现(换同事的设备或者环境进行复现),可以借助于抓包工具、借助数据库
3、如果此时问题比较严重,找开发协助复现(高级测试人员、开发人员)
4、如果在当前版本无法成功复现,可以在下一次版本迭代时再次复现,如果复现成功直接将日志私发给开发
5、更新系统然后在尝试复现测试,暂时放弃(可以在后续版本再次验证);如果后续版本出现了,此时直接提交bug(开发人员有相关的调试日志了)
10、如何提高测试用例的覆盖率,减少漏测?
1、首先详细阅读需求文档,确保覆盖所有功能点,使用Xmind提取测试点,同时,也要关注隐含需求
2、可以采用等价类划分、边界值分析、场景等方法来设计测试用例
3、在执行用例之前,公司会召开用例评审会;
11、整个测试流程当中最关键的是什么?
精准的需求分析,可以大幅降低后期成本
清晰的测试目标和策略,可以确保团队目标一致,资源合理分配
core:设计高质量的测试用例,能确保测试全面有效,及时发现问题
有效的缺陷管理与根因分析 推动问题解决和预防
12、开发和测试的区别?
开发负责编写代码实现功能模块;测试负责检查程序缺陷并确保整体质量;
开发深入技术细节和需求实现,测试更侧重用户视角和兼容性
13、多久做一次版本迭代?
一般分为大版本和小版本;
小版本每周都会有迭代;主要是历史功能的优化和缺陷的修复;
大版本2-3个月一次;主要是产品规划的新功能和新业务
14、当项目测试阶段无问题但用户环境中出现 Bug 时,如何解决?
1、获取用户设备型号/OS版本,网络环境,操作录像,关键日志
2、自己再去按照用户操作录像进行复现;考虑用户环境真实场景:用户可能使用的旧机型,不是纯净系统,非常规操作
3、然后针对旧机型、非纯净系统和非常规操作设计测试用例,执行测试用例
15、项目马上上线了,突然发现一个bug?
如果项目马上要上线了发现了bug,我会先确认并复现,把复现步骤、环境、日志、截图/录屏记录清楚;
然后迅速评估严重性:若影响核心流程,并告知开发立即修复
拿双师1对1为例 当时项目在第二天就要上线,但是在测试最后一版发现一个bug,然后我先确认并复现,然后把复现步骤、环境、日志以及录屏记录清楚;然后迅速评估严重性,发现该bug严重级别为超严重,因为该bug出现会导致后续的操作无法正常进行,则先将bug提交到缺陷管理系统,然后通过企业微信将bug链接发送给开发,让开发立即修复;
16、app和web端有相同的功能,你是如何开展工作的?
从设计用例开始,案例是同一套。
如果用react框架,在安卓端测一遍然后其他端测兼容就行了。
如果是分开写的,那肯定就是每一端都要测,然后繁复的工作用自动化代替.
17、不通知你bug状态,你怎么去维护你的bug?
早上来上班,快速浏览我的bug列表的bug状态,验证已修复的bug,更新状态;
检查“待确认”和“已分配”的bug,对于长时间无进展的bug,通过企业微信提醒开发;
定期进行bug汇总
18、你已经有测试任务,然后还要去验证已修复的bug,如何去完成?
首先确认两者的优先级;
明确哪些是今天必须完成和应该完成的;
先处理高优先级的新功能测试,除非有很急的验证,要不然会先进行新功能测试,
然后去批量处理bug的验证,按照优先级的顺序一个一个验证
接口
接口测试用例组成部分
多出:接口名称、请求方法、请求URL和请求头
接口用例设计的方法
1、单接口测试
正向测试:
必选p0;必选+非必选组合p2;全部参数p1
反向测试:
功能异常(数据类型正确,不能正确结果)p1;
数据异常(数据类型不正确:空、特殊字符、字母、下划线、长度 【等价类、边界值测试法】);
参数异常(多参,少参,无参,错误参);
2、业务场景测试
必须在单接口测试完成之后
从用户角度设计,用较少的用例,覆盖更多的接口
一般只需要设计业务场景的正向测试即可
设计登录单接口的测试点
- 正向:
- 登录成功
- 反向:
- 手机号未注册
- 密码错误
- 手机号为空
- 手机号有特殊字符、字母
- 10位手机号
- 12位手机号
- 密码为空
- 密码特殊字符、字母
- 1位密码
- 100位密码
- 多参:
- 少参:
- 无参:
- 错误参数:
postman常用断言
断言响应状态码
断言包含某字符串
断言JSON数据
**Response body:JSON value check**
pm.test("断言json结果中指定key的值", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.value).to.eql(100);
});
pm:postman的一个实例
test(): postman的方法。有两个参数。
参1:断言完成后,给用户的提示性文字信息。可以任意修改(不参与断言)
参2:是一个 匿名函数 调用。
var jsonData = pm.response.json();
var 是 js 语言中,定义变量的关键字。
jsonData 是变量名
pm.response.json() 表示 postman的 json响应结果
代表:
{
"success": true,
"code": 10000,
"message": "操作成功!",
"data": "46b1fcde-e996-4520-b8f6-a2cd2da95350"
}
pm.expect(jsonData.value).to.eql(100);
value 指代 json数据中的 “key” (举例:可以取值:success 或 code 或 message 或 data)
100,应该替换为 key 所对应的 value (预期结果)
postman关联
比如我要验证AI智习室的查询题库接口;
1、首先发起登录接口的post请求,从cookie中拿到sessionid的值
2、在测试环境中将创建sessionid的环境变量
3、在查询题库接口的Header中通过{{变量名}}引用该变量
简介
- 关联,是postman中,用来解决 http请求之间有依赖关系时,使用的一种技术。
- 依赖:1个http请求响应结果中的 数据,被另一个 http请求使用。
- 举例:
- 登录 http请求,返回的 令牌。 被 添加员工 请求 依赖(请求头中使用)。 可以使用 postman的关联技术来使用。
实现步骤
A接口响应结果,被B接口依赖:
- 发送 A接口请求,得到响应结果
- 将结果中关联数据,存入 公共容器(全局变量、环境变量)
- B接口,从 公共容器中提取数据,发送 B接口请求。

核心代码
-
获取响应结果 var jsonData = pm.response.json();
-
将数据设置到 全局、环境变量中。
-
全局变量:pm.globals.set(“全局变量名”, 全局变量值)
-
全局变量,在整个 postman 随处都能使用。
// 示例 pm.globals.set("glb_age", 22) -
环境变量:pm.environment.set(“环境变量名”, 环境变量值)
-
在 特定的环境下,才能使用。因此,必须先创建环境,再创建 环境变量。
// 示例 pm.environment.set("env_age", 88)
-
-
在 请求参数(URL、请求头、请求体)中 获取 变量数据 {{全局变量名}} 或者 {{环境变量名}}
{{glb_age}} 或 {{env_age}}
创建环境
直接创建environments-》然后在某个环境创建环境变量
postman参数化
以AI智习室登录接口的参数化为例
1、准备csv的数据文件
2、进入 Collection Runner,在Runner页面点击 Select File,上传CSV文件,预览数据确认格式是否正确
3、在请求体中通过 {{变量名}} 引用数据文件字段,在请求的 Scripts 标签页中,使用data.csv的字段名 验证返回结果
4、点击run执行参数化测试,所有行执行完毕后,检查runner生成的测试报告

读取数据文件数据
理论
根据 使用位置 不同,有两种方法。
-
第一种:请求参数(URL、请求头、请求体)中,使用 数据文件中 的数据
- 使用 {{}} 包裹 csv文件第一行的字段名。或 json文件的 key名
-
第二种:代码(Tests)中,使用 数据文件中 的数据
- 使用 postman 内置 关键字 data.csv文件的字段名 或 data.json文件的key名
![接口区分数据来源]()
postman使用console
左上角的三条杠-》view-》show postman console
requests
设置http请求语法
resp = requests.请求方法(url='URL地址', params={k:v}, headers={k:v},
data={k:v}, json={k:v}, cookies='cookie数据'(如:令牌))
请求方法:
get请求 - get方法
post请求 - post方法
put请求 - put方法
delete请求 - delete方法
url:要访问的地址 - string类型
params:查询参数 - 字典
headers:请求头 - 字典
data:表单格式请求体数据 - 字典 - tpshop商城项目
json:json格式请求体数据 - 字典 - ihrm项目
cookies:用来传递cookies
resp:代表响应结果。
cookie
# 导包
import requests
# 发送 获取验证码请求 - get
resp = requests.get(url="http://tpshop-test.itheima.net/index.php?m=Home&c=User&a=verify&r=0.8163589828918973")
# 获取 cookie
my_cookie = resp.cookies
# 发送 登录请求 - post,要携带获取到的 cookie, 获取响应结果
resp2 = requests.post(url="http://tpshop-test.itheima.net/index.php?m=Home&c=User&a=do_login&t=0.06754297110809726",
data={"username": "13812345678", "password": "123456", "verify_code": "8888"},
cookies=my_cookie)
# 打印响应结果
print("登录结果:", resp2.json())
# 发送请求,访问 "我的订单" 页面
resp3 = requests.get(url="http://tpshop-test.itheima.net/Home/Order/order_list.html",
cookies=my_cookie)
print("我的订单页面:", resp3.text)
session
Session自动管理Cookie 因为,cookie中的数据,都是由 session 提供的。
requests时无法转成json数据

测试报告newman

pytest
执行测试方法
单文件执行(了解)
方法1:终端命令 pytest -s xxx.py。
方法2:方法定义后,右键->运行 此方法。类定义后,右键->运行 所有方法。
方法3:导包 import pytest
if __name__ == '__main__':
pytest.main(['-s', 'xxx.py'])
多文件执行【重点】
1. 直接在项目目录下,创建文件 pytest.ini
2. 编写 pytest.ini 文件
[pytest] 固定内容
addopts = -s 添加命令行参数 add options
testpaths = ./xxx .py 测试用例文件,相对于 pytest.ini 位置
python_files = xxx*.py .py 文件名。 可用 通配符
python_classes = Test* 测试类名。 可用 通配符
python_functions = test* 测试方法名。 可用 通配符
3. 终端执行命令 pytest
Fixture
Fixture 是 pytest 用于提供测试所需依赖、准备测试环境以及清理测试环境的机制。它使用 @pytest.fixture 装饰器定义。
# 1.方法级别方法
def setup(self): 在 每个 普通测试方法执行之前,自动被调用一次。
def teardown(self): 在 每个 普通测试方法执行之后,自动被调用一次。
# 2.类级别方法
def setup_class(self): 在 类中所有 测试方法执行之前,自动被调用一次。
def teardown_class(self): 在 类中所有 测试方法执行结束之后,自动被调用一次。
断言
# 方法1:
assert 预期结果 == 实际结果 ———— 断言相等
# 方法2:
assert 预期结果 in 实际结果 ———— 断言包含
参数化
参数化的核心:数据驱动(用数据驱动测试用例执行)
- 数据驱动:针对一个接口,只写一个测试方法。用一份测试数据文件,管理各个测试用例的测试数据。
- 如:登录接口,共 15 条测试用例。但,只需要一个 测试方法,对应 有 15 组数据的 json数据文件,进行测试。
实现步骤(如何用 pytest 实现接口自动化中的数据驱动?)
拿AI自习室的登录接口为例;
1. 将准备的30条登录数据,按 [{},{},{}] 格式 组织到 json文件中。
2. 读取json文件,将数据转换为 [(),(),()]
3. 在通用测试方法上一行,添加 @pytest.mark.parameterize()
4. 给 parameterize() 传参。参1:字符串类型,内容为 json文件中一组数据的 key(phone、password、status_code、code等键)。参2:[(),(),()]每组键的值 格式数据。
5. 给通用测试方法添加形参,与parameterize() 参1 字符串的内容一致。
6. 测试方法内部直接使用形参驱动请求和断言。
优势:只需增改 JSON 数据,无需改动代码,极大提升维护性
从json文件读取
# 将测试数据 组织到 json文件中
[
{"x": 10, "y": 20, "expect": 30},
{"x": 100, "y": 200, "expect": 300},
{"x": 1000, "y": 2000, "expect": 3000}
]
--------------------------------------------------------------
import pytest
import json
# 待测 函数
def add(x, y):
return x + y
# 封装函数,读取json文件,将 [{},{},{}] 数据 转换为 [(),(),()] 格式的数据
def read_json_data(filename):
with open(filename, "r", encoding="utf8") as f:
json_data = json.load(f)
data_list = []
for data in json_data:
val = data.values()
tmp = tuple(val)
data_list.append(tmp)
# 必须返回,不能在 for 内
return data_list # 返回 [(10, 20, 30), (100, 200, 300), (1000, 2000, 3000)]
# 结合 pytest 定义测试类
class TestAddFunc(object):
@pytest.mark.parametrize("x, y, expect", read_json_data("add_data.json")) # 参2 要求必须是 [(),(),()] 格式的数据
def test_add(self, x, y, expect): # 通用测试方法
res = add(x, y) # 调用 待测函数,得实际结果
assert expect == res # 断言
测试报告
1. 安装插件 pip install pytest-html
2. 修改 pytest.ini 文件的 addopts 的值
addopts = -s --html=report/测试报告名.html --self-contained-html
3. 使用命令 pytest 生成测试报告
pytest 和 unittest 等框架相比,主要优势是什么?
语法简洁:使用简单的 assert 语句即可,不像 unittest 需要记住各种 self.assert* 方法。
Fixture 机制:提供了比 unittest 的 setUp/tearDown 更灵活、更可复用的测试准备和清理机制。
丰富的插件生态:pytest-xdist, pytest-cov, pytest-html
参数化支持:内置的 @pytest.mark.parametrize 装饰器使得数据驱动测试非常简单
过滤和执行:可以轻松地通过文件名、类名、函数名、marker 来选择性运行测试
报告清晰:输出报告信息更详细、易读。
conftest.py 文件是做什么的?
conftest.py 是一个特殊的文件,用于存放被多个测试文件共享的 fixture。
pytest 会自动发现该文件,其中的 fixture 不需要导入,可以被同一目录及子目录下的所有测试文件直接使用。
Allure
接口自动化
接口对象封装
核心思想:代码分层
- 分层思想:
- 按代码功能,划分为 接口对象层、测试脚本层
- 接口对象层:
- 负责 发送 http请求,访问待测接口。返回响应数据。
- 测试用例层(测试脚本层):
- 调用 接口,按响应数据,断言完成测试。
封装Tpshop商城
登录接口对象层
封装思想:
- 将 普通方式实现代码中,固定不变的,直接写到方法的实现内部。
- 将动态变化的,从参数传入。
- 将响应结果,通过返回值 return
分析:

import requests
# 封装 tpshop 商城 接口对象层
class TpshopLoginApi(object):
# 获取验证码
@classmethod
def get_verify(cls, session):
session.get(url="http://tpshop-test.itheima.net/index.php?m=Home&c=User&a=verify")
# 登录
@classmethod
def login(cls, session, login_data):
resp = session.post(url="http://tpshop-test.itheima.net/index.php?m=Home&c=User&a=do_login",
data=login_data)
return resp
# 测试,自己封装的接口,功能是否正常!
if __name__ == '__main__':
session = requests.Session()
# 发送获取验证码请求
TpshopLoginApi.get_verify(session)
login_data = {"username": "13812345678", "password": "123456", "verify_code": "8888"}
# 发送登录请求
response = TpshopLoginApi.login(session, login_data)
print("登录结果:", response.json())
登录接口测试用例层
使用 接口测试框架 pytest 调用自己封装的 Api,发送请求,获取响应结果,断言。完成接口测试!
import requests
from py02_tpshop_api import TpshopLoginApi
class TestTpshopLogin(object):
# 定义为类属性。 使用时,类属性 可以用 类名、实例、self、cls 均可以引用
session = None
def setup(self):
# 创建 session 实例
self.session = requests.Session()
# 调用自己封装的API,发送 获取验证码 请求
TpshopLoginApi.get_verify(self.session)
# 定义 测试方法 - 登录成功
def test01_login_success(self):
# 准备 请求体数据
req_data = {"username": "13812345678", "password": "123456", "verify_code": "8888"}
# 调用自己封装的API,发送 登录 请求
resp = TpshopLoginApi.login(self.session, req_data)
# 打印响应结果
print("登录成功:", resp.json())
# 断言
assert 200 == resp.status_code
assert 1 == resp.json().get("status")
assert "登陆成功" in resp.json().get("msg")
# 定义 测试方法 - 密码错误
def test02_pwd_err(self):
# 准备 请求体数据
req_data = {"username": "13812345678", "password": "12345689", "verify_code": "8888"}
# 调用自己封装的API,发送 登录 请求
resp = TpshopLoginApi.login(self.session, req_data)
# 打印响应结果
print("密码错误:", resp.json())
# 断言
assert 200 == resp.status_code
assert -2 == resp.json().get("status")
assert "密码错误" in resp.json().get("msg")
# 定义 测试方法 - 验证码错误
def test03_verify_err(self):
# 准备 请求体数据
req_data = {"username": "13812345678", "password": "123456", "verify_code": "8976"}
# 调用自己封装的API,发送 登录 请求
resp = TpshopLoginApi.login(self.session, req_data)
# 打印响应结果
print("验证码错误:", resp.json())
# 断言
assert 200 == resp.status_code
assert 0 == resp.json().get("status")
assert "验证码错误" in resp.json().get("msg")
目录结构
- api/:接口对象层(代码:python package)
- scripts/:测试脚本层(代码:python package)
- common/:通用工具方法、函数(代码:python package)
- data/:测试数据文件(文件:dir)
- report/:测试报告(文件:dir)
- config.py: 项目中的 配置信息。(全局变量)
- pytest.ini: pytest 配置
xxx接口参数化
组织数据文件
读取数据文件
- 在 common/ 下创建 文件 read_json_file.py
- 在 文件内,创建 函数,读取json文件中的数据,转换成 [(),(),()] 格式数据
- 测试此函数功能通过
parameterize参数化
- 在 通用测试方法上一行,添加 @pytest.mark.parameterize()
- 给 parameterize()添加参数。参1:一个字符串,内容为json文件中,一组测试数据的键。参2:[(),(),()]格式数据。
- 给 通用测试方法,添加形参。参数与 parameterize()的 参1 保持一致。
- 修改 通用测试方法 内部实现,使用 形参。
日志
日志的级别
- logging.DEBUG:调试级别【高】
- logging.INFO:信息级别【次高】
- logging.WARNING:警告级别【中】
- logging.ERROR:错误级别【低】
- logging.CRITICAL:严重错误级别【极低】
特性:
- 日志级别设定后,只有比该级别 低 的日志会打印。
- 如:设定日志级别为 info。 debug 级别的日志信息,不会打印。warning、error、critical 会打印
日志代码实现分析
日志代码,无需手写实现。会修改、调用即可!

jenkins
Jmeter
元件的执行顺序
相同的元件按顺序执行
不同的元件按以下顺序执行
1. 配置元件(config elements)
2. 前置处理程序(Per-processors)
3. 定时器(timers)
4. 取样器(Sampler)
5. 后置处理程序(Post-processors)
6. 断言(Assertions)
7. 监听器(Listeners)
jmeter如何进行接口测试
操作步骤:
2. 在‘测试计划’下添加‘线程组’
3. 在‘线程组’下添加‘HTTP请求’取样器
4. 填写‘HTTP请求’的相关请求数据
5. 在‘线程组’下添加‘察看结果树’监听器
6. 点击‘启动’按钮运行,并在“察看结果树”中查看测试结果
jmeter的主要组件有哪些?
测试计划、线程组、配置元件、前置处理器、定时器、取样器、后置处理器、断言、监听器
线程组
线程数:虚拟用户数
Ramp-Up时间(秒):启动全部虚拟用户数所需要的时间
循环次数:指定次数或勾选永远
延迟创建线程直到需要:测试开始的时候,所有线程就被创建完。勾选了此选项,那么线程只会在合适的需要用到的时候创建.
调度器配置
持续时间(秒):设置脚本压测持续时间
启动延迟(秒):启动延迟时间
jmeter如何进行参数化
以AI智习室的登录接口参数化为例
1、在测试计划下,找到配置元件,点击CSV Data Set Config
2、准备CSV的测试数据(创建包含50组账号的csv文件)
3、在CSV Data Set Config中,根据CSV文件的字段名定义变量名username
4、通过${username}的形式引用CSV文件中的值,在测试过程中循环读取CSV文件中的值,并依次替换变量。
参数化格式:${参数名}
1. JMeter参数化常用方式
用户定义的变量
用户参数
CSV Data Set Config
函数
2. 用户定义的变量
添加方式:测试计划 --> 线程组--> 配置元件 --> 用户定义的变量
3. 用户参数
添加方式:测试计划 --> 线程组--> 前置处理器 --> 用户参数
4. CSV 数据文件设置
添加方式:测试计划 --> 线程组--> 配置元件 --> CSV 数据文件设置
参数详解(CSV 数据文件设置):
变量名称:多个变量时,使用英文逗号分隔
忽略首行:True为忽略,False为不忽略,默认值:False
遇到文件结束符再次循环:当读取文件到结尾时,是否再从头读取文件,False=当读取文件到结尾时,停止读取文件
遇到文件结束符停止线程:当“遇到文件结束符再次循环”一项为False时起效;True:当读取文件到结尾时,停止进程
5. 函数(__counter)
计数函数,一般做执行次数统计使用;
位置:在菜单中选择--> 选项 --> 函数助手对话框
JMeter断言
添加方式:测试计划 --> 线程组--> HTTP请求 --> (右键添加) 断言 --> 响应断言
响应断言
JSON断言
大小断言
JMeter关联
添加方式:测试计划 --> 线程组--> HTTP请求 --> (右键添加) 后置处理器 --> 正则表达式提取器
1、正则表达式提取器
参数设置(正则表达式提取器):
引用名称:下一个请求要引用的参数名称,如填写title,则可用${title}引用它
正则表达式
():括起来的部分就是要提取的。
.:匹配任何字符串。
+:一次或多次。
?:不要太贪婪,在找到第一个匹配项后停止。
模板:用$$引用起来,如果在正则表达式中有多个正则表达式,则可以是$2$$3$等等,表示解析到的第几个值给title。如:
$1$表示解析到的第1个值
匹配数字:0代表随机取值,-1代表全部取值,1代表取第一个值
2、XPath提取器
XPath Query:用于提取值的XPath表达式
3、JSON提取器
参数设置:
Names of created variables:存放提取出的值的参数
JSON Path Expressions:JSON路径表达式($.(代表整个json数据))
跨线程组关联
当有依赖关系的两个请求(一个请求的入参是另一个请求返回的数据),放入到不同的线程组中时,就不能使用提取器保存的变量来传递参数值,而是要使用Jmeter属性来传递;
想让线程组之间按顺序执行:勾选测试计划-》独立运行每个线程组
函数实现:
1. __setProperty函数:将值保存成jmeter属性
2. __property函数:在其他线程组中使用property函数读取属性
备注:setProperty函数需要通过BeanShell取样器来执行(BeanShell取样器作用:执行函数和java脚本)
Jmeter直连数据库
准备工作: 启动数据库
加载mysql的JDBC驱动
方法1:在测试计划下方的位置,点击浏览添加JDBC的jar包
方法2:将JDBC的jar拷贝到lib目录,并重启jmeter
配置JDBC连接池的参数(JDBC Pool Configuration)
1、添加JDBC Request请求
JDBC连接池名称:必须与“JDBC连接池”中的连接名一致
要执行的sql语句
Variable Name中:写明要保存的数据的参数名
逻辑控制器
控制jmeter脚本的执行顺序(它的子集是请求)
如果(if)控制器:
第一种配置方法:
函数助手选择__jex13(函数内书写格式:"${name}" == "itcast")
第二种配置方法:
勾选上Interpret Condition as Variable Expression,判断条件需用使用__jexl3函数。
(使用这个函数来进行判定时,Jmeter自身的执行效果要高一些)
循环控制器:
控制子节点下的HTTP请求的执行次数
循环控制器与线程组中的循环次数的对比:
循环控制器只控制其子节点下的HTTP请求,线程组对所有的请求都有效
假如线程组循环次数为2,循环控制器次数为3,则循环控制器下的请求执行次数为:2*3
ForEach控制器:
与用户定义的变量或者正则表达式提取器配合使用,循环读取用户定义的变量或者正则表达式结果中的所有数据。
配置参数:
与用户定义的变量配合使用:
1、测试计划下添加用户定义的变量:
参数名:固定前缀 + 连续的数字后缀(key_1)
2、添加ForEach控制,并配置
3、在ForEach控制器下方添加HTTP请求,并引用ForEach读取的数${hey}
与正则表达式配合使用:
1、添加HTTP请求——itcast首页
2、添加正则表达式提取器,提取出itcast响应中所有的地址相关的数据,并保存为参数area(列表数据)
3、添加ForEach控制器,循环提取area列表中的每一个地址信息city
4、在ForEach控制器下添加一个HTTP请求——百度,引用ForEach控制器中定义的变量${city},作为参数
Jmeter如何实现事务监控?
在测试计划中,右键点击线程组,选择“添加”->“逻辑控制器”->“事务控制器”。
将需要监控的请求拖放到事务控制器下
事务控制器会自动记录事务的开始和结束时间,并计算整个事务的响应时间。
通过监听器(如“聚合报告”)可以查看事务的吞吐量和响应时间
定时器
它是请求的子集
没有特殊说明,TPS(吞吐量)就是QPS
同步定时器:同步定时器会暂缓请求发送,一直到积攒的请求数达到
要的数量时,将所有的请求同步发送出去,形成绝对的并发(更大的压力负载)
常数吞吐量定时器:设置Jmeter以指定的吞吐量速度往服务器发送HTTP请求。常数吞吐量定时器只是帮忙达到性能测试的负载(压力)要求,本身不代表性能有bug/无bug,对于bug的分析需要通过响应时间来判断
固定定时器
如何使用JMeter进行压力测试?
在线程组,可以通过增加线程数和循环次数来增加负载
分布式
JMeter如何实现分布式测试
准备一台控制机和两台执行机
1、在执行机一安装Jmeter,编辑bin目录下的配置文件,禁用SSL和修改端口号,保存文件并启动执行机服务jmeter-server.bat
2、在执行机二上重复上述安装和配置步骤,(确保两台执行机的JMeter版本一致)
3、在控制机上安装JMeter,编辑配置文件,添加执行机的IP地址和禁用SSL并保存文件
4、创建测试计划,添加线程组和HTTP请求,添加聚合报告
Jmeter报告
聚合报告

HTML报告

TPS算法

UI自动化
如何搭建自动化测试环境
准备测试工具、测试第三方依赖;
新建项目包含:py文件(工具类(驱动方法) config.py(DIR_PATH = os.path.dirname(__file__)) 文件夹(data log report img)
py包(base(公共方法) page(一个测试用例所涉及的操作页面(一个page对应的操作步骤)(结果不算)) script)pytest.ini(pytest的配置文件)
如何批量运行测试用例(一条/多条(一次打开/关闭))
批量运行:
1、每条测试用例运行到类级别的销毁方法时,quit_admin_driver,让条件不成立
2、运行到最后一条测试用例完毕之后,要再次主动调用quit_admin_driver的方法而且需要让其成功关闭
3、对于用例的运行做排序
opytest插件:pytest-ordering
排序
@pytest.mark.run(order=1)
class TestBegin:
@pytest.mark.run(order=2)
class TestLogin:
order的值约小优先级越高(仅限于正整数)
用我之前做过的案例来说,我把关闭浏览器的方法写在了utils中,再该文件定义了__key的私有属性默认true,
用于判断是否要关闭浏览器,然后在script包下加了begin和end的py文件,
然后安装pytest-ordering插件,给这些测试用例进行排序,
命令行执行时,主动调用begin改为false,执行最后一条测试用例调用end改为true,关闭浏览器
1.什么是Selenium WebDriver?
Selenium WebDriver 是一个用于自动化浏览器操作的强大工具。它可以模拟用户在浏览器中的各种操作,如点击、输入文本等,并且能够与多种编程语言(包括 Python)结合使用。WebDriver 直接与浏览器进行通信,控制浏览器的行为,从而实现自动化测试。
2.WebDriver、Selenium 和浏览器之间的协同工作流程?
初始化 webdriver.Chrome(),启动 chromedriver 和 Chrome 浏览器。
driver.get("https://www.example.com") 通过 WebDriver 发送命令,chromedriver 将命令转换为浏览器指令,浏览器加载网页。
find_element_by_name("q") 查找页面元素,send_keys("Selenium") 在输入框中输入文本。
submit() 提交表单,浏览器执行表单提交操作。
driver.quit() 关闭浏览器。
3.用selenium操控页面时,在浏览器的输入框中输入字符串运行,运行之后想再次运行,但此时运行结果报错:已输入内容。此时如何处理
1、在输入新内容之前,先清除输入框中已有的内容。可以使用 clear() 方法。
2、如果 clear() 方法无效,可以使用 JavaScript 直接操作 DOM 清除输入框内容。
driver.execute_script("arguments[0].value = '';", input_box)
3、处理动态内容:使用显式等待确保输入框加载完成。
4、execute_script()
# 滑动到页面最底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 滑动到页面顶部
driver.execute_script("window.scrollTo(0, 0);")
# 滑动到指定元素位置
element = driver.find_element(By.ID, "element_id")
driver.execute_script("arguments[0].scrollIntoView();", element)
# 滚动到最右侧
driver.execute_script("window.scrollTo(document.body.scrollWidth, 0);")
5.一个元素明明定位到了,点击无效(也没报错),如何解决?
使用js点击,selenium有时候点击元素是会失效
6. selenium中隐藏元素如何定位?
# 让隐藏元素变为可见(操作后恢复原状态)
driver.execute_script("arguments[0].style.display = 'block';", hidden_element)
hidden_element.click() # 正常操作
driver.execute_script("arguments[0].style.display = 'none';", hidden_element) # 恢复隐藏
7. 如何选中下拉列表中的下拉选项?
- 通过选项的顺序,第一个为0 select_by_index(index)
- 通过value属性 select_by_value(value)
- 通过选项可见文本 select_by_visible_text(text)
8. Selenium中如何保证操作元素的成功率或者稳定性?
减少操作步骤;
合理的使用等待操作;
使用不同方式进行定位如id/name/class/xpath/css selector
减少用例之间相互影响,所以设计用例时,尽量降低用例的耦合度
多用try捕捉处理异常
针对一些不稳定的动态控件经过JS实现操作
框架中使用用例失败重试,提升测试用例成功率
9.什么是PO模式
PO是一种设计模式,实现脚本的Page类和操作的页面一一对应起来
10. PO的优点
业务代码和测试脚本分离;
每一个页面对应一个页面类;
页面类主要包括该页面的元素定位,和这些元素相关的业务操作代码封装的方法;
代码复用;层次清晰
11. 你的自动化用例的执行策略是什么?
线上监控自动化脚本,使用Jenkins定时执行,可能设置为10分钟执行一次,这种每次执行用例数不会太多,一般都是核心流程;
回归测试用例,这种一般在上线之后进行执行,这种一般手动触发执行,也是在Jenkins新建一个任务,手动build
12. 自动化测试的优缺点是什么?
优点:减少回归测试成本,释放人力资源;提高测试效率和测试覆盖率;支持批量数据等手工难实现的场景,可执行繁琐用例;
缺点:
初期投资高(工具、脚本开发,维护成本随需求变更增加)
出现脚本逻辑或数据问题;
依赖特定测试环境;
13. 如何去定位动态变化的元素?
| 动态元素类型 | 解决方案 |
|---|---|
| 属性动态变化 | 1. XPath轴(parent/following-sibling) 2. 部分匹配(contains/starts-with) 3. find_elements遍历 |
| 动态加载元素 | 1. WebDriverWait 显式等待 2. 触发事件(点击/悬停) 3. 滚动到元素(scrollIntoView) 4. 监听AJAX完成 |
14. 如何通过子元素定位父元素?
通过xpath的语法直接定位:.//*[@name="name"]/.. 两个点..就是代表父级元素
15. 怎么判断该功能是否符合使用自动化测试?
首先进行评估,评估完之后,确实能提升测试效率,那就选择自动化测试;
比如尤其是UI自动化,有些手工测试只需要一个小时,它可能写代码需要两天;
功能是否需要频繁回归测试;
需求/界面是否长期不变;
手工测试是否低效或易出错;
16. 八大定位元素方法及区别
| 定位方式 | 定位依据 | 唯一性 | 速度 | 适用场景 |
|---|---|---|---|---|
| id | id属性 | 唯一 | 最快 | 有唯一id的元素 |
| name | name属性 | 不唯一 | 快 | 表单元素常用 |
| class name | class属性 | 不唯一 | 快 | 有特定class的元素 |
| tag name | HTML标签名 | 不唯一 | 快 | 标签结构简单的页面 |
| link text | 完整链接文本 | 唯一 | 快 | 文本链接 |
| partial link text | 部分链接文本 | 不唯一 | 快 | 文本链接(模糊匹配) |
| XPath | XML路径 | 灵活 | 较慢 | 复杂定位,无合适属性时 |
| CSS selector | CSS选择器 | 灵活 | 快 | 兼容性好,浏览器原生支持 |
4. 执行UI自动化时如找不到元素分析哪些原因?
- 元素定位代码是否正确,是否匹配到唯一元素
- 是否有做元素等待,是否需要鼠标悬浮
- 元素是否在新窗口,元素是否存在于iframe标签中
# 等待页面加载完成(可以等某个关键元素出现)
submit_button = WebDriverWait(driver, 10).until(
EC.presence_of_element_located(
(By.XPATH, '//*[@id="submitOrder"]/div/div[2]/div'))
)
# 第一步:滚动到元素的位置
driver.execute_script("arguments[0].scrollIntoView(true);", submit_button)
time.sleep(0.3)
# 提交订单按钮,js点击或者Selenium 的 .click() 方法
driver.execute_script("arguments[0].click();", submit_button)
# submit_button.click()
5.如何管理自动化测试用例?
小项目:放在excel中去管理和维护
大项目:放在数据库去管理和维护,更好的将数据共享到项目中当中
项目初期:放到excel中去
项目迭代:逐步的将测试用例迁移到数据库当中去,比如冒烟测试、回归测试
项目稳定:将所有的测试用例放到数据库中去
6.when开展自动化测试
在满足以下条件时引入自动化更高效:
核心功能已稳定
存在高频重复测试场景
有长期维护投入
从项目流程看自动化测试执行的环节:
1、在单元测试之后,冒烟测试阶段(快速反馈)执行自动化测试
2、在项目集成的时候进行自动化测试
3、在上线部署后,在回归测试阶段进行自动化测试
app测试
1、测试过程中遇到app出现crash或者ANR,怎么处理?
1、使用adb命令打印日志文件
2、再去复现操作步骤
拿到日志后再搜索其中的关键字,初步定位问题原因后,再交给开发人员去具体查找深层原因并修复。
2、app的性能测试,需要重点关注那些方面?
app使用时对CPU、内存占用情况(GT结果怎么看)
app使用时对电量、流量的消耗情况(adb什么场景消耗大)
app启动时长(adb冷启动、热启动)
app流畅度(fps帧率,值越大流畅度越好,值越小,流畅度越差)
长时间使用稳定性(adb monkey)
3、app的专项测试,需要重点关注那些方面?
安装(从不同渠道安装、不同操作系统安装、存储空间不足安装)
卸载(正常卸载(手机卸载\使用第三方软件卸载)、运行时卸载(后台运行))
升级(跨版本升级、从不同渠道升级)
交叉测试()
用户体验(UI界面测试、易用性测试)
4、什么是兼容性测试?兼容性测试侧重哪些方面?
兼容测试主要是检查软件在不同的硬件平台、软件平台上是否可以正常的运行,即是通常说的软件的可移植性。
web兼容性测试:
进行多浏览器的兼容性测试
app兼容性测试:
手机型号、操作系统、网络(wifi和移动数据)、分辨率、屏幕
应用兼容性:
手机硬件: 手机上的物理按键(音量键 home键 电源键)
外部硬件: 蓝牙设备 有线设备
操作系统设置: wlan 时间 定位
其他APP: 具有后台播放功能的APP,例如音乐
若公司没有太多机型,可参考云测平台或者模拟器
5、如何测试手机在上市之前在各操作系统上的兼容性
1. 明确测试目标
确定需要测试的操作系统版本(如Android、iOS等)及其具体版本号。
确定测试的重点,包括功能兼容性、性能、UI适配、网络兼容性等。
2. 搭建测试环境
设备池:准备不同品牌、型号的手机设备,覆盖主流市场。
操作系统版本:安装不同版本的操作系统(如Android 10、11、12,iOS 14、15、16等)。
网络环境:模拟不同的网络条件(2G、3G、4G、5G、Wi-Fi等)。
工具支持:使用兼容性测试工具(如Appium、TestComplete、BrowserStack等)。
3. 功能兼容性测试
核心功能测试:确保手机的基本功能(如通话、短信、摄像头、蓝牙、Wi-Fi等)在不同操作系统上正常工作。
应用兼容性测试:测试预装应用和第三方应用在不同操作系统上的运行情况。
API兼容性:验证手机硬件与操作系统API的兼容性(如传感器、GPS、NFC等)。
4. UI适配测试
分辨率适配:测试手机屏幕在不同分辨率下的显示效果。
布局适配:确保UI元素在不同操作系统版本上布局合理。
字体和图标:检查字体大小、图标显示是否正常。
5. 性能测试
启动时间:测试手机在不同操作系统上的启动速度。
响应速度:测试应用打开、切换、关闭的速度。
资源占用:检查CPU、内存、电池消耗情况。
发热测试:长时间运行高负载应用,检查手机发热情况。
6. 网络兼容性测试
网络切换:测试手机在不同网络环境下的切换能力(如从Wi-Fi切换到4G)。
网络稳定性:检查网络连接是否稳定,是否存在断线或延迟问题。
漫游测试:测试手机在国际漫游时的网络兼容性。
7. 安全性和权限测试
权限管理:测试手机在不同操作系统上对应用权限的管理是否正常。
数据安全:检查数据传输和存储的安全性。
系统更新:测试操作系统更新后手机的兼容性。
8. (自动化测试)
使用自动化测试工具(如Appium、Robot Framework)编写脚本,覆盖常用功能和场景。
自动化测试可以提高效率,尤其是在需要重复测试的场景中。
9. 用户场景测试
模拟真实用户的使用场景,如通话、拍照、玩游戏、浏览网页等。
测试手机在不同操作系统上的用户体验是否一致。
10. 缺陷管理与修复
记录测试过程中发现的兼容性问题,并跟踪修复进度。
对修复后的版本进行回归测试,确保问题已解决且未引入新问题。
11. 测试报告
汇总测试结果,包括兼容性问题、性能数据、UI适配情况等。
提供改进建议,为产品上市提供决策支持。
12. 持续测试
在手机上市后,持续监控用户反馈和市场表现,及时发现并解决新的兼容性问题。
定期更新测试用例,覆盖新操作系统版本和新功能。
小程序
1、优缺点
优点:无需下载安装,用户体验性好
缺点:小程序大小为20M;不适用于复杂的业务逻辑;页面层级实际设计不超过三级
python
一、基础知识
-
可变与不可变类型的区别?
- 可变:list/dict/set(支持原地修改)
- 不可变:int/str/tuple/frozenset(修改会创建新对象)
- 示例:
a = (1,2); a += (3,)会生成新元组
-
装饰器
允许在不修改原有函数代码的基础上,动态地增加或修改函数的功能
def decorator03(func): def wrapper(*args,**kwargs): print('start03') result = func(*args,**kwargs) print('end03') return result return wrapper a,b=1,2 @decorator03 def say_hello03(a,b): return a + b print(say_hello03(a,b)) -
*args 和 **kwargs 的作用?
- *args:接收任意数量位置参数(元组形式)
- **kwargs:接收任意数量关键字参数(字典形式)
*args必须位于所有位置参数之后,而**kwargs则应该位于所有参数的最后- 典型应用场景:函数参数透传、装饰器
-
多线程怎么实现?
- 调用 THREADING 模块下的 THREAD
-
线程与进程的区别
| 特性 | 进程 | 线程 |
|---|---|---|
| 定义 | 资源分配的基本单位 | 进程内的执行单元 |
| 资源 | 独立的内存空间和资源 | 共享进程的内存空间和资源 |
| 创建开销 | 较大 | 较小 |
| 并发性 | 进程切换开销较大 | 线程切换开销较小 |
| 隔离性 | 高隔离性,一个进程崩溃不影响其他进程 | 低隔离性,一个线程崩溃可能影响整个进程 |
| 通信方式 | 进程间通信(IPC) | 共享内存,需要同步机制 |
| 应用场景 | 独立应用程序(高隔离性和安全性) | 多任务处理、并行计算(高效并发和资源共享) |
7、is和==区别?
is:比较内存地址;==:比较值
8、Python中数据结构有哪些?
list、set、dictionary、tuple、Str;int float bool bytes
9、说说while-else和for-else?
else执行的条件:
必须循环正常结束(即未被 break 中断)。
即使循环条件初始为假(如 while False),else 也会执行。
10、什么是装饰器?
动态地增加/修改函数或类的行为
11、Python类中有哪些常用装饰器?
classmethod\staticmethod\property
13、什么是可迭代对象?
列表(list)、元组(tuple)、字符串(str)、字典(dict)、集合(set)
14、列表推导式 vs 生成器表达式
| 特性 | 列表推导式(List Comprehension) | 生成器表达式(Generator Expression) |
|---|---|---|
| 语法 | 使用方括号 [x for x in iterable] |
使用圆括号 (x for x in iterable) |
| 内存占用 | 立即生成所有元素,占用完整内存 | 惰性计算,逐个生成元素,内存高效 |
| 返回值类型 | 返回 list 对象 |
返回 generator 对象(迭代器) |
| 适用场景 | 需多次访问结果或需要索引/切片操作 | 大数据处理或只需单次遍历 |
| 执行时机 | 立即执行 | 延迟执行(调用 next() 或遍历时计算) |
| 是否可重用 | 可多次遍历 | 一次性消费(遍历后需重新创建) |
16、说说filter函数、map函数、reduce函数?
| 函数 | 输入 | 输出 | 典型用途 |
|---|---|---|---|
filter |
一个可迭代对象 | 过滤后的迭代器 | 筛选满足条件的元素 |
map |
一个或多个可迭代对象 | 转换后的迭代器 | 批量处理或转换元素 |
reduce |
一个可迭代对象 | 单个累积结果 | 聚合计算(如求和、求积) |
filter(过滤):
nums = [1, 2, 3, 4, 5]
even_nums = filter(lambda x: x % 2 == 0, nums) # 返回迭代器
print(list(even_nums)) # 输出: [2, 4]
map(对iterable的每个元素应用函数):
a = [1, 2, 3]
b = [4, 5, 6]
result = map(lambda x, y: x + y, a, b) # 返回迭代器
print(list(result)) # 输出: [5, 7, 9]
reduce(累积计算):
sum_result = reduce(lambda x, y: x + y, [1, 2, 3], 10) # 发挥单一的结果
print(sum_result) # 输出: 16 (10 + 1 + 2 + 3)
17、如何定义实例属性和类属性?
| 特性 | 实例属性 | 类属性 |
|---|---|---|
| 定义位置 | __init__ 方法内 |
类内部(方法外) |
| 归属 | 属于实例 | 属于类 |
| 内存 | 每个实例独立存储 | 所有实例共享同一内存 |
| 修改影响 | 仅影响当前实例 | 影响所有实例 |
| 访问方式 | self.属性名 / 实例.属性名 |
类名.属性名 / 实例.属性名 |
18、什么是lambda函数,有什么好处?
Lambda 是什么:匿名函数,用 lambda 参数: 表达式 定义。
核心用途:简化代码,与高阶函数(如 map/filter)配合。
适用场景:短小的一次性操作,避免定义单独的函数。
19、python想要对数组倒序?
my_list = [1, 2, 3, 4, 5]
reversed_list = my_list[::-1] #切片 [5, 4, 3, 2, 1]
my_list.reverse() # 直接修改原列表
sorted(my_list, reverse=True)
20、sort()和sorted()有什么区别?
my_list.sort() # 原地排序 无返回值
new_list = sorted(my_list) # 返回新列表
print(my_list) # 输出: [3, 1, 4, 2] (原列表不变)
print(new_list) # 输出: [1, 2, 3, 4]
21、什么是深拷贝,浅拷贝?(一层浅,多层深,独立副本必须深!)
| 特性 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 复制层级 | 只复制第一层 | 递归复制所有层级 |
| 嵌套对象 | 共享相同引用 | 创建全新对象 |
| 内存占用 | 较少 | 较多 |
| 修改嵌套对象影响 | 影响原始对象 | 不影响原始对象 |
| 速度 | 较快 | 较慢 |
| 使用场景 | 简单对象/无嵌套结构 | 复杂嵌套结构/需要完全独立副本 |
22、异常(else/finally/raise)
try:
# 可能会抛出异常的代码
except 异常类型:
# 异常处理代码(报错后执行)
else:
# 没有异常时执行的代码
try:
# 可能会抛出异常的代码
except 异常类型: # 红色标注
# 异常处理代码
else: # 红色/紫色标注
# 没有异常时执行的代码
finally: # 红色标注
# 无论是否异常都执行的代码
try:
gender = input('请输入您的性别:')
if gender != '男' and gender != '女':
raise Exception('性别只能是男或女')
else:
print('您的性别是:', gender)
except Exception as e:
print(e)
23、内置函数
类型转换:int、float、str、list、tuple、set
数学函数:max、min、abs、sum
迭代器操作函数:sorted、reversed、enumerate、filter、map、reduce
24、os模块的函数
| getcwd() | 获取当前的工作路径 |
|---|---|
| listdir(path) | 获取path路径下的文件和目录信息,如果没有指定path,则获取当前路径下的文件和目录信息 |
| mkdir(path) | 在指定路径下创建目录(文件夹) |
25、os.path的函数
| abspath(path) | 获取目录或文件的绝对路径 |
|---|---|
| exists(path) | 判断目录或文件在磁盘上是否存在,结果为bool类型,如果目录或文件在磁盘上存在,结果为True,否则为False |
| join(path, name) | 将目录与目录名或文件名进行拼接,相当于字符串的“+”操作 |
| splitext() | 分别获取文件名和后缀名 |
| basename(path) | 从path中提取文件名 |
| dirname(path) | 从path中提取路径的目录部分(不包含文件名) |
26、JSON
json string -->json.loads() -->Python Object
Python string -->json.dumps() -->Json Object
27、动态类型和静态类型的优缺点是什么?
动态类型:无需声明类型,变量可随时更改类型,支持鸭子类型(关注行为而非类型)
类型问题只能在执行时发现,难以追踪变量类型
静态类型:在运行前捕获类型问题,类型注解提高可读性
需要额外写类型注解,严格类型检查
28、列表和元组的区别?
| 特性 | 列表(List) | 元组(Tuple) |
|---|---|---|
| 可变性 | 可变 | 不可变 |
| 语法 | [ ] |
( ) 或无括号 |
| 性能 | 较慢,内存开销大 | 更快,更节省内存 |
| 方法数量 | 多 | 少(只有 count, index) |
| 能否修改元素 | ✅ 可以 | ❌ 不可以 |
| 能否作为字典键 | ❌ 不可以 | ✅ 可以(若元素可哈希) |
| 适用场景 | 动态数据集合 | 固定数据、结构化数据 |
29、多线程和多进程的区别?
| 特性 | 多线程 | 多进程 |
|---|---|---|
| 资源分配 | 线程共享进程的资源(内存、文件句柄等) | 每个进程有独立的内存空间和资源 |
| 创建/销毁开销 | 较小,适合频繁创建/销毁 | 较大,适合长期运行的任务 |
| 通信方式 | 直接共享内存,通信简单但需同步(如锁) | 需通过 IPC(管道、队列、共享内存等)通信 |
| 上下文切换开销 | 较小(共享地址空间) | 较大(需切换独立的地址空间) |
| 独立性与稳定性 | 一个线程崩溃可能导致整个进程崩溃 | 一个进程崩溃不影响其他进程 |
| 并发性 | 高效资源共享,适合 I/O 密集型任务 | 真正并行计算,适合 CPU 密集型任务 |
| 适用场景 | I/O 密集型任务(文件读写、网络请求) | CPU 密集型任务(科学计算、图像处理) |
| GIL 影响 | 受 GIL 限制,无法并行执行 CPU 任务 | 不受 GIL 限制,可充分利用多核 CPU |
30、迭代器怎么操作?
| 操作方法 | 用途 |
|---|---|
iter(obj) |
将可迭代对象转换为迭代器 |
next(iterator) |
获取迭代器的下一个元素 |
for 循环 |
自动处理迭代器的遍历 |
zip() |
同时迭代多个序列 |
reversed() |
反向迭代 |
map()/filter()/reduce |
结合函数处理可迭代对象 |
31、yield
yield 的作用:将函数变为生成器,实现按需生成数据、状态保存和双向通信。
节省内存的原理:惰性计算,按需生成数据,避免一次性加载所有数据到内存。
适用场景:大文件处理、流式数据、无限序列、批量任务分发等
32、*args 和 **kwargs 的区别
| 特性 | *args |
**kwargs |
|---|---|---|
| 参数类型 | 位置参数(非关键字参数) | 关键字参数(键值对参数) |
| 数据结构 | 元组(tuple) | 字典(dict) |
| 调用方式 | func(1, 2, 3) |
func(name="Alice", age=30) |
| 定义顺序 | 必须在普通参数之后,**kwargs 之前 |
必须在 *args 之后 |
| 示例 | def func(*args): print(args) |
def func(**kwargs): print(kwargs) |
re
re.match(pattern, string, flags=0):
仅匹配字符串开头
使用group(num) 或 groups() 匹配对象函数来获取匹配表达式
re.search(pattern, string, flags=0):
扫描整个字符串并返回第一个成功的匹配。
使用group(num) 或 groups() 匹配对象函数来获取匹配表达式
re.match 与 re.search的区别
re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None,而 re.search 匹配整个字符串,直到找到一个匹配。
re.sub(pattern, repl, string, count=0, flags=0):
用于替换字符串中的匹配项
re.findall(pattern, string, flags=0):
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表
match 和 search 是匹配一次 findall 匹配所有
#分组匹配(Group:前提正则含有()分组)
# group():返回整个匹配的字符串。
# group(n):返回第 n 个分组(需正则中有 () 分组)。
# groups():返回所有分组的元组。
text = "2023-12-31"
match = re.search(r"(\d{4})-(\d{2})-(\d{2})", text)
if match:
print("完整匹配:", match.group()) # 2023-12-31
print("年:", match.group(1)) # 2023
print("月:", match.group(2)) # 12
print("日:", match.group(3)) # 31
print("所有分组:", match.groups()) # ('2023', '12', '31')
datetime
datetime.now():当前本地日期和时间
from datetime import datetime
now = datetime.now() # 返回 datetime 对象
print(now) # 输出: 2023-10-05 14:30:45.123456
日期时间格式化(strftime)
from datetime import datetime
now = datetime.now()
formatted = now.strftime("%Y-%m-%d %H:%M:%S")
print(formatted) # 输出: 2023-10-05 14:30:45
字符串转日期(strptime)
from datetime import datetime
date_str = "2023-10-05 14:30:00"
dt = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
print(dt) # 输出: 2023-10-05 14:30:00
| 操作 | 方法 | 示例 |
|---|---|---|
| 获取当前时间 | datetime.now() |
datetime.now() |
| 格式化日期 | strftime |
dt.strftime("%Y-%m-%d") |
| 字符串转日期 | strptime |
datetime.strptime("2023-10-05", "%Y-%m-%d") |
| 日期计算 | timedelta(时间差,加减日期) |
now + timedelta(days=1) |
| 获取日期部分 | dt.year, dt.month |
dt.year |
numpy
多维度,元素类型一致,高效性
数组:
np.array([[]])、zeros((2,3))、ones((2,2))、eye(3)单位矩阵、arange(0,10,2)
数组属性:
arr = np.array([[1, 2, 3], [4, 5, 6]])
print("形状:", arr.shape) # (2, 3)
print("维度:", arr.ndim) # 2
print("元素总数:", arr.size) # 6
print("数据类型:", arr.dtype) # int64
# 变形reshape
arr = np.arange(6).reshape(2, 3) # 1D → 2D
print(arr)
# 广播(即满足 a.shape == b.shape,这要求维数相同,且各维度的长度相同)
a = np.array([1,2,3,4])
b = np.array([10,20,30,40])
c = a * b
当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制
a = np.array([[ 0, 0, 0],
[10,10,10],
[20,20,20],
[30,30,30]])
b = np.array([0,1,2])
print(a + b)
:[[ 0 1 2]
[10 11 12]
[20 21 22]
[30 31 32]]
# 统计计算
arr = np.array([[1, 2], [3, 4]])
print("总和:", np.sum(arr)) # 10
print("列总和:", np.sum(arr, axis=0)) # [4 6]
print("最大值:", np.max(arr)) # 4
print("均值:", np.mean(arr)) # 2.5
print("标准差:", np.std(arr)) # 1.118
二、面向对象编程
-
__init__和__new__的区别?__new__:创建实例的构造方法(返回实例对象)__init__:初始化实例的初始化方法__new__在__init__之前执行
class MyClass: def __new__(cls, *args, **kwargs): print("Creating instance") # 调用父类(这里是object)的__new__方法来创建实例 instance = super(MyClass, cls).__new__(cls) return instance def __init__(self, value): print("Initializing instance") self.value = value # 创建MyClass的一个实例 obj = MyClass(10) print(obj.value)3、静态类与动态类的区别
静态类:
- 不能被实例化,不依赖实例状态,所有方法通过类直接调用
- 所有方法为
@staticmethod或@classmethod
class MathUtils: # 阻止实例化 def __new__(cls): raise TypeError("Cannot instantiate static class!") @staticmethod def add(a, b): return a + b @staticmethod def multiply(a, b): return a * b # 直接调用静态方法 print(MathUtils.add(2, 3)) # 输出: 5动态类:
- 允许实例化,支持运行时修改
- 支持动态添加/删除方法或属性
- 可以使用
type()或元类动态创建类
class Dog: def __init__(self, name): self.name = name # 动态添加实例属性 dog = Dog("Buddy") dog.age = 3 # 新增属性 # 动态添加方法 def bark(self): print(f"{self.name} says Woof!") Dog.bark = bark # 类添加方法后,所有实例均可调用 dog.bark() # 输出: Buddy says Woof! # 使用type()动态创建类 Cat = type("Cat", (), {"meow": lambda self: print("Meow!")}) cat = Cat() cat.meow() # 输出: Meow!
Linux
一、文件与目录操作(核心必会)
| 命令 | 作用 | 典型示例 |
|---|---|---|
ls |
列出目录内容 | ls -larth(按时间倒序+显示隐藏文件) |
cd |
切换目录 | cd ~(返回家目录)cd ..上一级目录 cd ../..上两级目录 |
pwd |
显示当前路径 | |
mkdir |
创建目录 | mkdir -p a/b/c(递归创建嵌套目录) |
rm |
删除文件/目录 | rm -rf dir(强制递归删除目录) |
cp |
复制文件 | cp -r src_dir dest_dir(递归复制) |
mv |
移动/重命名文件 | mv old.txt new.txt |
tar |
打包压缩/解压 | tar -c(创建新的归档文件(打包))z(使用 gzip 压缩或解压缩(.tar.gz 或 .tgz))vf archive.tar.gz -C dir/(gzip压缩)x(解压) |
| unzip | 解压zip | unzip egoser.zip -d dir/ |
| touch | 新建文件 |
find 命令常用语法速查表
| 功能 | 命令格式 | 说明 |
|---|---|---|
| 基本查找 | find <路径> [选项] [表达式] |
在指定路径下查找文件 |
| 按名称查找 | find /path -name "文件名" |
支持通配符(*, ?) |
| 忽略大小写 | find /path -iname "文件名" |
名称查找不区分大小写 |
| 按类型查找 | find /path -type <类型> |
类型: f(文件), d(目录), l(链接), s(套接字)等 |
| 按大小查找 | find /path -size [+/-]n[单位] |
单位: c(字节), k(KB), M(MB), G(GB) |
| 按时间查找 | find /path -mtime [+/-]n |
mtime(修改内容时间), atime(访问时间), ctime(状态变更(chmod、所有者和所在组或者mv)时间) |
| 查找最近修改 | find /path -type f -mtime -7 | 查找7天内修改过的文件 |
常用大小查找示例
| 示例 | 代码 |
|---|---|
| 大于等于512KB | find /path -size +511k |
| 小于等于512KB | find /path -size -513k |
| 500MB到1GB之间 | find /path -size +500M -size -1G |
二、文本处理三剑客
| 命令 | 核心能力 | 高频用法 |
|---|---|---|
grep |
文本过滤 -c 只输出匹配行计数 | grep -rin "error" *.log(递归+忽略大小写) |
awk |
结构化数据处理,处理列(计算,判断) | awk -F(字段分隔符) ',' '{print $1, $4}' data.csv |
sed |
流编辑器 | sed -i 's/foo/bar/g' file.txt(批量替换) |
三、系统监控与进程管理
| 命令 | 应用场景 | 关键参数 |
|---|---|---|
top |
实时监控系统资源 | 交互模式按P(CPU排序)/M(内存排序) |
ps |
查看进程状态 | ps aux | grep nginx |
kill |
终止进程 | kill -9 PID(强制终止) |
free |
查看内存使用 | free -h(人性化显示) |
df |
磁盘空间检查 | df -hT(显示文件系统类型) |
du |
目录空间分析 | du -sh *(统计当前目录大小) |
四、网络与调试工具
| 命令 | 用途 | 典型场景 |
|---|---|---|
curl |
HTTP请求工具 | curl -I http://domain.com(仅显示头信息) |
wget |
网络文件下载 | wget -c http://url/file.zip(断点续传) |
netstat |
网络连接状态 | `netstat -tulnp |
ssh |
远程登录 | ssh -p 2222 user@host |
scp |
安全文件传输 | scp file.txt user@host:/path |
| rz | 文件上传 | |
ping |
网络连通性测试 | ping -c 4 google.com |
yum update |
更新软件包列表 | |
| yum list 软件包 | 查看是否存在对应软件包 |
五、权限与用户管理
| 命令 | 功能 | 示例 |
|---|---|---|
chmod |
修改文件权限 | chmod 755 script.sh |
chown |
修改文件所有者 | chown user:group file.txt |
sudo |
提权执行命令 | sudo apt update |
useradd |
创建用户 | useradd -m testuser |
passwd |
修改用户密码 | passwd testuser |
六、服务 systemctl
| 命令 | 功能 | 示例 |
|---|---|---|
<服务名> -v |
检查 服务 是否已安装 | httpd -v |
systemctl start <服务名> |
启动服务 | systemctl start httpd |
systemctl restart <服务名> |
重启服务 | systemctl restart httpd |
systemctl status <服务名> |
查看服务状态 | systemctl status httpd |
systemctl enable <服务名> |
启用服务开机自启 | systemctl enable httpd |
systemctl disable <服务名> |
禁用服务开机自启 | systemctl disable httpd |
七、查看文件内容
| 命令 | 功能 | |
|---|---|---|
cat |
查看文件内容比较少 | |
more和less |
查看文件内容比较多的情况 | |
| head | 查看前面x行文件内容 | |
| tail | 查看后面x行文件内容 | tail -f:查看实时日志文件信息 |
Linux如何搭建服务,如禅道?
以搭建禅道服务为例:
1、首先确保已安装web服务(Apache(yum -y install httpd))、MySQL数据库
2、使用wget命令下载对应版本的禅道,并使用tar命令解压禅道 至/opt目录下
3、设置禅道(默认http端口80)和数据库的端口号,避免与linux的端口号发生冲突
/opt/zbox/zbox -ap 8081 /opt/zbox/zbox -mp 3308
4、去到禅道目录使用start命令启动禅道,查看status状态
5、使用firewall中开放特定端口命令开放指定端口
firewall-cmd --zone=public --add-port=8081/tcp --permanent
firewall-cmd --reload
6、启动浏览器访问禅道
fiddler
1、快捷键
R:replay;shifft+R:n次重放
ctrl+X:remove all
打断点:在All Processes 右边小正方形点击第一下请求前,在点击响应后 点击go松开断点
或者使用F11或者alt+F11 shift+F11
弱网测试:rules-》simulate modem speeds/customize rules(simulateModem自定义请求或者响应的speed)
2、断点
全局断点:请求前:数据篡改 响应后:网络中断/数据篡改
局部断点(右下角输入框):请求前:bpu 关键字 取消断点:bpu 响应后:bpa 关键字 取消断点:bpa
3、Fiddler 设置 HTTP 代理抓取手机请求
android App抓包详情:
1. Fiddler设置 允许远程连接 + 设置端口(如 8888)
2. 手机代理 确保手机和电脑在同一局域网;设置 Wi-Fi 代理(电脑 IP + Fiddler 端口)
3. 安装证书 访问 http://<IP>:8888/FiddlerRoot.cer 安装证书(设置 → 安全 → 加密与凭据 → 安装证书;ios:设置 → 已下载描述文件 → 安装;设置 → 通用 → 关于本机 → 证书信任设置)
4. 抓包 手机访问网页/App,Fiddler 显示请求
4、用Fiddler设置断点有什么作用?
进行接口测试时,修改请求参数或响应参数,验证后端接口功能。
例如:测试一个登录接口的输入框,前端限制输入数字大小为8~16位,当我们需要测试输入大于16或者小于8的数字时,服务器的响应是否正确,但是这时无法通过前端页面进行操作。
因为前端已经限制了不让输入大于16或者小于8的数字,此时就需要抓包,修改请求里的参数,绕过前端去测试服务端的功能是否正常。
5、怎么用Fiddler拦截来自某个网址的所有请求?
在命令行输入:bpu url
6、登录接口的弱网测试?
在rules-》点击customize rules
进入Fiddler Script的文件,设置弱网参数:模拟3G网络(上行100KB/S+下行200KB/S),添加500ms固定延迟和30%的丢包率;发现25%登录请求在弱网下超时失败(请求时间大于8S)
7、使用fiddler定位问题(登录失败)
以AI智习室的登录接口为例,我发现了登录失败的问题
打开fiddler,设置代理,清空之前的请求记录,
在网页执行一次登录操作
然后寻找login请求,但是发现返回的状态码500错误,一看到500,我想大概率是后端问题,
然后查看日志,发现了是登录接口的空指针异常,然后进一步提交给开发去解决
2、http协议调试代理工具有哪些?请详细说明抓取https协议 的设置过程?
fiddler
安装证书; Tools--Options--HTTPs,配置允许抓取HTTPS连接和解析HTTPS流量然后选择要解释的来源,点击actions安装证书
使用fiddler如何进行抓包?
配置 HTTPS 抓包:
在 Tools > Options > HTTPS 中,勾选 Capture HTTPS CONNECTs 和 Decrypt HTTPS traffic,并安装 Fiddler 根证书以解密 HTTPS 流量。
开始抓包:
确保 Fiddler 处于捕获状态(左下角显示 Capturing),然后在浏览器或应用中执行需要抓包的操作。
查看与分析数据:
左侧列表显示所有请求,点击某个请求后,右侧点击inspectors查看详细信息,包括请求头、请求体、响应头、响应体等。
过滤与搜索:
使用过滤器(Filters 选项卡)或搜索框,快速定位特定请求。
断点调试与修改:
通过 Rules > Automatic Breakpoints 设置断点,拦截并修改请求或响应。
计算机网络
get和post的区别?
作用:一般用get来获取数据,用post来提交数据
参数传递方式:get的请求参数放在url中,post的请求参数放在请求体当中。
安全性:get请求参数直接暴露在URL中,是不安全的
get的参数放在url中,浏览器对url有长度限制,而post参数长度是不受限制的。
时间消耗不同:get产生一个TCP数据包,post产生两个TCP数据包
session、cookie和token
1.区别
Cookie是存储在客户端的键值对,依赖浏览器自动管理;Session是服务端状态管理,通过Session ID关联;Token(如JWT)是无状态的凭证,包含自描述信息。三者的过期时间分别由客户端属性、服务端策略和Token字段控制。安全性上,Cookie需防御CSRF/XSS,Session需保护ID传输,Token需防篡改和泄漏。
2、联系
Session默认是靠Cookie跟踪的,记录jsessionid,反复携带
3、如何解决Cookie失效、被禁用,会导致Session无法跟踪?
URL重写:将 sessionid 直接嵌入到 URL 中(URL;jsessionid=xxx?参数名=参数值&参数名=参数值&...),强制携带了jsessionid,避免Session跟踪丢失
4、怎么让服务器不用保存用户数据,又保证数据的安全性、一致性和完整性,还能不通过服务器查询到用户数据时,输出数据?
使用token
5、等待两小时,使用当前的cooike、session和token(一小时)技术实现的会话会失效吗?或者只等待了半小时,但已经把浏览器关闭了,session会失效吗?
1、会失效(token有效时间只有1小时)
2、会失效(session在你关闭浏览器时会被销毁)
6、token流程
token流程:① 客户端登录后,服务器生成Token(含用户信息+签名)并返回给客户端;② 客户端存储Token,后续请求时主动在Header(如Authorization: Bearer Token)中携带;③ 服务器验证Token的签名和有效期,无需查询服务器存储即可确认身份。
1、简述你所知道的网络协议,并说明网络协议的作用
HTTP/HTTPS:HTTP是明文传输,HTTPS是加密传输;HTTP端口为80,HTTPS端口为443
FTP:用于文件传输。
TCP:提供可靠的、面向连接的数据传输。
UDP:提供无连接的数据传输,速度较快但不保证可靠性。
IP:负责数据包的路由和寻址。
DNS:将域名转换为IP地址。
SMTP/POP3/IMAP:用于电子邮件传输和接收。
2、简述TCP和UDP的区别
TCP(传输控制协议):提供可靠的、面向连接的数据传输。它确保数据包的顺序和完整性,适用于需要高可靠性的应用,如网页浏览和文件传输。
UDP(用户数据报协议):提供无连接的数据传输,速度较快但不保证数据包的顺序和完整性。适用于实时应用,如视频流和在线游戏。
3、OSI和TCP/IP体系结构


物理层:解决使用何种信号来传输比特的问题。
数据链路层:解决分组在一个网络(或一段链路)上传输的问题。
网络层:解决分组在多个网络上传输(路由)的问题。
运输层:解决进程之间基于网络的通信问题。
应用层:解决通过应用进程的交互来实现特定网络应用的问题。
4、http协议的结构
http请求:
1、请求行:请求URL、请求方法
2、请求头:Host(目标服务器的主机名和端口号)、user-agent(客户端信息)、cookie数据
3、请求体:通常用于POST、PUT方法,包含发送到服务器的数据
http响应:
1、状态行:响应状态码
2、响应头:content-Type、content-Length、location(重定向的目标 URL)
3、响应体:包含服务器返回的实际数据,比如HTML页面,JSON数据
5、TCP三次握手的流程,为什么不是四次或两次?
1、客户端向服务器发送 SYN 报文、初始化序列号 ISN(seq=x),然后客户端进入 SYN_SENT 状态,等待服务器确认。
2、服务器收到客户端的 SYN 报文后,服务器发送 SYN + ACK 报文,包含确认号(ack=x+1)和自己的初始化序列号(seq=y),然后服务端进入 SYN_RECV 状态。
3、客户端接收到服务端的 SYN+ACK 报文后,客户端发送 ACK 报文,包含确认号(ack=y+1),然后客户端和服务器端都进入 ESTABLISHED 状态,完成 TCP 三次握手。
为什么不是四次握⼿? 或者两次握⼿?
因为三次握⼿才能保证双⽅具有接收和发送的能⼒。 两次握⼿可能导致资源的浪费,由于没有第三次
握⼿,服务端就⽆法确认客户端是否收到了⾃⼰的回复,所以每收到⼀个 SYN ,服务器都会主动去
建⽴⼀个连接, ⽽四次握⼿虽然更安全,但效率较低,所以可以优化为三次。
6、四次挥手的流程?
1、客户端发送 FIN 报文(seq=x),进入 FIN-WAIT-1 状态。
2、服务器发送 ACK 报文(ack=x+1),进入 CLOSE-WAIT 状态;客户端进入 FIN-WAIT-2 状态。
3、服务器发送 FIN 报文(seq=y),进入 LAST-ACK 状态。
4、客户端发送 ACK 报文(ack=y+1),进入 TIME-WAIT 状态;服务器进入 CLOSED 状态。客户端等待 2MSL 后进入 CLOSED 状态。
1、客户端发送一个 FIN 报文给服务端,表示自己要断开数据传送,报文中会指定一个序列号(seq=x)。然后,客户端进入 FIN-WAIT-1 状态。
2、服务端收到 FIN 报文后,回复 ACK 报文给客户端,且把客户端的序列号值 +1,作为 ACK 报文的序列号(seq=x+1)。然后,服务端进入 CLOSE-WAIT(seq=x+1)状态,客户端进入 FIN-WAIT-2 状态。
3、服务端也要断开连接时,发送 FIN 报文给客户端,且指定一个序列号(seq=y+1),随后服务端进入 LAST-ACK 状态。
4、客户端收到 FIN 报文后,发出 ACK 报文进行应答,并把服务端的序列号值 +1 作为 ACK 报文序列号(seq=y+2)。此时客户端进入 TIME-WAIT 状态。服务端在收到客户端的 ACK 报文后进入 CLOSE 状态。如果客户端等待 2MSL 没有收到回复,才关闭连接。
7、网页状态码
| 状态码范围 | 类别 | 含义 |
|---|---|---|
| 1xx | 信息性状态码 | 请求已被接收,继续处理 |
| 2xx | 成功状态码 | 请求已成功处理 |
| 3xx | 重定向状态码 | 需要进一步操作以完成请求 |
| 4xx | 客户端错误状态码 | 客户端请求有误 |
| 5xx | 服务器错误状态码 | 服务器处理请求时出错 |
2xx 成功 (Success)
| 状态码 | 名称 | 含义 | 常见场景 |
|---|---|---|---|
| 200 | OK | 请求成功。 | 正常访问页面或获取资源。 |
| 201 | Created | 请求成功且服务器创建了新资源。 | 通过 POST 方法成功提交新数据(如发表文章)。 |
| 204 | No Content | 服务器成功处理,但无内容返回。 | DELETE 请求成功;表单提交后无需跳转。 |
3xx 重定向 (Redirection)
| 状态码 | 名称 | 含义 | 常见场景 |
|---|---|---|---|
| 301 | Moved Permanently | 永久重定向。请求的资源已永久移动。 | 网站更换域名,旧链接跳转到新地址。 |
| 302 | Found | 临时重定向。请求的资源临时从不同 URL 响应。 | 用户未登录,临时跳转到登录页。 |
| 304 | Not Modified | 未修改。资源未变更,可使用客户端缓存。 | 再次访问页面,本地缓存有效时。 |
4xx 客户端错误 (Client Error)
| 状态码 | 名称 | 含义 | 常见场景 |
|---|---|---|---|
| 400 | Bad Request | 错误请求。请求语法错误,服务器无法理解。 | 提交的数据格式或参数有误。 |
| 401 | Unauthorized | 未认证。请求需要用户验证。 | 访问需要登录的页面。 |
| 403 | Forbidden | 禁止访问。服务器理解请求但拒绝授权。 | 尝试访问无权限的系统文件或目录。 |
| 404 | Not Found | 未找到。服务器无法找到请求的资源。 | 访问的 URL 链接错误或资源已被删除。 |
| 418 | I'm a teapot | 我是一个茶壶。彩蛋状态码。 | 用于幽默或反爬虫场景。 |
5xx 服务器错误 (Server Error)
| 状态码 | 名称 | 含义 | 常见场景 |
|---|---|---|---|
| 500 | Internal Server Error | 服务器内部错误。服务器遇到意外错误。 | 服务器端代码(如 PHP, Java)出现 Bug。 |
| 502 | Bad Gateway | 错误的网关。网关从上游服务器收到无效响应。 | 后端应用服务(如 PHP-FPM)未启动或崩溃。 |
| 503 | Service Unavailable | 服务不可用。服务器当前无法处理请求。 | 服务器超载或正在进行停机维护。 |
| 504 | Gateway Timeout | 网关超时。网关未能及时收到上游服务器响应。 | 上游服务器处理时间过长 |
8、在网页输入一个网址,会发生什么(http/https的请求过程)?
当用户在网页输入一个网址时,首先浏览器会通过 DNS 解析域名获取 IP 地址,然后通过 TCP 三次握手与服务器建立连接。
如果是 HTTPS,还会进行 TLS 握手。接着,浏览器发送 HTTP 请求,服务器处理请求后返回响应。
浏览器解析响应内容并渲染页面,同时加载页面中的外部资源。
最后,用户可以与页面交互,浏览器可能通过 AJAX 或 WebSocket 与服务器进行异步通信,最后 ,关闭TCP连接
移动端专项测试
1、采用什么策略来进行app启动时间的统计?
adb shell dumpsys window | findstr mCurrentFocus
adb shell am start -W(启动 Activity 并 等待其完成启动) 包名/启动名
单设备多次测试
适用场景:
1、初步评估app的启动性能
2、快速发现启动时间的波动问题
步骤:
(1)选择一台设备,测试5-10次,记录每次的启动时间,确保测试环境一致
(2)计算平均值(启动时间)、波动范围(稳定性)和标准差
(3)如果波动范围较大,需要进一步分析原因(如资源加载不稳定,后台进程干扰)
多设备综合统计
使用场景:
1、全面评估app在不同设备上的性能表现
2、发布前的性能验收测试
步骤:
(1)选择3-5台平板设备,模拟真实用户的使用场景
(2)每台设备冷热启动各测试10次,记录数据
(3)分别计算每台设备的平均值和波动范围
(4)综合所有设备的数据,计算整体平均值和波动范围
2、GT如何监控APP运行时CPU和内存占用率?
1、监控CPU、内存占有率
在GT工具中,选择目标app,在监控选项中勾选CPU/PSS,点击启动;
操作app,模拟用户实际使用场景;
查看实时显示 CPU/内存 占用率的变化曲线,然后去查看 CPU/内存 占用率的峰值、平均值以及波动情况;
如果CPU占用率过高(持续超过80%),进一步分析原因(性能问题)/如果内存占用率持续上升且不释放,可能存在内存泄漏问题(资源未释放)
2、结合adb shell top -n 1 查看实时的 CPU 和内存占用情况
3、如何通过adb命令测试电量损耗情况?
1、首先重置电池统计数据 adb shell dumpsys batterystats --reset
2、模拟拔掉充电器 adb shell dumpsys battery unplug
2、使用git bash执行监控脚本(指令包括记录基础状态指令和耗电app指令)
# 创建脚本 battery_test.sh
#!/bin/bash
echo "开始监控电量,按 Ctrl+C 停止"
for i in {1..12} # 监控12次(共60分钟)
do
echo "===== $(date +'%H:%M:%S') =====" >> battery_log.txt
adb shell dumpsys battery >> battery_log.txt # 记录基础状态
adb shell dumpsys batterystats com.yourapp.package >> battery_log.txt # 关键!记录你的APP耗电
sleep 300 # 等待5分钟
done
打开 battery_log.txt 重点看:
Level: 93 # 当前电量百分比(对比初始值计算消耗)
Voltage: 4200 # 电压(mV)
temperature: 320 # 电池温度(0.1度单位,32.0°C)
com.yourapp.package: # 你的APP数据
Total cpu: 2m 30s # CPU占用时间
Wake lock: 1h # 唤醒锁持有时间(过长=异常耗电)
4、如何在emmagee测试app流量消耗情况?
1、选择目标app,设置每5秒采样一次
2、点击开始测试,Emmagee 会自动启动目标 APP 并开始监控
3、操作app,模拟用户实际使用场景,可以在界面上查看当前的流量的使用情况
4、点击“停止测试”按钮,Emmagee 会生成测试报告,直接点击设置按钮,再点击测试报告,找到对应时间戳的文件即可查看总流量消耗情况。
Java
1、三大特性
2、数组和链表的区别
| 特性 | 数组 | 链表 |
|---|---|---|
| 存储方式 | 连续内存空间 | 非连续内存空间 |
| 随机访问 | O(1) | O(n) |
| 插入/删除 | O(n)(中间操作) | O(1)(已知位置) |
| 内存占用 | 较少(仅存储数据) | 较多(额外存储指针) |
| 适用场景 | 频繁随机访问、固定大小数据 | 频繁插入删除、动态大小数据 |
| 扩展性 | 差(需重新分配内存) | 好(动态分配节点) |
3、栈和队列的特点
| 特性 | 栈 | 队列 |
|---|---|---|
| 操作规则 | 后进先出(LIFO) | 先进先出(FIFO) |
| 插入操作 | 入栈(Push) | 入队(Enqueue) |
| 删除操作 | 出栈(Pop) | 出队(Dequeue) |
| 查看操作 | 查看栈顶(Peek) | 查看队头(Peek) |
| 实现方式 | 数组、链表 | 数组、链表 |
| 时间复杂度 | 入栈、出栈、查看栈顶均为 O(1) | 入队、出队、查看队头均为 O(1) |
| 应用场景 | 函数调用、表达式求值、撤销操作 | 任务调度、消息队列、BFS 算法 |
MySQL
1、char vs varchar
CHAR`定长,空格填充;`VARCHAR`变长,节省空间
2、事务日志类型
redo log:崩溃恢复,保证持久性
undo log:回滚与MVCC支持
3、索引失效的场景
1. 使用左或者左右模糊匹配时,就是like %xx 或者 like %xx%
2. 在查询条件中对索引列使用函数/进行表达式计算
3. 联合索引不走最左匹配原则
4. where字句中,如果or前的条件列是索引列,而在or后的条件列不是索引列
4、如何优化慢查询
索引优化:为where条件字段添加索引;使用联合索引遵循最左匹配原则;警惕索引失效场景;
查询语句精简:避免select *;优先使用join而非子查询;添加limit限制返回数据量;
执行计划分析:利用explain分析慢查询,检查type访问类型,key索引使用情况
5、执行引擎有哪些?
InnoDB(支持事务、提供行级锁和外键)\MyISAM(不支持事务)\Memery(数据放在内存中)
6、日志文件有哪些?
undo log(事务回滚和MVCC)、redo log(记录数据页做了修改)
小程序linux中后台部署流程
部署细节流程

1、本地服务检查
- 检查网络连通性:ping
# linux查看IP地址的命令
ifconfig
# windows下查看IP地址的命令
ipconfig
2.安装应用服务
通过集成工具,一次性安装所有应用服务https://lnmp.org/auto.html
wget : 通过网络下载文件
./install.sh 可执行文件脚本
yum install xxxx 在线单个安装某个软件

安装结果验证
通过tail 查看安装日志文件最后几十行 : tail -30 lnmp-install.log
通过cat more less head查看文件内容
通过如下命令行检查服务是否正常
3、项目上传路径
Apache的配置文件作用:告知部署人员,项目文件应该存放的位置、端口、主机域名等信息,方
便前端请求的时候,后台的Apache服务直接根据配置文件找到对应的文件路径
可以按照默认的配置文件上传存放
可以根据自己的需求进行修改配置文件在上传存放
Apache虚拟主机配置文件名:httpd-vhosts.conf
配置文件存放位置:/usr/local/apache/conf/extra/httpd-vhosts.conf
- Apache配置文件的说明:

- 备注信息
# 1.确认上传的路径(按照讲义默认路径 /home/wwwroot/default/)
cd /home/wwwroot/default/
# 2.finalshell可以用rz上传
rz
# 3.解压缩
unzip egoser.zip
# 解压到当前目录直接操作: unzip egoser.zip
# 4.修改权限,-R作用:让当前路径下所有文件的权限全部修改为指定权限
chmod -R 777 egoser/
4、数据库初始化
# 在linux进入数据库(数据库密码)
mysql -u root -p
# 查看当前mysql有哪些数据库
show databases;
# 创建数据库egowx并设置编码方式和排序规则(utf8_general_ci)
create database egowx charset utf8 collate utf8_general_ci;
# 方式一:恢复备份文件(在linux下面操作:需要输入数据库密码)
mysql -u root -p egowx < /home/wwwroot/default/egoser/ego.sql
# 方式二:恢复备份文件(在mysql下面操作)
# 使用(打开)数据库
use egowx;
# 导入备份好的sql文件
source /home/wwwroot/default/egoser/ego.sql;
# 查看某数据库下有哪些表
show tables;
# 退出数据库
exit;
- 1、Navicat远程连接数据库服务器方式
grant all privileges on *.* to `root`@`%` identified by 'root';
flush privileges;

- 2、关闭iptables的限制
systemctl stop firewalld;
systemctl stop iptables
systemctl disable iptables
在linux输入以上命令后,可以直接在navicat中通过常规方式连接linux的数据库
5、配置apache和项目文件
Apache应用服务的配置
项目本身的配置文件
- 修改Apache配置文件
# 进入Apache配置文件路径
cd /usr/local/apache/conf/extra/
# 重命名原有的配置文件
mv httpd-vhosts.conf httpd-vhosts.confd
# 上传新配置文件
rz
# 重启Apache服务
systemctl restart httpd
# 查看Apache的服务状态
systemctl status httpd
- 修改项目配置文件
找到配置文件/home/wwwroot/default/egoser/application/extra
使用vi编辑wx.php文件修改对应APPID和APPSecret(自己申请的),并且保存退出
- 重启应用服务
目的:修改后的配置立即生效
#重启Apache服务
systemctl restart httpd
#重启mysql服务
systemctl restart mysql
通过浏览器验证重启后的服务是否正常
其中一个接口地址:http://虚拟机IP/api/v1/banner/1
6、虚拟域名作用
作用:因为小程序无法直接和后台进行通讯,需要借助于微信客户端,但是微信客户端无法识别具
体的IP地址,所有需要修改本地的hosts配置文件,让本地请求的“假域名”优先找本地地址,指定本
地的服务器IP
- Windows如何修改
路径 : C:\Windows\System32\drivers\etc\
修改:hosts文件
# 最后一行增加内容如下
虚拟机ip地址 e.cn
软件质量题型
软件测试的质量特性有哪些
功能性、可靠性、易用性、性能效率、安全性、兼容性、可维护性、可移植性
1、针对杯子如何测试
查看杯子外观;用水杯装水看漏不漏水;看能不能喝到;杯子材质是否达到安全标准级别;杯子从不同高度落下的损坏程度;
杯子从不同的地方和温度的环境下是否可以正常使用;杯子是否可以容纳其他液体(果汁、酒精);
杯子装热水会不会变形,是否有防滑措施;将杯子盛满水放24小时检查是否漏水;
装热水杯子是否烫手;装冷水会不会很冻手;放在不同形状的承载物上是否会倒;
2、设计登录页面测试用例
1. 功能测试
正确登录:输入正确的用户名和密码,验证是否能成功登录。
错误登录:
输入错误的用户名或密码,验证是否提示错误信息。
输入空用户名或密码,验证是否提示必填项。
密码可见性:点击“显示密码”按钮,验证密码是否可见。
记住我:勾选“记住我”,验证下次登录时是否自动填充用户名和密码。
忘记密码:点击“忘记密码”,验证是否能跳转到密码重置页面。
注册功能:点击“注册”链接,验证是否能跳转到注册页面。
第三方登录:验证通过第三方平台(如Google、Facebook)登录是否正常。
2. 界面测试
布局:验证页面布局是否符合设计,元素是否对齐。
文字:验证文字内容、字体、大小、颜色是否正确。
按钮:验证按钮是否可用,状态是否正常(如禁用、悬停、点击)。
输入框:验证输入框的提示文字、大小、位置是否正确。
错误提示:验证错误提示信息是否清晰、位置是否正确。
3. 性能测试
响应时间:验证登录操作的响应时间是否在可接受范围内。
负载测试:验证多用户同时登录时,系统是否稳定。
压力测试:验证系统在高并发登录时的表现。
4. 安全性测试
密码加密:验证密码是否加密传输。
SQL注入:验证输入框是否对SQL注入攻击有防护。
XSS攻击:验证输入框是否对XSS攻击有防护。
登录失败限制:验证多次登录失败后是否锁定账户或增加验证码。
会话管理:验证登录后会话是否安全,退出后会话是否销毁。
5. 兼容性测试
浏览器兼容性:验证登录页面在不同浏览器(如Chrome、Firefox、Safari、Edge)中的表现。
设备兼容性:验证登录页面在不同设备(如PC、手机、平板)上的显示和功能是否正常。
分辨率兼容性:验证登录页面在不同分辨率下的显示效果。
6. 用户体验测试
易用性:验证登录流程是否简单直观。
错误提示友好性:验证错误提示是否清晰易懂。
键盘操作:验证是否支持键盘操作(如Tab键切换、Enter键提交)。
3、设计百度首页的测试用例
一、功能测试
1. 搜索功能
用例 1:输入关键字(如 "软件测试"),点击“百度一下”按钮,验证搜索结果页面是否正确显示。
用例 2:输入空关键字,点击“百度一下”按钮,验证是否提示“请输入查询词”。
用例 3:输入特殊字符(如 !@#$%^&*()),验证搜索结果的正确性。
用例 4:输入超长字符串(如 1000 个字符),验证搜索功能是否正常。
用例 5:点击“百度一下”按钮后,验证页面是否跳转到正确的搜索结果页。
2. 搜索建议
用例 6:输入关键字时,验证是否显示搜索建议列表。
用例 7:点击搜索建议中的某一项,验证是否跳转到对应的搜索结果页。
3. 语音搜索
用例 8:点击语音搜索按钮,验证是否弹出语音输入界面。
用例 9:使用语音输入关键字,验证搜索结果是否正确。
4. 图片搜索
用例 10:点击“图片”链接,验证是否跳转到图片搜索页面。
用例 11:在图片搜索页面输入关键字,验证图片搜索结果是否正确显示。
5. 新闻搜索
用例 12:点击“新闻”链接,验证是否跳转到新闻搜索页面。
二、UI 测试
1. 页面布局
用例 14:验证百度 Logo 是否显示在页面顶部中央。
用例 15:验证搜索框是否位于页面中央。
用例 16:验证“百度一下”按钮是否位于搜索框右侧。
2. 响应式设计
用例 17:在不同分辨率(如 1920x1080、1366x768、移动端)下,验证页面布局是否正常。
用例 18:在移动设备上,验证页面是否适配屏幕大小。
3. 字体和颜色
用例 19:验证页面字体、颜色是否符合设计规范。
用例 20:验证链接的悬停效果是否正常。
三、性能测试
1. 页面加载速度
用例 21:验证页面加载时间是否在 2 秒以内。
用例 22:验证页面资源(如图片、CSS、JS)是否加载完成。
2. 搜索响应时间
用例 23:验证搜索结果的响应时间是否在 1 秒以内。
用例 24:在高并发情况下,验证搜索功能的响应时间是否正常。
四、兼容性测试
1. 浏览器兼容性
用例 25:在 Chrome、Firefox、Safari、Edge 等主流浏览器中,验证页面功能是否正常。
用例 26:在 IE 11 中,验证页面是否正常显示。
2. 设备兼容性
用例 27:在 Windows、macOS、iOS、Android 等不同操作系统中,验证页面功能是否正常。
用例 28:在平板设备上,验证页面布局是否正常。
五、安全测试
1. XSS 攻击
用例 29:在搜索框中输入 XSS 攻击脚本(如 <script>alert('XSS')</script>),验证是否被过滤或拦截。
2. SQL 注入
用例 30:在搜索框中输入 SQL 注入语句(如 ' OR 1=1 --),验证是否被过滤或拦截。
3. HTTPS 加密
用例 31:验证页面是否使用 HTTPS 协议,确保数据传输安全。
六、异常测试
1. 网络异常
用例 32:在网络断开的情况下,验证页面是否显示“网络不可用”提示。
用例 33:在网络延迟较高的情况下,验证页面加载是否超时。
2. 服务器异常
用例 34:模拟服务器返回 500 错误,验证页面是否显示友好的错误提示。
用例 35:模拟服务器返回 404 错误,验证页面是否显示“页面未找到”提示。
七、用户体验测试
1. 快捷键支持
用例 36:验证是否支持快捷键(如按 Enter 键触发搜索)。
用例 37:验证是否支持 Tab 键切换焦点。
2. 无障碍访问
用例 38:验证页面是否支持屏幕阅读器。
用例 39:验证页面是否支持键盘操作。
4、用户开户的功能测试点
功能测试:
1、基本信息填写
姓名、身份证号、手机号、验证码是否强制填写
身份证号格式校验(18位,包含校验位)
手机号格式校验(11位数字,符合运营商号段)
2、验证码
短信/邮箱验证码发送成功率(不同运营商、网络环境)
验证码有效期测试(如5分钟内有效,超时后提示重新获取)
验证码错误处理(连续错误3次锁定账户30分钟)
验证码防刷机制(60秒内禁止重复获取)
3、安全信息设置
密码复杂度校验(至少8位,含大小写字母+数字+特殊符号)
密码一致性校验(两次输入不一致时提示错误)
密码可见性切换(明文/密文显示功能)
交易密码与登录密码是否允许相同(根据合规要求设置)
4、开户结果反馈
成功开户后跳转至账户首页,并发送成功通知(短信/APP内消息)
开户失败时明确提示原因(如“身份证已注册”“手机号绑定超限”)
异常场景测试:
断网时填写表单,恢复网络后自动保存已填信息
使用已注册的身份证/手机号重复开户
同一设备多账号注册检测(如限制单设备最多绑定3个账户)
超长输入(如姓名输入500字符,触发自动截断)
安全性测试
敏感信息加密传输(HTTPS抓包验证)
密码存储安全性(数据库密文存储,非明文)
实名认证合规(调用公安系统接口核验身份证真实性)
用户协议勾选强制要求(未勾选时禁止提交)
隐私政策弹窗(首次开户时必读,需手动确认)
兼容性测试:
1、Android/iOS/鸿蒙不同版本
2、第三方服务兼容
短信网关兼容性(移动/联通/电信/虚拟运营商)
身份证核验接口稳定性(模拟公安系统响应超时)
性能测试:
1、压力测试
模拟100用户并发开户(检查响应时间≤2秒,错误率≤1%)
验证码接口吞吐量(≥200请求/秒)
2、稳定性测试
持续开户操作12小时,监测内存泄漏情况
用户体验测试:
1、流程流畅度
步骤引导清晰性(如进度条显示当前步骤1/3)
错误提示友好性(如“身份证号格式错误,请检查第18位校验码”)
2、无障碍支持
屏幕朗读功能适配(盲人用户可操作开户流程)
色弱模式对比度(文字与背景色对比度≥4.5:1)
5、判断三个整数能否构成三角形?
正常:(两边之和大于第三边)两边之差小于第三边 三边相等;两边相等;三边不等且大于零
边界情况:(1,1,1)(两边之和小于第三边)(1,1,2)
异常情况:输入0、负数、三边为负数
6、文件上传与下载
文件上传:
根据系统要求对文件类型、文件大小进行校验,可以从等价类、边界值分析;
正常:上传单个文件;上传多个文件批量上传;中途取消上传文件;上传文件是否能正确打开;上传同名文件是否提示覆盖同名文件;按不同文件类型上传;
异常:上传已被损坏的文件;上传一个正被其他程序使用的文件;网络异常,重新联网,文件是否支持断点续传;上传错误的文件类型,是否提示上传失败
边界值:上传0kb文件;验证文件的文件名称数的最小值、最大值以及特殊字符(空格);上传文件数超过最大值时提示;
安全测试:上传含有木马的文件;
页面测试:页面校验(页面美观易用、按钮、文字是否正确)
文件下载:
正常:
下载单个文件;批量下载文件;取消下载;重复下载同一文件;下载过程中,暂停下载;
单击是否提示下载还是打开页面;对于下载到本地的文件是否正确打开/检查是否与原文件一致;直接打开的页面文件是否正常显示;
下载次数是否被记录;
异常:本地磁盘空间不足,提示下载失败;网络异常,重新联网,文件是否支持断点下载;
7、贪吃蛇
蛇的移动:
基本方向: 验证蛇能正确向上、下、左、右四个方向移动(初始方向通常是右)。
方向切换:
验证可以随时按有效方向键改变蛇头方向(除反方向外,如向右时不能立即向左)。
验证快速连续按键时,蛇的转向逻辑正确(通常只响应最近一次有效按键)。
验证在蛇身体较长时,转向是否流畅、有无卡顿或穿模。
速度: 验证蛇以恒定且合适的速度移动(或按关卡递增速度)。
边界移动:
穿墙模式: 验证蛇从一侧边界移出会从对侧边界移入。
撞墙模式: 验证蛇头碰到任何边界即判定游戏结束。
食物生成:
位置: 验证食物每次随机生成在游戏区域内(非蛇身体占据的位置)。
唯一性: 验证同一时间游戏区域内有且仅有一个食物存在(吃掉后才生成下一个)。
视觉效果: 验证食物有清晰可见的标识(颜色、形状)。
吃食物 & 成长:
碰撞检测: 验证当蛇头移动到与食物完全重合的位置时,判定为吃到食物。
增长逻辑: 验证蛇吃到食物后,立即在蛇尾增加一节(或按规则增加),长度+1。
分数增加: 验证吃到食物后,分数按规则增加(如每吃1个+10分)。
食物消失: 验证吃到食物后,当前食物立即消失,并生成新食物。
碰撞检测 (自身 & 边界):
自身碰撞:
验证蛇头碰到除尾部最后一节外的任何自身身体部分时,游戏结束(尾部在移动时会离开,通常不算碰撞)。
边界情况:验证蛇在高速移动或快速转向时,自身碰撞检测是否准确。
边界碰撞: (如果采用撞墙模式) 验证蛇头碰到任何边界线时,游戏立即结束。
8、蓝牙耳机
蓝牙配对:
耳机是否正确进入配对模式,并被不同设备搜索到;
连接成功后,是否可以手动或自动连接设备;
耳机开机,是否能自动与上一次配对的设备进行连接;设备开机后,耳机能否连接回该设备;
在有效距离内,不同角度,有障碍物的情况下,连接是否稳定,音频是否流畅无断续;
是否支持同时连接多个设备;
在其他蓝牙设备的干扰下,连接和音频质量是否受影响;
耳机是否能保存多个设备的配对信息;能够正确删除单个或者所有配对信息;
耳机未连接成功是否超时退出配对模式;
音频播放场景:
基本播放控制:物理触控是是否能控制播放、暂停、下一首、上一首?响应是否灵敏和准确
在播放过程中,低电量提示是否出现提示音
音频质量的最大音量和最小音量的验证
通话场景:
有来电时,耳机是否能及时、清晰的发出铃声;
使用物理触控能否实现接听、挂断、拒接
接听后,通话是否成功建立连接
麦克风拾音和听筒放音质量的验证
9、微信查看朋友朋友圈,接口的参数和测试用例怎么设计
查看陌生人朋友圈:填写陌生人ID 返回空列表
查看好有朋友圈:填写朋友ID 返回所有朋友圈内容(前提是该朋友未设置xx天可见或者有发朋友圈)
查看被屏蔽用户的朋友圈:填写屏蔽人ID 返回空列表
查看屏蔽自己的用户的朋友圈:填写屏蔽当前用户ID 返回空列表
查看已注销用户的朋友圈:填写注销用户ID 返回“用户不存在”
正常翻页:lastid=上页最后一条ID,返回下一页数据
无lastid:lastid为空,返回默认xx条数据
targetID为空;targetID非数字;targetID不存在;targetID参数名错误;不添加targetID参数;lastid参数名错误
目标用户无朋友圈;朋友圈设置三天可见/一个月可见;当前用户被拉黑;
10、微信朋友圈的点赞
正常:点赞和取消点赞的正常使用;点赞后下方是否正常显示头像;取消点赞后显示的头像消失;
点赞后的头像是否按时间顺序排列;是否支持多次点赞;一条朋友圈所支持的点赞人数;
点赞后是否提醒被点赞用户;用户点赞过的朋友圈被微信好友点赞时是否会通知用户;
点赞后可见分组好友是否可见,其他是否不可见;
异常:断网进行点赞或取消点赞;
易用性:排版、按钮正常,无错别字;界面美观;点赞一行最多显示多少个用户头像;最多显示多少行;
兼容性:不同的移动设备:Android、IOS;不同的OS:windows、Mac;
11、微信朋友圈
发布朋友圈:
纯文字(空、一个、上限字符、超长文字);纯图片(一张、九张、超过九张提示、预览/编辑/旋转/删除)
纯视频(短视频、长视频、损坏视频、超长视频限制、预览/编辑/旋转/删除);是否支持发布实况
位置信息(添加位置、不显示位置、自定义位置);@提醒谁看(公开、私密、部分可见,不给谁看)
发布过程:
编辑状态下保存(再次进入是否恢复);发布中断网(草稿保存,恢复后继续发布);
取消发布;发布成功进入朋友圈;发布失败提示;发布内容为空提示;
发布时出现敏感词、违禁词提示;发布内容过长提示;
查看朋友圈:
时间倒序,最新发布的在最上面;不同类型内容正常显示;图片/视频加载正确;是否可点击图片/播放视频/查看实况
位置信息显示正常和点击跳转地图;发布者头像、昵称显示以及点击跳转个人主页;发布时间显示;
下拉加载最新内容;上滑展示更多内容;朋友圈广告显示、关闭按钮、点击跳转是否都正常;
点赞/评论:
点赞后/取消点赞后图标状态变化;点赞后/取消点赞后下方是否显示/删除用户头像;是否支持重复点赞;
点赞后下方用户头像是否按时间顺序排列;
网络中断是否支持点赞或取消点赞;
发布评论(纯文字、纯表情,表情+文字、图片);评论成功(用户头像显示在下方;
通知发布者或之前已经点过赞或者评论过得用户);评论字数限制;
删除评论(删除自己的评论;发布者删除他人的评论);评论列表显示按时间顺序排列;
回复评论(在评论下进行回复,通知被回复者);
点击评论者头像跳转;网络中断时评论或者删除评论;
12、优惠券
用户进入活动页/商品栏领取,成功领券提示;平台自动发放;达到个人限领张数提示“已领完/已抢光”;
允许重复领取同类型券;验证到期前一天推送消息提醒
优惠券显示正常(券类型、金额、有效期)
购物车自动勾选最优券/手动切换优惠券;订单金额小于门槛券时不可用;使用优惠券计算是否正确;
多张券组合使用(满减券+无门槛券)
订单页面显示优惠券抵扣金额(计算是否正确);部分退款,按比例退回券金额;
全额退款,优惠券退回用户账户,过期券退款时不退回
已过期券在我的优惠券页面已不存在;
高并发领券,验证接口响应时间&服务器资源监控
13、微信二维码扫码支付
扫码:过期码/涂改过的扫码校验;二维码尺寸/清晰度/完整性扫码校验;使用不同品牌手机/手机像素扫码校验
二维码扫描距离/角度阴暗、高亮环境下校验;没网的状态下扫码校验;多人同时扫码校验;同时识别到多个二维码校验;
二维码扫描信息正确;
输入金额:输入金额上下限校验;输入金额为空;账户余额不足校验;单笔超出上限;当日超出上限
输入密码/指纹:密码是否加密处理,为空以及长度校验;密码错误提示错误次数上限校验;
指纹支付;验证本人未输入/已输入的指纹;指纹错误验证次数上限校验;取消支付;
余额不足切换银行卡支付;
金额:输入金额,支付金额 扣款金额一致性校验;扣款后余额校验;查看账单详情校验;
14、一支笔
外观测试:外观的大小是否影响携带和存放;笔身印的图标是否正确;笔芯对应颜色是否正确;
功能测试:笔筒开合是否流畅;笔芯的替换是否方便;与笔芯的结合是否牢固;
性能测试:笔芯的寿命是否符合一般人的使用时间;
用过的笔芯在纸上是否会扩散,墨水干的速度是否符合要求;高温和低温对笔的影响;
有汗水时,握笔的地方是否会变的易滑动;连续书写一分钟以上是否书写流畅
安全测试:笔身的材料是否易燃,是否对人体有害;笔身的硬度是否能承受正常的握力;笔芯材料是否无毒
场景:笔尖从空中垂直下落,笔芯是否能正常书写;笔倒放笔芯墨水是否会流出;沾上水笔芯是否会晕开;在不同材质的纸笔是否能正常书写;
15、电梯
电梯内:分楼层键是否正常;开关门键是否正常;报警键是否正常;
同时关注显示屏:电梯内外显示屏显示的电梯层数和运行方向是否相同
有障碍物时,电梯门的感应系统是否有效
当电梯当前状态是上行时,有人在X楼按下上升/下降键,电梯是否会停止;
当电梯当前状态是下行时,有人在X楼按下上升/下降键,电梯是否会停止;
在搭载满员的情况下,如有人在X楼按下上升/下降键,电梯是否会停止;
界面测试:查看电梯的外观,按钮的图标显示、大小;电梯内部张贴的说明是否清晰可见且包含中英文;
易用性测试:楼层的按键高度,电梯是否有空调、通风条件、手机信号是否流畅;电梯是否有扶手;
安全测试:下坠是否有制动装置;暴力破坏电梯是否报警;超重是否报警;超时自动关门;
停电情况下电梯是否有应急电源装置
性能测试:测试电梯负载单人/多人时的运行情况;一定人数下较长时间的运作;更长时间运作时的运行情况
不断增加人数导致电梯报警;
16、用户登录接口
针对这个登录接口,我会从正向功能、逆向功能异常、数据异常和参数异常四个维度来设计用例
正向:输入正确的手机号和密码 预期结果:响应状态码200,响应体包含code:200和有效的token
逆向:输入正确的手机号,错误密码 预期结果:响应状态码200,但code:非200 响应体提示:密码或手机号错误
输入未注册的手机号 预期结果:响应状态码200,但code:非200 响应体提示:密码或手机号错误
数据异常:手机号为空 响应状态码400 提示用户名或密码不能为空
密码为空 响应状态码400 提示用户名或密码不能为空
手机号>11 响应状态码400 提示手机号格式不正确
密码输入一个字符或者1000个字符 响应状态码400 提示密码长度在8-16位
密码仅输入数字/字母/特殊字符 响应状态码400 提示密码包括字母数字特殊字符
密码数字/字母/特殊字符两两组合 响应状态码400 提示密码包括字母数字特殊字符
参数异常:缺少手机号参数 响应状态码400
缺少密码参数 响应状态码400
多传额外参数 忽略多余参数不进行处理
将手机号传为字符串类型 响应状态码400 提示手机号格式不正确
17、查询题库接口
针对这个查询题库接口,我会从正向功能、逆向、数据异常、参数异常和业务权限四个维度来设计用例
正向:必选参数:按年级学科查询 响应状态码200,返回题目列表;
组合参数:指定教材题型,响应状态码200,返回对应年级科目的题型;
全部参数:难度,响应状态码200,返回对应年级科目的相同难度的题型
逆向:年级边界值 gradeG0;响应状态码400 提示G0年级不存在;
科目不存在 响应状态码400 提示科目不存在
题型/难度 响应状态码400 提示题型/难度不存在
缺少年级/科目参数 响应状态码400 提示缺少年级/科目参数
年级学科难度组合参数 响应状态码400 提示难度不存在
多传额外参数 忽略多余参数不进行处理
业务权限:小学账号请求初中资源 响应状态码403 提示: "无权限访问该年级资源"
18、发布试卷
针对这个发布试卷接口,我会从正向功能、逆向(数据异常、参数异常和业务规则)四个维度来设计用例
正向:成功发布试卷 响应状态码200 返回试卷ID,检查数据库是否存在该试卷记录,且题目关联正确
未选教材使用默认人教版教材 响应状态码200,返回人教版题目列表
逆向: 题目ID不存在 状态码400 错误信息:题目ID无效
在数学试卷加入英语题目ID 状态码400 错误信息:题目与试卷科目不匹配
题目数量0道 状态码400 错误信息:题目数量不能为0
试卷名称重复 状态码400 错误信息: "试卷名称已存在"
在小学试卷中混入一个初中题ID 状态码400 错误信息:题目与年级不符
逻辑思维题
项目部署至linux
1、安装和配置Mysql(开启Mysql远程连接权限;打通防火墙;使用navicat通过IP地址链接到Linux系统)
2、安装apache tomcat服务器
3、部署后端文件
将打包的.war文件传输到linux下的tomcat的webapps中
在navicat初始化sql文件
服务器DNS解析配置: 编辑/etc/hosts文件增加IP地址和域名配置
修改客户端DNS解析:使用管理员模式编辑hosts文件最下方增加IP地址和域名配置
4、部署前端代码
上传前端代码到Linux系统,移动代码到/usr/local目录下
安装前端代码运行环境node.js(因为使用的node.js和vue.js开发)移动node.js的文件夹到/usr/local下 配置 node.js的环境变量
进入前端代码目录,编辑env的配置(前端代码连接后端的配置)
启动前端代码,给前端代码授权chmod 777 -r ./
在windows的hosts文件配置前端DNS
验证结果:在本地电脑通过浏览器输入域名192.168.85.139:8080访问
1、查看实时操作日志
tail -f /usr/local/apache-tomcat-8.5.63/logs/catalina.out
2、出现bug,怎么判断是前端,还是后端出现了问题?
我一般首先检查后端是否有问题
使用tail -f /usr/local/apache-tomcat-8.5.63/logs/catalina.out来实时查看日志
查看是否有error/exception,查看到error/exception在深入定位bug的具体位置
再检查前端,打开开发者工具,检查API请求状态,查看response内容,console标签
AI智习室
1. 二套数据驱动模板的具体应用?
登录模版:验证身份认证系统的可靠性(设计正确的手机号和密码;手机号不存在/超过11位/超长密码;参数错误;)
查询题库模版:确保教学资源匹配的精准性(年级+科目;年级+科目+教材;年级+错误科目;)
发布试卷模版:保障试卷组织的教学精准性
2. 登录模块最复杂的3个场景?
验证码防重放攻击:同一验证码10分钟内仅允许使用1次(使用requests_mock模拟多次提交)
弱密码策略校验:密码需包含数字+字母,长度≥8位;
3. 如何解决token传递问题?
针对登录标识的传递;
会话级 Fixture + 动态 Cookie 管理:在公共层中定义get_header()创建全局会话对象session,调用登录接口提取sessionid,注入会话头
4. 教材版本变更如何维护?
动态数据维护策略:会有开发每周执行教材版本爬虫,如果教材变更后,在数据驱动新增测试用例
5. Allure报告如何定位问题?
参数标记:在报告中高亮显示异常参数组合;
自动对比实际响应与预期值差异
6. 自动化测试的执行报告和测试报告有哪些内容?
我们公司的执行报告会详细记录:
基础信息:测试任务名称、环境(测试/生产)、执行时间、执行机器、测试框架版本
执行概况:本次运行的测试模块、用例总数/通过率、失败用例的分类统计
失败用例详情:失败用例名称及所在模块 、错误类型(如接口超时、断言失败、脚本异常) 、失败截图/日志片段、资源消耗(执行总时长、cpu和内存占用峰值)
用途:记录自动化测试运行的技术细节,供开发/测试团队快速定位问题。
eg:在公司发现密码超长校验返回500错误(预期400),开发通过报告里的请求参数和日志快速复现并修复了问题;
二、测试分析报告关键组成
测试目的
质量概括:各模块通过率趋势图、自动化覆盖率变化、严重缺陷数量、与上一版本对比
缺陷分析:缺陷分布、高频缺陷类型、关联的缺陷管理工具缺陷单
风险预警:高风险模块、未覆盖场景
改进建议:需修复的缺陷优先级、测试用例补充建议
用途:汇总测试结果,评估版本质量,供产品决策。
我们公司的自动化测试报告分为两种:
执行报告:记录每次运行的详细数据,包括通过率、失败用例的请求响应对比等,主要用于开发排查问题。
测试报告:汇总版本质量,分析缺陷分布和风险,帮助产品决策是否发布。
我通过分析执行报告发现过密码校验缺陷,并在测试报告中建议加强边界值测试,最终提升了接口健壮性。
7. 在接口自动化测试中,你遇到的最大难点是什么?如何解决的?
在查询题库接口测试中,需要严格验证年级+学科组合匹配正确的题库资源。
但测试时发现:六年级数学混入初中题型
解决方案:
在数据文件中增加边界值用例,明确标记禁止出现的初中题型
在测试脚本的断言中加入题型黑名单检查,自动检测超纲题目
将测试结果截图发给开发,建议修复方案
成果:
该场景错误率从18%降为0
测试方案被推广到所有年级接口"
8. 为什么要对requests进行封装?
1、减少代码冗余,提高复用性
2、统一处理异常、增强代码健壮性
3、便于全局配置管理,降低维护成本
4、适配测试框架,支持扩展需求
9、发布试卷接口的难点?
在我们的发布试卷接口测试中,
曾发现接口返回成功(201),但数据库未生成试卷记录的严重BUG
通过校验关联表,发现了题型关联错误的问题(如小学题型关联了初中题目)
根据api文档,接口测试时如果出现异常,如何排查
1、我会优先排查参数问题
2、其次检查权限控制
3、环境配置问题
以AI智习室的登录接口为例:
在测试登录接口出现403的异常,首先检查请求参数发现缺少token字段,补充token字段后重新发起请求,但异常依旧,
查阅API文档,对比请求头和请求体参数,发现填写的token值不匹配。重新获取正确的token值,比较两者的token,并再次发起请求,最终请求成功。
遇到一个不能稳定复现的 API Bug,如何解决?
如果我遇到一个不能稳定复现的 API Bug,我会先确认 bug 的现象和影响范围,
然后打印日志、查看接口请求记录,特别关注异常时的请求参数和系统状态。
接着会尝试复现,在此过程中我会重点分析是否与外部依赖或环境不一致有关。
必要时我会联系开发协助排查bug
AI智习室家长登录接口偶发500错误,重试后又能成功登录;
在返回500错误时 提示:数据库连接异常;
深度分析日志发现:DB Connection Pool Exhausted的error错误
关注登录接口异常时填写的手机号和密码是否有误,请求头的token是否已过期;
复现时准备之前相同的测试数据和网络环境;
当时联系开发一起协助排查,最后发现是因为测试环境的数据库连接池过小导致的500错误。
双师1对1
1. 定向Monkey测试
1、获取当前运行的Activity信息:adb shell dumpsys window | findstr mCurrentFocus
2、构造精准Monkey命令:
adb shell monkey \
-p com.education.app \ # 限定目标包名
-c android.intent.category.LAUNCHER \ # 允许启动类组件
-c android.intent.category.MONKEY \ # 允许Monkey组件
--pct-touch 90 \ # 90%触摸事件(适合诊断页面)
--pct-motion 10 \ # 10%手势事件
--pct-appswitch 0 \ # 禁止跳转其他页面
--pct-syskeys 0 \ # 禁用系统按键(防止退出)
--pct-nav 0 \ # 禁用导航事件
--pct-majornav 0 \ # 禁用主要导航
--throttle 300 \ # 事件间隔300ms(模拟真人操作)
--ignore-crashes \ # 忽略崩溃继续执行
--ignore-timeouts \ # 忽略ANR继续执行
-s 2023 \ # 固定随机种子(便于复现)
-v -v -v \ # 最高级别日志
10000 # 事件数量
3、写一个动态监控Activity栈的shell脚本(关键!):
在git bash启动该脚本文件:无限循环实时监控是否跳出目标页面)
adb shell "while true; do # 在设备端启动无限循环
dumpsys window windows | grep subjectDiagnosisActivity || { # 检查当前Activity
echo '[ERROR] 跳出目标Activity!时间:$(date)' # 如果未匹配到目标Activity
adb shell am start -n com.education.app/.diagnosis.subjectDiagnosisActivity # 自动重启目标Activity
}
sleep 1 # 每1秒检查一次
done" > activity_monitor.log &
# 输出日志到文件并后台运行
2、在学科诊断自动化测试中,你遇到的最大难点是什么?如何解决的?
比如在测试五年级数学诊断时,系统随机生成3道多选题连续出现,传统脚本会因选项数量变化而崩溃
最大的难点是处理诊断过程中的动态多题型组合;
动态多题型组合场景:
诊断过程随机出现单选+多选+跳过的组合
多选题型选项数量不固定(2-5个选项)
技术挑战:传统PO模式无法动态识别题型;多选操作后断言状态不稳定
解决方案:我采用 "动态识别题型+分层处理" 策略:
1、在utils工具类定义题型识别器:动态识别当前题型
2、重构Page层业务方法:定义动态题型处理器,根据返回的题型调用不同题型方法
3、增强断言机制:重构utils中的断言方法:动态题型后显示等待状态稳定
成长体现:
作为新人,这次经历让我深刻理解:自动化测试不仅是模拟操作,更需要模拟真实场景的随机性。我现在会主动分析业务中的动态因素来设计测试用例"
3、怎么判定自动化测试中发现的bug是有效bug?
"当自动化脚本报告失败时,我会先手动复现3次。比如学科诊断中遇到'开始学习'按钮断言失败,我会检查:
是否是页面加载延迟导致?(调整显式等待时间)
元素定位器是否因UI改版失效?(更新XPath)
测试数据是否异常?(重新生成数据)
之前遇到过在使用公司测试wifi不稳定导致诊断结果提交超时,实际是环境问题而非Bug"
4、Monkey测试和自动化测试的区别?
| 维度 | Monkey测试 | 自动化测试 |
|---|---|---|
| 测试目的 | 随机暴力测试,发现隐藏崩溃/ANR | 验证预设功能逻辑,保障核心流程正确性 |
| 执行逻辑 | 无脑随机操作(点击/滑动等) | 按脚本预设步骤执行 |
| 适用阶段 | 早期稳定性测试 | 回归测试/冒烟测试 |
| 技术实现 | 系统级命令(adb shell monkey) |
测试框架(Appium+Pytest等) |
| 典型工具 | Android Monkey, Maxim | Appium, Selenium, Jmeter |
| 缺陷发现类型 | 内存泄漏/崩溃/ANR | 功能逻辑错误/UI异常/数据不一致 |
| 维护成本 | 零成本(无需维护用例) | 高成本(需随需求更新脚本)维度 |
5、你们公司是怎么去定义Monkey压测的指标?
"在双师1对1项目中,Monkey压测指标分为三个层次:
基础稳定性:
崩溃率必须<0.1%,通过adb logcat实时监控
曾发现直播模块在连续2000次随机点击后出现内存泄漏,优化后达标
ANR发生率:0%发生率
执行标准:
事件总数;执行时长;覆盖不同平板机型和安卓系统
资源消耗监控:
使用GT工具监控CPU和内存占用率
6、你对自动化的理解?
1、基于不同的业务,使用的不同技术手段,通过这些技术手段来推动公司或者这个项目的业务发展(app、接口和web端使用的技术栈)
2、根据公司的业务形态
7、为什么选择使用Appnium而选择uiautomatorviewer做自动化?
Appium是自动化测试框架,支持多平台和多语言,支持Xpath/ID/Class等方式,,而uiautomatorviewer仅限Android的UI元素查看器,仅展示基础属性
8、自动化测试中怎么处理发现的bug?
1、当自动化报告提交失败时,查看Allure附带的视频回放,查看日志,使用pytest装饰器flaky手动复现3次,确保问题稳定复现
2、将bug提交到缺陷管理系统,然后提供bug单给指定开发,以便他们及时修复;
9、你们会有多少台设备去执行自动化?
设备数量会根据项目需求和测试规模动态调整。例如,常规迭代可能使用5-10台设备(覆盖主流机型),而大版本发布或压力测试时会扩容至20-30台。
10、自动化测试的bug处理流程是怎么样的?
当自动化脚本报告失败时,打印日志,查看Allure的错误截图
使用pytest手动复现3次,确保问题稳定复现
在缺陷管理系统提交完整Bug报告,指派给指定开发;
开发修复后发给测试重新确认,已修复,关闭bug
11、自动化的bug平均有多少条?
在双师1对1项目中,自动化测试平均每个版本发现5-15条有效Bug
因为:
自动化用例集中在核心正向流程(如学科诊断的完整路径)
前置的代码审查/API测试拦截了大部分基础问题"
12、自动化测试,一个项目会占比是多少,然后研发真正解决了多少个?
占比25%-30%(精准覆盖学科诊断)比如双师1对1的用例数400多,然后自动化差不多有100多条;
缺陷解决率85%+:P0/P1级缺陷100%解决(如诊断结果错误,接口超时),剩余未解决的主要是低优先级优化项
13、新一版的apk进行Monkey稳定性测试会有大概多少崩溃/ANR的bug?
1、新版本首次Monkey测试(10万次事件)通常出现20+崩溃/ANR
2、如果是已经是进行了多次版本迭代的apk,最多5个左右崩溃/ANR
14、app端自动化具体的实例
学科诊断为例!
定义获取driver的get_driver类方法 该方法判断driver是否为空
定义字典变量并追加启动参数(platformName系统名、platformVersion系统版本、deviceName设备ID、appPackage、appActivity)
调用webdriver.Remote方法获取driver,设置隐式等待10s并返回driver
定义关闭app的driver对象的类方法,判断driver是否不为空;
定义智能文本断言方法,该方法try语句中包含显示等待定位元素赋值给success变量,否者进入except调用截图方法进行截图
封装日志类:定义get_log的类方法,创建日志器对象、设置日志打印级别、创建处理器对象(控制台对象和日志文件对象)、设置日志信息格式、给处理器设置日志信息格式、给日志器添加处理器
在pytest.ini配置--alluredir=./report参数,便于生成allure测试报告
2、base层:在初始化函数中调用get_driver方法,初始化driver对象,定义显示等待元素、点击、截图等基础方法
3、page层
定义诊断类:通过uiautomatorviewer元素定位器获取元素信息,然后使用ID/XPATH定位所操作的元素
定义业务方法:点击选择学科、点击开始诊断、前几步是定位学科基础情况,第二步是题型的判断,使用find_elements获取所有选项、根据random.chioce随机选择选项并点击,点击下一步/下一题,循环操作,直至诊断操作完成
4、脚本层
定义诊断测试类:使用pytest的类级别的初始化方法,在该方法内实例化诊断对象,然后再定义方法级别的初始化,每个测试方法前调用start_activity回到学科诊断首页
定义学科诊断测试方法:在try语句中调用page层start_diagnosis方法
使用工具类的智能文本断言方法验证返回结果,否则进入except调用attach将错误截图插入到测试报告并raise抛出异常
15、查看Allure测试报告哪些内容?
就拿学科诊断为例!
1、我会首先查看总览页的通过率趋势图,例如学科诊断模块的通过率从95%下降到85%,就需要立刻排查,
同时关注该模块的失败用例分布(失败用例分析的例子:发现过诊断结果断言失败,查看allure的截图:发现该页面是处于开始学习页面的上一个页面,检查测试方法,发现最后操作是提交多选题答案,检查logs:看到日志“多选题选项3点击失败”,最后发现Xpath定位器因UI改版而失效)
2、查看该模块的用例详情:检查答题过程中的视频,确认选项选择是否正确;查看操作日志是否有"元素未找到"异常记录
3、然后去查看环境信息:平板系统版本和app的版本
16、CI流程
在我之前的公司,我们的CI流程主要是基于Jenkins搭建的;
当开发人员将代码合并到特定的分支时,会触发Jenkins的自动构建任务;
构建成功后,会触发我们测试团队的自动化测试任务,主要运行我们编写的UI自动化测试和接口自动化测试;;
自动化测试执行完成后,我们会去查看Allure测试报告或者查看被推送到邮箱测试结果,重点关注通过率和失败用例。如果发现有失败的测试用例,我们会去分析是bug还是脚本问题。如果是bug,就提交到缺陷管理系统;如果是脚本问题,我们会及时修复自动化脚本;
场景:
Jenkins控制台显示诊断测试失败
查看Allure报告发现截图缺少'开始学习'按钮
对比开发提供的APK版本号,发现测试环境未更新
重新部署后测试通过"
车载
CAN总线是如何解决多个节点同时发送数据,即总线竞争的问题?
通过仲裁帧判断
对车载测试的了解程度?
测试方式的不同:全仿真、半仿真、台架、整车、路测
测试工具的不同:Canoe、CANalyzer
测试方向:智能座舱测试(中控、仪表、车灯、车辆设置(行车电脑、灯光设置、车辆诊断))
智能座舱OS(ONX、Linux、android)
国产车载OS(aliOS、小度OS、鸿蒙OS)
CAN总线协议(主流的总线协议、CAN总线的优点、CAN线、CAN信号、数据帧组成)
实习经历问题
1、你们公司有几套环境?
测试环境:专门提供给测试人员使用
开发环境:开发人员使用
生产环境:提供给用户
预生产环境:设置和数据是一样.
2、你印象最深的 bug 是什么?你实习中遇到的最大的问题是什么,你是怎么解决的?
我印象深刻的Bug,涉及到金赢在线项目中首页模块图片上传和展示的问题。
Bug描述:
在首页模块中,用户可以通过平台上传图片。然而,在测试过程中,我发现当上传的图片尺寸过大时,首页展示的图片会出现拉伸变形的情况,导致图片内容显示不完整,影响了用户体验。
在实习期间,我遇到的最大的问题是在金赢在线手机项目的首页模块中,图片上传和展示的Bug。这个Bug让我印象非常深刻,因为它不仅影响了用户体验,还涉及到了前后端的协同工作。
(具体表现:)
图片尺寸问题:当上传的图片尺寸超过系统预设的最大尺寸(例如1920x1080像素)时,图片在首页展示时会被强制拉伸,导致图片变形。
内容显示不完整:由于图片被拉伸,部分关键信息(如行情数据、市场资讯等)被裁剪或变形,用户无法完整看到图片内容。
响应式布局问题:在不同分辨率的设备上(如手机、平板等),图片的展示效果不一致,部分设备上图片变形更加严重。
问题原因:
经过与开发团队的沟通,发现问题的根本原因是:
前端未对图片进行自适应处理
后端未对图片尺寸进行限制
解决过程:
Bug提交:我通过禅道提交了该Bug,详细描述了问题的表现和复现步骤,并附上了截图和日志信息。
与开发团队沟通:我与前端和后端开发人员进行了沟通,明确了问题的根本原因,并提出了解决方案建议。
回归测试:在开发团队修复问题后,我进行了回归测试,确保图片上传和展示功能在所有设备上都能正常显示,且图片不再出现拉伸变形的情况。
双师1对1的这个项目吧
在进行学科诊断的脚本开发初期,在page层只定义了一套业务方法,然后组长建议我几套业务方法,要不然根本无法提升测试覆盖率;我首先根据测试用例去熟悉该模块的功能,发现该模块涉及多选、跳过、添加图片、重新诊断等复杂场景,然后我就去添加了上述场景的业务方法
3、简述你在实习的工作内容,比较熟悉什么?
在接口功能测试中,我使用Postman工具对系统的接口进行测试,验证接口的请求和响应是否符合预期。
UI兼容性测试:在不同浏览器、不同设备上测试系统的UI展示效果,确保UI在不同环境下的一致性。
移动端测试
App功能测试:对移动端App进行功能测试,确保各个功能模块按照需求正常工作。
兼容性测试:在不同型号的手机、不同操作系统版本上进行兼容性测试。
稳定性测试:使用monkey命令进行稳定性测试,验证App在高强度操作下的稳定性。
支持团队工作:环境搭建、测试数据准备、测试执行
参与团队讨论:参与团队的日常站会、需求评审、测试用例评审等
使用JMeter进行一些简单的性能测试和参与编写简单的自动化测试脚本
冒烟测试:在每次新版本发布前,执行冒烟测试,确保基本功能正常,避免严重问题进入测试环境。
在测试过程中,我深刻体会到对用户需求的准确理解至关重要。只有完全理解需求,才能设计出有效的测试用例,确保系统功能的正确性。此外,我也熟悉缺陷管理流程,能够通过禅道等工具提交和跟踪缺陷,确保每个问题都能得到闭环处理。
我过去的主要工作是系统测试和自动化测试。
在系统测试中,主要是对系统的业务逻辑功能,以及系统的特性进行测试。
性能测试中,主要是进行的压力测试,在各个不同数量请求的情况下,获取系统响应时间以及系统资源消耗情况。
自动化测试主要是通过自己写脚本以及一些第三方工具的结合来测试的特性测试。
在测试中,我感觉对用户需求的完全准确的理解非常重要。另外,就是对BUG的管理,要以需求为依据,并不是所有 BUG 均需要修改。
测试工作需要耐心和细致,因为在新版本中,虽然多数原来发现的BUG得到了修复,但原来正确的功能也可能变得不正确。因此要注重迭代测试和回归测试。
4、你们公司有上线流程吗?
有的;
测试完成与准出:
当一个版本的测试达到尾声时,我们首先会确保:
严重级别以上Bug必须修复并通过验证
测试团队会输出详细测试报告,清晰地说明测试范围、结果、遗留问题以明确的测试结论和建议
上线评审会:我们会组织开发、测试、产品、项目经理等相关方召上线评审会议
上线实施与监控,上线后验证与观察
工作问题
1、你的测试的职业发展是什么?
1、技术方面:我希望继续提升自己的测试基础能力,包括需求分析、用例设计、缺陷跟踪等全流程,同时深入团队使用的工具链(如自动化框架、持续集成平台)。通过参与公司项目,理解业务逻辑和技术架构,成为能独立负责模块测试的可靠成员。
2、大胆承认自己技术的不足:脚本的设计方面、性能测试方面、自动化测试等;
3、职业进阶角度:
首先未来1年内成长为中级测试工师:能够独立负责一个模块的测试工作,从测试用例的设计到自动化测试的执行;
未来三年内成长为高级工程师:那时候我对公司的业务有一定的了解,我希望那时候自己能够独立负责一个业务板块的测试;如果有可能带几个同事共同完成一个业务板块的测试;技术上未来3年内能够负责更深入的测试工作,比如在自动化测试的成长上,我希望能够帮助公司建立更完善的测试质量保证制度;对于我现有技术水平是不满足这些要求的,未来希望向测试开发方向发展,提升技术深度;
2、反问面试官相关问题
问我加班,回答后反问:公司加班的福利待遇怎么样呢?那公司的加班强度怎么样呢?
公司转正的标准是什么呢,转正比例是多少呢?试用期考核标准是怎么评估的,有没有绩效考核kpi标准?
公司这个部门目前的人员配置是怎么样的?有没有老带新?
转正的薪资能达到多少?
转正之后交不交五险一金?
公司想招一个什么样的人?
请问团队目前的测试流程是怎样的?
团队常用的测试工具和技术栈是什么?
目前团队负责的项目类型是什么?
对于实习生,是否有机会参与自动化测试或性能测试等专项任务?
团队如何评估测试覆盖率和质量?
团队在什么场景下会优先选择自动化测试?
团队在设计测试用例时是否有特定方法论?
3、对加班的看法,高强度工作下自己的调整方法
“我认为加班是项目推进中的正常现象,尤其在版本发布或紧急需求时,团队协作解决问题是必要的。但长期来看,我更倾向于通过优化工作方法(如提前规划测试用例、提升自动化覆盖率)来提高效率,减少不必要的重复劳动。我会优先保证任务完成质量,同时主动学习如何平衡效率与工作量。”
面对高强度工作,我会优先拆解任务目标,用工具管理优先级,同时保持规律作息和运动习惯,确保可持续的工作状态。作为实习生,我也会积极请教团队经验,快速适应节奏。
4、测试组长在下班之际,突然给我一个任务,然后我自己对这个任务预判自己加班几个小时都做不完,且组长只跟我一个人说这个紧急任务,你会怎么做?
1. 快速评估任务量与划分优先级
2、立即与布置任务的负责人沟通,说明任务量超出个人能力范围,请求增派支援或调整截止时间。
3、专注核心任务
5、遇到项目进度紧张怎么办?
时间上:如果领导评估项目需要加班,那为了赶项目进度加班是必需的;
任务上:加班时间仍然紧张,我会先梳理子任务优先级;把那些优先级低的任务排在后边,如果实在时间来不及了,就放弃;
风险上:如果加班,砍任务仍然完不成项目;我会评估由于任务完不成所带来的风险,我们是否能够承受;
6、为什么要做软件测试?
1、我高中同学在网易做软件测试,一起吃饭正好聊到软件测试方向,然后跟他聊了与软件测试相关的知识之后,我对软件测试岗位初印象是比较感兴趣的;
2、在学习软件测试理论、功能测试技术、性能测试和自动化测试等技术,然后拿项目去使用这些技术去实践后,让我有很大的成就感,激起我浓厚兴趣;
3、还有就是跟我的兴趣和性格比较匹配,因为在测试过程需要耐心和细心,然后我又对测试技术很感兴趣,所以我致力于在测试岗位上一直发展;
7、谈谈你对测试的理解
1、我认为测试不仅仅是找出错误,而且还包括验证软件的功能、性能、可靠性以及用户体验等方面,发现其中的问题并及时解决。
2、测试可以提前发现和修复缺陷,能减少未来的维护成本,对于保障软件的质量和提升用户满意度十分重要。
3、我了解多种测试方法,比如功能测试、性能测试、安全测试等,知道多种测试工具的使用。


浙公网安备 33010602011771号