• 2022软件测试面试题 200道大厂面试真题 刷完拿到10k职位


    系列文章目录

    提示:阅读本章之前,请先阅读目录



    前言

    软件测试,200道真题测试面试题


    1. 编写测试用例时,一般会用到哪些方法进行测试用例的设计?

    在工作当中,我用到的最多的方法是,边界值,等价类,场景法

    第一个呢,是边界值,针对测试经验给我的反馈,大量的软件程序之间的错误,在输入端这边的错误,大部分都是因为输入或者输出在范围边界上,比如,一个整数大于0,小于等于5,那么,我们就可以得到一些数值,就是-1,0,1,4,5,6,那么,这些数值就是我们当前要输入的值的一个边界,那我们就可以根据这些值来设计测试用例。

    第二个,就是等价类,分为有效等价类,以及无效等价类,在我们输入范围的子集里面,对软件程序运行是正向的,那么就是有效等价类,而在这个范围子集之外的,就是超出程序设计的范围之外,就是无效等价类。

    第三个,场景法,就是把系统全部业务流程都梳理出来,然后每个业务流程的分支也梳理出来,然后,我们梳理出来正向的流程,以及反向的流程之后,我们就去设计在每条流程可能会经历的测试行为是什么?在流程中间,我们可以输入什么样的数据,或者,执行什么样的操作,可以转到其他流程,然后再转到正常流程上,让整条流程能够跑通。场景法中,我们都会结合边界值和等价类的设计方法,来对我们的系统有一个全面的覆盖测试。

    2. 测试过程中,为什么要做接口测试?

    为什么要进行接口测试的话,我总结了四个点

    第一个就是,我们在进行功能测试的时候,往往只是针对前端页面的功能测试,即使前端有较为良好的数据格式校验,但是可以通过一些工具,来绕过我们的前端校验,直接调用接口,这样,就会导致,我们前端页面的校验完全失效,因此,我们就需要对接口进行测试,绕过前端,直接校验接口,来发现在页面发现不了的BUG。

    第二个就是,检查系统对于异常的处理能力,对于接口,如果传入一些异常的数据,是否会导致服务器崩溃,从而导致一些代码的泄露,所以,进行接口测试,是非常有必要的。

    第三个就是,检查系统的安全性,我们知道,互联网中会存在非常多的黑客恶意攻击服务器,导致数据的泄露,一些注入攻击,代码审查等,如果,我们的接口没有对这些恶意攻击进行处理,那么,就有可能导致我们的系统被攻击入侵,从而导致直接的经济损失,所以,对于接口的测试,是有一定的程度来检查我们系统的安全性。

    第四个就是,保障服务端的质量,避免我们的版本更新迭代,会导致服务端不稳定,在我们前端调用接口的时候,是需要返回一个稳定的处理结果,否则的话,也会导致前端的功能的不稳定,所以,要想确保前端功能的稳定,就需要确保服务端的质量。

    3. 测试过程中,如果遇到了不可复现的BUG该如何处理?

    这个主要有两个处理的方向。

    第一个,就是,自己复现细节,试试看能不能把bug复现出来。在我们去复现的时候,一定要注意版本,比如,我们是在1.2的版本里面发现了这个bug,那么,我们就要去这个1.2的版本去复现这个bug,而不是在其他版本去复现,因为,在新的版本,开发人员可能自己发现了这个bug,然后直接修复了,没有跟测试人员进行沟通,这个情况是有的。那么,如果想要增加复现的几率呢,我们需要看看有没有一些运行日志,或者错误信息,来辅助我们进行复现。

    第二个,就是,我们跟开发人员去沟通这个bug,把我们的操作步骤,操作细节,输入的数据,还有bug的详细信息,都给到开发人员,跟开发人员进行沟通,看看开发人员是什么样的反馈,因为开发人员的开发经验是比较丰富的,对于一些bug的产生,是有一个非常清楚的认知是可能因为什么原因导致这个bug,并且是有可能复现不了的。所以,当我们自己复现不了的时候,是可以跟开发人员进行沟通的。

    那么这个bug实在是无法复现怎么办呢?
    我们首先要对bug进行分级,看看这个bug,是不是会影响到我们正常业务,如果是影响到了业务的执行,或者是,会让用户产生不好的体验,优先级高的bug,那么,我们就要全力去复现,因为这个bug是比较重要的,如果实在是找不到的话,我们可以等后续版本的更新,看看是不是开发人员,在修复其他功能的时候,可以一起修复了,因为很多时候,可能是另外一个功能影响这个功能,功能之间有关联。
    当然,如果这个bug,不是那么重要,就是不会造成一些不好的体验,或者是不会影响到用户的正常使用,那么,我们在全力复现之后,还是无法复现,那么,我们就可以先放一放,先提交到缺陷管理平台,去记录这个bug的信息,在后续的版本中,我们多留个心眼,看看能不能重新复现。

    4. 如何提交一条完整的bug信息?

    主要是以下的信息,我们从开发人员来修复这个bug的角度来说。

    bug标题,开发人员当然是希望,在开始bug的修复之前,先看这个bug标题的描述,然后能够快速的了解这个bug的情况,需要直击关键点,哪个模块哪个功能,经过什么样的行为,出现了什么bug

    bug等级,我们测试人员,需要根据这个bug等级的规范,来确定这个bug的严重等级,以便于开发人员,对于一些严重等级高的优先处理

    bug的优先级,我们测试人员,需要根据这个优先级的规范,来定义bug的优先级,以便于开发人员,对优先级高的bug,进行优先的修复解决,避免影响到当前版本的bug修复进度

    bug对应的软件版本,这个bug是出现在哪个版本上,这个也很重要,对开发人员可以快速定位bug,然后修复

    bug的操作步骤,对于这个bug的复现,是经过什么样的操作步骤,然后产生的这个bug,这个以便于开发人员按照这个步骤去复现这个bug

    bug的输入数据,对于这个bug,我们输入一些什么样的数据,就会导致bug的产生

    bug的期望解决结果,我们需要给到开发人员,清晰的期望结果,希望这个bug解决到什么样的程度,达到什么样的结果

    bug的错误信息,我们主要是以截图为主,把这个bug出现的情况,截图,上传到附件,也可以上传日志,对于一些操作步骤复杂的,可以录制视频上传

    bug的指派,我们需要通过分析,这个问题可能是前端还是后端的问题,然后指派给对应的开发,提升bug处理的效率,否则的话,前端也不知道这个bug是由前端解决的,后端也不知道这个是不是该由后端解决的

    5. 工作中遇到的最经典的bug是什么?

    回答1:
    在我以往的测试中,我就遇到了一个非常搞笑的bug,就是,个人信息的出生日期控件,前端页面呢,是让用户自己选择自己的出生日期,第一个选项是年,第二个是月,第三个是日,然后呢,这个bug就是,在我们选择2月份的时候,第三个日的选项,居然可以选择31,这个明显就是,前端没有对日期的格式进行校验,然后我就提交bug给到了前端,然后前端进行了修复,根据用户选择的日期之后,会进行格式的校验。

    回答2:
    在我以往的测试中,我在测试分页功能的时候,用户可以输入一个数,然后到达指定的页数,然后这个输入框,只限制了只能输入数字,然后不能输入中文,英文这些字符,然后,我就尝试输入1.5,2.5这样的,带有小数点的数字,然后点击跳转之后,然后直接返回了服务端报错的页面,是服务端抛出异常的代码,然后,我就给到了后端这个bug,然后紧急进行修复了,这个是我测试工作中,遇到的印象比较深刻的,比较经典的bug。

    6. 给你一支笔怎么测试?

    先说一下思路,就是,笔和其实跟软件程序的测试概念是不太一样的,软件程序的测试本质上就是输入和输出的测试,测试程序输入之后可能会出现什么bug,测试程序输出的过程中可能会产生什么bug,那有相同点的地方就是,软件质量的六大特性,测试的本质就是测试它的一个质量,那软件质量的六大特性,分别就是,功能性,易用性,可靠性,效率性,可维护性,可移植性。

    那么,我们就可以根据这些特性来测试我们的笔,
    功能性,可以测试它最长连续使用的时间是多少,连续使用会不会出现断触,是不是在任何纸质上都可以使用
    易用性,是不是所有人群都可以使用,不分男女老少,是不是拿起来就能使用。
    可靠性,在经过100个人的使用,是不是还能够正常的使用;连续使用之后,会不会损坏;
    效率性,能不能写上比其他普通的笔更多的字;
    可维护性,能不能把笔帽,笔芯换成新的;
    可移植性,能不能跑到另外一个地方的纸上使用;能不能把里面的部分,拆出来然后装到其他同款型号的笔上使用;

    7. Web的兼容性如何测试?

    在进行web的兼容性测试的时候,一般都是测试浏览器的兼容性,就是测试web页面,在不同浏览器的展示样式,以及功能的使用上,有没有什么异常。
    主要我们会测试chrome浏览器,火狐浏览器,safari浏览器,360浏览器,oprea浏览器,Egde浏览器
    出现比较多不兼容的情况,我之前遇到过就是,不同浏览器它的内边距padding和margin的默认值不一样,就会导致页面的最上边和最左边,会产生一个空白的间隙,这个原因是没有清除默认样式导致的。
    还有就是js脚本的兼容,在不同的浏览器,可能有一些js的版本,会导致该浏览器的版本无法兼容js的语法,然后导致页面功能失效。

    8. Monkey测试如何执行?

    monkey指令,其实,实际上就是安卓的一个操作指令monkey,它在安卓系统中,有个monkey.jar的包,我们可以通过adb shell monkey来调用它,比如,我们可以通过-p,来指定运行的app,然后monkey是通过随机性的事件来执行操作,比如,点击,拖动等操作,我们是没有办法直接控制monkey的操作步骤,因为它是随机产生事件的,如果我们想复现上一次操作的bug,我们可以使用-s,来指定这个随机产生的种子数,比如-10,那么,第一次运行和第二次运行,会是一样的。
    如果我们一定要指定monkey的操作步骤,那么我们通过adb shell monkey是实现不了,但是monkey提供了一个脚本的方式,我们创建一个脚本代码,这个脚本的文件格式,是txt,然后里面编写好每一步的操作步骤,比如,点击哪里,这个是需要坐标系的数据,然后,我们通过push把这个文件传到安卓设备上,然后再通过monkey -f 来执行这个脚本。

    9. Selenium运行原理是什么,为什么可以实现Web自动化?

    Selenium的运行原理,实际上它不会直接去操控浏览器,而是通过一个webdriver的服务,我们在配置web自动化测试环境的时候,我们需要根据浏览器的类型,去下载我们的webdriver,这里的意义就是,通过webdriver这个服务去控制浏览器,完成我们的操作。那么,整体运行原理就是,我们通过编写脚本代码,调用selenium封装好的各种操作方法,然后selenium就会运行webdriver,然后webdriver就会在系统后台进程创建一个服务,然后去下方操作指令给到浏览器,浏览器再按照指令进行操作,然后浏览器操作完成之后,根据我们需要返回的数据,返回到webdriver,webdriver再传回selenium,然后,我们就可以拿到各种数据以及实现行为操作,这样就可以完成web的自动化。

    10. 在web自动化测试过中,如何有效的定位动态元素?

    首先,我们要清楚什么是动态元素。
    动态元素,一般来说,就是那些属性或者路径会不断改变的元素,比如,动态id,刷新页面,每一次的元素id,都是发生变化的,所以,我们是没办法通过id去定位的,那么,这个时候,我们就可以选择比较灵活的定位方式,有xpath和css selector,一般来说,我们可以通过相对路径进行定位,然后选取这个动态元素,不会变的属性或者文本内容,如果会定位到多个元素,那么,也可以考虑先定位它的父级,然后再定位它本身,如果我们还是很难通过相对路径定位,也可以使用绝对路径,虽然说绝对路径不是推荐的定位方式,但是也是处理动态元素定位的一种办法,可以灵活使用。

    11. 在web自动化测试过程中,元素定位失败的原因是什么?

    第一个,检查是否添加了等待,有三大等待,显式等待,隐式等待,还有强制等待,如果我们没有等元素完全加载出来的话,是完全有可能定位失败的
    第二个,检查定位的语法有没有错误,我们可以通过F12的开发者工具,然后按Ctrl+F,去校验我们的语法
    第三个,就是我们可能定位到了多个元素,然后这个元素不在第一个,因为selenium默认选择的元素就是第一个,所以也有可能造成定位失败
    第四个,窗口的句柄,是否进行切换,如果在原有的句柄操作之后,弹出新的窗口,那么句柄是需要进行切换的,可以通过window_handls获取所有的句柄,再通过switch_to_window进行切换
    第五个,检查页面是不是存在frame框架,如果我们要定位的元素在不同的frame框架里面,那么,我们是需要通过进入这个frame框架,才能定位到
    第六个,检查是不是被覆盖,有时候,页面会弹出新的广告元素,把要点击的元素进行覆盖,那么,也会造成定位失败,还有一种情况就是,浏览器被缩小了,这个元素没有被显示出来,这个时候,我们可以通过最大化浏览器窗口解决这个问题

    12. 在自动化测试过程中,如何选择数据驱动形式?

    在自动化测试过程中,数据驱动的形式,可以有很多种,比如,excel,yaml,txt,csv,xml等,其本质,就是存放测试用例的数据,通过数据来驱动自动化的测试。
    那么,我们该如何选择数据驱动的形式
    那么,最主要的,还是需要根据我们团队的测试人员的技术水平来选择,如果是技术水平较低,那么,我们可以选择excel,这种最常见的数据文件,因为,基本上人人都会使用excel,那么来编写测试用例,相对来说,是比较容易接受的,且学习成本低,我们只需要编写好使用文档规范,如何去编写测试用例然后执行自动化测试,测试人员只需要根据这个规范文档,去编写即可轻松实现自动化测试,而不需要去编写代码。
    那么,如果我们的测试人员,技术水平是有基础的,是能够通过编写代码,实现自动化的测试, 那么,我们可以选择yaml,作为数据驱动的形式,yaml是比较直观,高效的数据形式,通过键值对的形式,其实,更符合编程逻辑,所以,有代码基础的测试人员,就可以根据我们的yaml规范文档,来编写测试用例,也可以实现自动化的测试。

    13. 可以说一下什么是关键字驱动吗?

    关键字驱动是自动化测试框架中最为核心与底层的设计模式,适用于UI自动化与接口自动化测试。
    本质意义上,就是面向对象编程的对象与封装,这种设计模式就是基于业务使用场景,进行合理独立封装,然后再通过调用封装好的函数来执行业务。
    一般而言,封装的时候,都会考虑代码的复用性,以及封装的灵活度。
    封装也会根据实际需求进行优化,从常态化操作的封装,再到业务流程的封装,以及固定步骤和数据的封装,封装的形式是多样化的。一般都会根据当前项目的需求,进行优化。
    因此,关键字驱动设计模式对于自动化项目是适配性最强的设计模式。
    在我以往的工作中,我用的最多的接口自动化测试框架,是python+requests+yaml数据驱动+logging+pytest+allure+jenkins,web自动化测试框架是python+excel关键字驱动+logging+unittest+unittestreport+yaml+jenkins实现持续集成。

    14. 可以说一下PO吗?

    PO设计模式,也叫POM设计模式,就是Page Object Model,页面对象模型
    ,PO模型是专门用于UI自动化中的,PO关注的核心是页面,而不是操作行为。
    其思想就是,将复杂的业务流程进行切片,把完整的业务流程,切割成一个又一个的独立页面,最终将页面所需的顺序进行组装,最终实现业务流程的运行。
    PO模型中,主要分为四层
    base 基类层,封装了selenium的一些常用的操作,点击,获取元素,输入等一些共用的方法
    pageobject 页面对象层,对当前页面的业务流程进行封装,组成成单个页面业务流程的执行
    testcase,测试用例层,把所有的业务流程组装成完整的业务流程
    testdata 数据层,存放业务流程中所需要的数据

    PO设计模型,极大提升了代码的可维护性,所有的内容都是基于页面来管理,每一个页面的单独维护都可以对测试用例的执行进行同步的维护,降低了维护成本。同时,PO设计模型,对单一系统的自动化测试,有一个非常好的覆盖,因为都是基于当前系统的编码设计,所有页面都是基于当前系统进行封装的。

    15. 可以说一下如何提升Selenium自动化脚本的执行效率吗?

    第一个,我们可以通过减少强制等待的使用,强制等待是造成selenium执行脚本效率低的主要原因之一,我们可以用显式等待和隐式等待,元素加载完成之后,立马执行下一步操作。
    第二个,在selenium4.0版本及以上,可以通过chromeoptions来配置页面的加载策略,有三钟加载策略,分别是,normal,正常模式,就是等页面所有的元素和资源加载完毕,才进行下一步的操作,这也是selenium默认的策略;第二个是eger,就是等所有dom节点加载完毕,就会开始下一步操作,不会等资源是否都加载完毕;第三个是none,需要配合显式等待或者隐式等待,当我们需要定位的元素,加载完毕之后,就开始下一步操作,不会等全部资源都加载完毕
    第三个,合理的设计与封装自动化测试框架,减少人为的介入,让自动化测试框架,可以在无人值守的情况下,自动执行自动化测试
    第四个,减少不必要的操作步骤,因为selenium打开的浏览器,都是0缓存的,都是需要重新加载所有的资源,所以,我们可以通过简化进入测试页面的步骤,降低自动化测试执行的时间来提升效率。
    第五个,我们还可以多线程的方式执行测试用例,可以用测试框架unittest或者pytest

    16. 如何提高自动化测试的稳定性?

    第一,合理使用三大等待,在一些特殊的场景,如果需要用到强制等待,那么,我们是可以使用的,因为它对于自动化测试的稳定性是有益的,对于一些无法用显式等待或隐式等待解决的问题,该用的时候,就可以用强制等待
    第二,检查定位元素的正确性,我们写在定位元素的定位时,我们可以先通过F12,来调试定位元素的代码,来保障正确性
    第三,我们要对一些容易出现异常的操作,进行异常处理,也就是try…except,最常见的就是读取文件不存在,定位元素,变量不存在等,让异常可以被处理,而不是直接抛出错误,让整个自动化测试停止
    第四,对于使用了多线程的自动化测试,我们需要减少每个测试用例之间的依赖,甚至是互相独立,不依赖,因为多线程的执行,是无法指定测试用例的执行顺序的。
    第五,有独立的测试环境,测试数据,我们需要避免因为人为的操作,从而导致自动化测试中断

    17. 如何设计高质量的自动化脚本?

    第一,应当提高代码的复用性,把一些共用的函数或方法,然后封装到共用类,通过这个类来调用我们所需要的函数,从而减少代码的冗余,提升代码的质量。
    第二,应当根据当前业务,选择合适的设计模型,比如,web自动化,我们就可以用PO设计模型,使用设计模型的好处就是,可以增加代码的可维护性,分层设计的架构,可以更好的管理我们的脚本。
    第三,在各类函数的封装上,要考虑灵活传参的形式,不要把函数的功能写死,要灵活,可以通过不同参数,实现不同的需求,让函数可以灵活多用,甚至一个函数可以解决多个需求,提升函数的利用率,来减少代码量

    18. 之前你们公司的UI自动化测试框架是如何实现的?

    我之前公司的UI自动化测试框架,技术栈是:
    python+unittest+excel+ddt+logging+openpyxl+unittestreport
    这个是我们基本的技术框架,那为什么要去选择这样的技术框架呢,主要有以下几点的考虑
    第一,python的话,在我们公司的团队,是主流的编程语言,所以说,用python的话,我们的学习成本会很低,而且上手是会快,当然,python也是目前做自动化最主流的编程语言
    第二,unittest测试框架,因为在之前的项目中,主流用的就是unittest,所以,我们直接沿用这个测试框架,我们搭建框架的效率是非常高的
    第三,excel关键字驱动,excel,我们主要是拿来做测试用例的编写,我们通过excel编写关键字驱动的业务流程,然后通过自动化测试框架来读取这个excel,来达到关键字驱动,所以说,我们这个框架,是以关键字驱动为核心
    第四,ddt,参数化,我们会搭配unittest进行参数化的测试,可以非常便捷的执行关键字驱动
    第五,logging,对于运行中产生的日志信息,我们都是通过logging来实现日志的输出以及日志的保存,对每一次运行的详细都进行记录和保存,以备在出现运行错误的时候,进行日志的排查,logging我们是会进行二次封装的
    第六,openpyxl,这个是处理excel的库,它强大的地方,就是可以读取excel,也可以修改excel并保存,我们通过读取excel里面的测试用例,然后,我们会把测试用例的执行结果,重新输出到这个excel的测试用例的测试结果这个字段,当然,我们还会输出执行的开始的时间,结束的时间,以及如果报错了,我们还可以进行截图之后把这个截图的照片路径,输出到这个测试用例上,这样,我们就可以通过路径拿到这个照片查看错误的信息。
    第六,unittestreport,这个是个开源的插件,这个插件,主要是可以查看更加丰富的测试报告,它是基于element UI的前端展示样式,所以,它会比HTMLtestrunner,会更加好看,而且还支持将测试用例排序,查询,分模块显示等,也有统计图等详细信息,当然,另外一个原因就是,它自己封装了一个多线程的方法,所以,通过它,我们可以轻松实现unittest的多线程执行测试用例

    那么,技术框架的设计思路,大概就是分为三层:
    PO设计模型+数据驱动+结构分层
    这三层,可以实现三个特性,可维护性,可读性,可扩展性
    基本的技术框架就是这些,然后,后续可以根据我们的需求,如果需要持续集成,那么就可以增加jenkins。

    19. 一个完整的请求是怎么样的?

    我们以HTTP的请求为例子

    我们通过浏览器访问url,或者是通过工具访问url,大致流程都是这样
    我这里以浏览器访问的方式来解释

    首先,浏览器根据这个url的请求协议,进行发起请求,比如我这里的url是,http://www.baidu.com,那么,浏览器会以http的请求协议进行请求,请求之前会携带,三个部分,请求头,请求行,以及请求体,然后给到服务器,服务器接收到之后,根据url请求的资源路径是哪个,去调用对应的接口,然后进行处理,处理完之后,返回响应结果,然后浏览器收到响应结果之后,给到前端,前端再对响应数据进行解析,加载资源,最后就是浏览器渲染页面。

    20. HTTP中的长连接和短连接有什么区别?

    长连接和短连接,指的是http发送完请求之后,是否保留tcp连接通道,短连接就是发起完请求之后,立马关闭tcp通道,而长连接是继续保持tcp通道,但是保持的时间是会限定的,以及可能还会限制进行请求的次数,这个在后端是可以定义的。
    那么,在HTTP1.0的协议版本下,默认是没有长连接的,在HTTP1.1的协议版本,长连接是默认开启的。
    在请求头,有这样一个参数,就是connection:keep-alive,在HTTP1.1的协议版本,这个不设置,它也是默认长连接,但是,它一定是长连接吗?显然不是,因为它主要是通过后端的定义。
    那么,这两种连接模式,如何选择?
    我们可以根据当前业务场景,进行选择,因为两者,都有好处与坏处。
    短连接,坏处就是,会频繁的发起请求,关闭请求,对服务端资源的消耗是非常大的,因为服务端要频繁的处理每一个请求的建立与关闭,所以,短连接只适用那些,只完成1,2次的请求,然后就不再请求的业务场景,这样就避免频繁占用服务器资源,用完立马关闭连接通道。
    长连接,好处就是,长时间保持连接通道,用户进行频繁的请求时,会一直使用该通道,那么服务器就不需要频繁的建立和关闭。那也有一个坏处就是,假设现在服务器有10万个长连接的请求,那这10万个,所有的用户都需要用到长连接吗,因为连接通道,用户是不会主动关闭的,会一直保持着,直到达到最长连接时间或连接次数,才会关闭,所以,这也会造成资源的浪费,所以,我们在选择长连接的使用的时候,需要根据业务场景来选择,如果用户需要频繁的使用请求,那么就可以选择长连接。


    更新日志

    提示:将会持续优化更新

    20220730,面试题#13,#14,#15,#16,#17,#18,#19,#20

    20220729,面试题#8,#9,#10,#11,#12

    20220728,面试题#3,#4,#5,#6,#7

    20220727,面试题#1,#2

  • 相关阅读:
    Flutter实战之go_router路由组件入门指南
    torch F.unfold()举例
    自主通用多物理场仿真PaaS平台伏图(Simdroid)及伏图电子散热模块上架华为云商店
    功能测试人员如何做到花一个月的时间进阶自动化软件测试工程师
    KT142C-sop16语音芯片的4个IO口如何一对一触发播放_配置文件详细说明
    【Java】字节流、字符流、IO异常、属性集
    Leetcode 220. Contains Duplicate III (Sliding window + set)
    cookies,sessionStorage 和 localStorage 的区别
    Git同时配置和提交代码到Github和Gitee
    Mac上安装Java的JDK多版本管理软件jEnv
  • 原文地址:https://blog.csdn.net/wg8ofk08/article/details/126005137