ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

自动化测试系统学习路线:从接口到UI,从脚本到平台

自动化测试系统学习路线:从接口到UI,从脚本到平台 前阵子有个工作两年的测试朋友问我自动化测试到底该怎么系统学他说网上教程刷了不少Selenium、Playwright、Appium、pytest都听过一点但一到自己动手写脚本就不知道从哪里下手更不敢把“熟悉自动化测试”写进简历。这个问题我太有感触了这些年面试过不少测试候选人简历上十有七八写着熟悉框架、熟悉工具但往深了问两轮多数人只停留在“用工具打开浏览器点了两下”的程度真正能把自动化用例维护好、跑稳、接到流水线里的人并不多。自动化测试入门这件事难的不是某个工具的命令怎么敲而是缺少一条清晰的主线你学它到底为了解决什么问题、先写哪一类脚本最能出价值、团队里实际落地时大家又踩过哪些坑。这篇长文就按我理解的主线完整走一遍——从自动化测试的定位与边界、技术选型与学习顺序到UI自动化和接口自动化的实战入门再到App自动化的原理和常见坑最后聊聊大厂里自动化到底怎么落地以及AI这两年给这个领域带来的真实变化。内容尽量通俗但不会为了迁就新手就把复杂度藏起来。1. 先别急着装环境自动化测试到底在解决什么问题1.1 手工测试的困境是自动化的出发点我见过太多团队处于这种状态每次发版前测试同学抱着笔记本一条一条点功能几百条回归用例点完两个多小时中途被打断一次就要从头回忆点到哪了。更难受的是点完心里还没底总觉得可能有漏掉的地方。人做重复性操作时天然会疲劳、会走神这是手工回归的最大隐患。自动化测试解决的就是这个层面的问题——把确定性的重复操作交给脚本去执行。比如注册登录、订单流程、支付回调这一类核心链路只要业务逻辑不变脚本每次都能用同样的步骤、同样的输入、同样的顺序去执行结果可预期出问题还能定位到具体步骤。过去点两个多小时的回归脚本跑一遍可能只要五分钟而且可以挂在流水线里每天晚上跑。还有一个很容易被忽视的场景是数据驱动的验证。有些系统需要验证大量输入组合比如优惠券规则、价格计算、权限控制手工构造几十组数据去测人早就看花了眼。自动化脚本配合参数化把几组甚至几百组数据一次性跑完然后再通过断言把不符合预期的结果挑出来。这种效率提升手工测试根本无法比拟。1.2 自动化测试的边界有的事情自动化做不了但我也要泼一盆冷水。自动化测试不是银弹很多刚入门的朋友容易走向另一个极端觉得会写脚本就万事大吉了。我见过最典型的失败案例是团队花了两个月把一套UI用例全部自动化结果上线前需求一变页面改版几十条用例一夜之间全部报废维护成本比手工测试还高。那什么场景适合自动化我自己的判断标准很简单第一操作步骤稳定、不会频繁变化第二执行频率高、重复性强第三验证结果可以用程序明确判断。比如核心回归、多浏览器兼容、接口数据校验、性能压测这些都很适合。不适合自动化的场景也有三类探索式测试需要人用直觉去发现产品的问题、主观视觉判断页面好不好看、交互顺不顺手、一次性短期验证用完就扔的东西没必要沉淀成脚本。还有一点需要提前建立认知就是自动化测试的投入产出比。行业里常讲的分层策略是这样的越底层的测试执行速度越快、稳定性越高、维护成本越低所以数量应该越多越靠近用户界面的测试执行最慢、最脆、开发维护成本最高数量应该最少。换句话说如果你只有时间做一类自动化优先做底层如果能把接口层覆盖好95%的回归风险就已经被兜住了UI层更多是补充验证用户视角的体验。新手入门时如果心里没有这个分层意识很容易一上来就死磕UI脚本磕了几个月写出一堆跑两次就废的脆弱用例然后得出“自动化测试没用”的结论。2. 入门路线怎么选先搞清楚三种自动化测试的分工2.1 单元、接口、UI三层各管什么事很多入门教程上来就教Selenium导致很多人以为自动化测试就是“驱动浏览器点点点”。实际上自动化测试按照测试对象和测试层级可以分成三大类它们在工作里的地位差别非常大。我用一个表格来说明看完你就知道为什么不能只盯着UI这一层。测试层级验证对象执行速度稳定性开发成本维护成本单元测试单个函数、方法、类最快毫秒级最高中低接口测试模块间、服务间的API交互较快秒级高低低UI测试用户操作页面的完整流程慢分钟级低高高单元测试是开发同学写代码时顺手做的验证的是某个函数输入输出是否正确接口测试验证的是服务之间或者前后端之间的数据契约是否成立比如登录接口拿到token、下单接口扣减库存UI测试则是模拟用户打开浏览器或App实际操作一遍验证整个链路最终呈现给用户的结果。三层各有侧重并不互相替代但从自动化的角度来说接口测试的性价比明显最高——开发成本比UI低稳定性却高得多执行也快得多。2.2 主流的工具和语言选型工具这块入门朋友最容易挑花眼。我先给你捋一个比较实用的选型版图再解释为什么大多数人推荐从Python入手。UI自动化Web端老牌的Selenium适合需要兼容大量浏览器场景的现代一点的Playwright内置等待机制、多浏览器支持、还可以录制脚本这两年越来越火Cypress则适合前端团队主导用JavaScript写测试的场景。UI自动化App移动端Appium是跨平台的绝对主流底层基于WebDriver协议支持Android和iOS国内还有一套基于图像识别的Airtest适合游戏或者不便拿到元素树的项目但稳定性不如原生控件定位。接口自动化代码型首选Python的requests库配合pytest测试框架这也是目前中小团队和大部分大厂团队里最常见的组合Java技术栈常用的有RestAssured加TestNG或JUnit如果只是临时调试接口Postman、Apifox这类工具也能解决但它们更偏手工调试不算真正的自动化。单元测试Java用JUnit、TestNGPython用pytest、unittestGo用内置test框架。语言选Python还是Java这个问题被问过太多次了。我的看法是如果只看测试领域Python确实更有优势——语法简单、第三方库丰富、社区生态成熟requests、pytest、Appium的Python客户端都很成熟。但如果你所在的公司或者你想去的团队是清一色的Java技术栈那用Java写接口自动化框架也是完全正常的事毕竟岗位要求的从来不是“你会什么语言”而是“你能不能在这个技术栈里把自动化落地”。作为学习者我建议先用Python把核心概念吃透之后转Java只是换一层语法壳子而已。2.3 我建议的自动化测试学习顺序大多数教程是按“UI自动化→接口自动化”来安排的因为UI的演示效果直观打开浏览器就能看到脚本在跑成就感来得快。但我不推荐这个顺序。理由很简单UI自动化的坑最多如果你连脚本语言的基本语法都要边写边查再叠加定位元素、处理弹窗、等待页面加载这些问题很容易被劝退。我的建议路线是这样的先学接口自动化再学UI自动化最后根据工作需要接触App或单元测试。接口自动化上手需要的技能栈最薄——懂一点HTTP请求的基本概念GET、POST、请求头、请求体、状态码懂一点Python基础就能写出可用的脚本。而且接口测试的断言非常明确请求返回什么、预期是什么对就是对错就是错不会像UI那样受网络、渲染、动画各种因素干扰。等你把接口自动化的思路理清了再回头学UI心态会完全不一样因为你知道脚本是给谁在看、断言要落在哪里。学习期间需要补的三块基础知识别省HTTP协议的基本常识状态码、常见请求方法、Header里放什么、Body里放什么、JSON格式的读写、常用Linux命令看日志、跑脚本、连服务器排查环境问题。这三块基础不牢固后面写接口用例会非常痛苦。3. UI自动化第一课写一个不会被骂的脚本3.1 环境准备这是耐心含量最高的一步UI自动化入门最大的拦路虎其实不是写脚本而是环境搭建。尤其Selenium需要下载对应浏览器版本的驱动chromedriver之类浏览器一升级、驱动版本没跟上就当场报错新手花半天查报错都是常事。我个人建议新手直接选Playwright起步它的驱动是安装时自动管理的不需要手动下载浏览器驱动环境出问题的概率低很多脚本写起来也更现代。当然工作上如果团队已经定了Selenium你也不用慌核心概念都一样换汤不换药。用Python搭建Playwright环境的步骤非常简单python -m venv venv source venv/bin/activate # Windows下用 venv\Scripts\activate pip install pytest-playwright playwright install chromium这三行搞定以后浏览器内核、驱动、依赖都装好了。需要留意的是playwright install这一步会下载浏览器内核网络不好时容易超时如果下载失败可以检查一下网络状况或者去国内镜像源找对应内核包手动安装。3.2 第一个脚本打开网页、搜索、断言环境通了以后我建议你亲手敲一个最简单的脚本完整跑通“打开页面→执行操作→断言结果”三步。拿常见的搜索场景举例import re from playwright.sync_api import sync_playwright, expect def test_search(): with sync_playwright() as p: browser p.chromium.launch(headlessFalse) # 有头模式方便看到动作 page browser.new_page() page.goto(https://www.baidu.com) page.get_by_role(textbox, name搜索).fill(自动化测试) page.get_by_role(button, name搜索).click() # 断言结果页包含关键词 expect(page).to_have_title(re.compile(自动化测试)) browser.close()细看这段代码它把一个UI自动化用例的核心要素全包含了启动浏览器、打开页面、定位元素并操作输入、点击、断言页面结果。代码里最有价值的一行是expect(page).to_have_title(...)因为自动化测试的最终目的是做验证不是表演“脚本能操作页面”断言写不到位脚本跑得再顺也没用。同样的功能如果用Selenium写代码会长一些需要自己处理等待、自己写断言这也是我推荐新手从Playwright上手的原因——它把很多常见问题从设计上规避掉了。3.3 元素定位稳定是UI自动化的命门UI自动化用例最大的痛点不是写不出来而是写出来以后隔三差五地挂。挂的原因七成出在元素定位上。页面结构稍微调整一下脚本就找不到元素了这是最常见的事故。定位方式按稳定程度排序我的建议是这样优先用ID、name这类唯一属性——一个页面的控件ID一般是稳定且唯一的其次是data-testid这类专门为测试预留的属性——很多规范团队会给关键按钮加上data-testid就是为自动化铺路的再往后是CSS选择器——根据class、标签层级去定位相对灵活最后才考虑XPath——特别是那种从html/body一路写到底的绝对路径一个div层级变化就全断了是最脆弱的写法。有些朋友喜欢打开开发者工具右键复制XPath复制完一贴脚本一跑通过了很开心。但等到下一次前端重构这类用例会一夜之间集体失效。PUI自动化如果想长期维护定位这块就得稳。工作中如果遇到一个按钮没有id也没有data-testid稳妥的变通办法是结合它的文本内容和兄弟节点的关系来写相对XPath而不是直接用一整串绝对路径。3.4 等待机制脚本一会儿好一会儿坏的真正原因很多UI踩坑案例里最典型的现象是同一个脚本上午能跑下午跑就报“找不到元素”本地能跑CI上就跑挂。而且当你手动去点点那页面的时候元素明明就在那儿。这背后往往是同步问题——脚本执行到某一步时页面元素还没加载完。刚入门的同学最常用的粗暴办法是time.sleep(3)等三秒再说。我不建议养成这个习惯。sleep的问题是拍脑袋定时间网络快点用不了这么久浪费时间网络慢点又不够照样报错。而且sleep会让整个用例执行时间成倍拉长十几条用例跑下来多出来的全是白等。正确的思路是显式等待——轮询等待某个条件成立时间设长一点但元素一出现就立刻继续执行。Playwright在这方面做得很好它默认会对操作自动等待比如点击之前会等待元素可操作、稳定不会因为一点网络波动就报错。Selenium则需要自己写WebDriverWait类似这样from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, submit)) ).click()我在实际项目里有个经验UI用例偶发失败不要想着“加个sleep压压惊”而是要当成一个bug去排查——到底是定位不稳定还是等待条件不对还是页面本身有异步请求没有完成。找到根因一次修好以后就不用反复折腾了。4. 接口自动化最值得优先投入的方向4.1 为什么说接口自动化的投入产出比最高回头看看前面那张表接口自动化执行快、稳定性高、开发成本低这还不是最重要的。最重要的是它离业务逻辑最近覆盖面广。一个下单接口验证通过等于把前端所有入口Web、App、小程序的这条链路都覆盖了因为它们的底层调的是同一个接口。UI自动化做不到这个你得在三个端各写一遍脚本。而且接口测试的排错效率也高。接口返回一个错误码你可以直接定位到是服务端的业务逻辑问题还是参数传错了但UI测试你只看到页面报了一个“系统异常”还要一层层查日志才知道是哪里出的问题。对于只想快速入门、想尽快在工作里体现价值的同学我做接口自动化一定是你最先尝到甜头的方向。4.2 用 pytest requests 搭一个最小框架接口自动化最经典的组合是pytest加requests我来演示一个最小可用的工程结构。project/ ├── conftest.py # 存放公共fixture ├── config.py # 环境配置 ├── test_login.py # 登录接口用例 └── utils/ └── http_client.py # 请求封装先看conftest.pyfixture是pytest的核心机制相当于自动化的“前置/后置处理器”import pytest import requests BASE_URL https://api.example.com pytest.fixture def base_url(): return BASE_URL pytest.fixture def session(): s requests.Session() yield s s.close()接着写一个最基础的登录接口用例import pytest def test_login_success(base_url, session): resp session.post( f{base_url}/auth/login, json{username: tester, password: 123456} ) assert resp.status_code 200 data resp.json() assert data[code] 0 assert data[data][token] ! 这个用例表面上只做了三件事发起POST请求、校验HTTP状态码、解析JSON并断言业务字段。但这里已经体现了一个重要的习惯——不只断言状态码是200还要断言业务字段。很多接口不管你参数对不对只要请求到了都可能返回200但业务上可能是失败的。所以真正的接口断言至少要覆盖业务码和数据关键字段。再配合pytest的参数化一组数据跑一遍用例这是数据驱动的基础用法import pytest pytest.mark.parametrize(payload, expected_code, [ ({username: tester, password: 123456}, 0), ({username: tester, password: wrong}, 1001), ({username: , password: 123456}, 1002), ]) def test_login_various(base_url, session, payload, expected_code): resp session.post(f{base_url}/auth/login, jsonpayload) assert resp.json()[code] expected_code数据一多用例覆盖就上来了而且新加数据就是往参数列表里加一行的事维护成本极低。4.3 接口自动化进阶的三个真实难点跑通上面这个Demo很容易但真正在公司把接口自动化做好会遇到几个绕不开的坎我提前给你打个预防针。第一个是鉴权。现在大部分系统的接口都要求携带token登录后拿到的token要在后续所有请求里带上。更麻烦的是token会过期过期后脚本不能直接挂掉而是应该自动重新登录再重试。这块可以用pytest的session级别fixture统一处理登录一次把token存起来所有用例共享如果用例执行时发现token失效就重新登录刷新。第二个是数据依赖。典型场景是下订单接口需要先用商品接口创建商品拿返回的productId作为下订单的入参。这个可以先写一个“准备数据”的辅助方法或者用fixture把创建商品的步骤封装好让订单用例通过参数引用的方式拿到前置数据。这样用例之间不互相影响还可以实现数据隔离。第三个是环境切换。开发和测试环境域名不一样测试数据也不一样脚本不能写死某个环境。解决方案很简单把环境配置抽到config.py里通过环境变量或命令行参数切换用例里不要出现硬编码的URL全部通过配置读取。这些难点并不需要一步到位你可以先把最简单的跑通再慢慢加上鉴权、依赖、环境切换。但心里要有这个概念接口自动化做成什么样才算“框架”而不是“脚本集合”关键就看有没有把公共逻辑抽象出来让人家新写用例时只需要关心业务参数和断言。5. App自动化环境比代码更折磨人5.1 Appium的工作原理如果把UI自动化扩到移动端Appium是目前绕不开的工具。它实际上是WebDriver协议的移动端实现——你在脚本里用一套统一的API写操作Appium Server负责接收指令然后转换成Android或者iOS系统能理解的命令真正去驱动App的还是系统框架Android是UIAutomator2iOS是XCUITest。Appium在这个体系里相当于一个翻译官。理解了这一点你就会明白App自动化和Web自动化在代码层面非常相似同样是定位元素、执行操作、断言结果。真正的差异在环境层面Web自动化你只需要一个浏览器驱动App自动化你需要Node环境、JDK、Android SDK、adb工具、Appium Server、模拟器或真机而且Android SDK版本、Appium版本、设备系统版本之间还有兼容性问题。很多跨不过入门门槛的人不是脚本写不出来是环境配了一个星期还没跑通。5.2 从零跑通第一个Android脚本如果你有Android设备或模拟器可以按这个思路来准备环境安装Node.js和JDK并配置JAVA_HOME安装Android SDK或者直接装Android Studio里面带SDK和模拟器通过adb devices确认设备已经连接上安装Appium Servernpm install -g appium在Python环境里安装Appium-Python-Client。然后写一个最简的启动脚本from appium import webdriver desired_caps { platformName: Android, platformVersion: 12.0, deviceName: emulator-5554, appPackage: com.example.app, appActivity: .MainActivity, noReset: True } driver webdriver.Remote(http://localhost:4723/wd/hub, desired_caps) driver.find_element(id, com.example.app:id/button_login).click() driver.quit()这段代码里desired_caps是Appium的“灵魂”它告诉服务端要连接什么设备、启动哪个应用。appPackage和appActivity两个参数新手最容易填错——你得去被测试App的AndroidManifest文件里找包名和启动Activity或者用adb shell pm list packages命令先看看设备上装了什么包。5.3 App自动化常见的几个坑App自动化最常见的坑排前三个一是设备连不上。adb devices里看不到设备脚本报“no devices found”。这个问题大多出在开发者模式没开、USB调试没开或者驱动没装好。另外用模拟器的话不同模拟器的adb端口不一样也是要排查的点。二是desired_caps配置和实际环境不匹配。比如platformVersion写错了设备实际是Android 13你写12脚本可能也能跑但容易出诡异问题noReset这个参数如果没设置脚本每次启动应用都会弹权限框把用例带崩。三是混合应用的控件定位。现在很多App的页面其实是WebView渲染的原生控件定位方法抓不到里面的元素。这种情况要先切换到WebView上下文再像Web自动化那样去定位元素。新手遇到这个问题会非常懵排查半天以为是代码错了其实是没切上下文。以我个人的经验如果你所在公司还没有一个稳定的移动测试环境设备管理、版本管理、平台兼容都没有基础App自动化可以先放一放先把Web端和接口的自动化做好更实在。等平台和环境成熟了App自动化上手的成本会低很多因为底层原理你已经懂了。6. AI辅助下自动化测试的门槛正在降低6.1 AI在测试里到底能做什么这两年AI对研发测试领域的渗透是实实在在的。光说自动化测试这块我实际用过并且觉得有价值的场景有几个而且这些场景现在很多人已经在用了。第一自然语言生成脚本。你可以直接描述“打开登录页面输入账号密码点击登录断言跳转到首页”让Claude、ChatGPT这类大模型工具帮你生成对应的pytest或Playwright脚本。基于语言模型对常用框架的熟悉程度生成出来的脚本即使不能直接运行也基本是“改几个选择器就能跑”的水平。第二失败日志分析。以前一条用例挂了你要点进日志一行行翻找异常原因。现在把报错日志直接丢给AI它很快能告诉你“大概率是元素等待超时”或者“登录接口返回401token失效了”。效率提升非常明显。第三测试数据和断言建议。让大模型根据接口文档生成测试数据、生成边界条件用例或者帮你想想这个接口除了状态码还应该断言哪些字段。它虽然不能替代测试设计和业务理解但作为“头脑风暴搭档”非常称职。6.2 AI生成的脚本能不能无脑相信我需要强调一点AI生成的代码跑通是第一步但千万别直接当成可维护的用例。我自己用过AI写接口自动化测试脚本说实话框架结构、请求写法基本正确但有两个问题很明显一是不会结合你的业务去设计断言经常只帮你断言了HTTP状态码二是对异常场景的覆盖不足不太会主动思考参数非法、数据不存在、权限不足这些边界情况。所以我的态度是AI是一个效率增强器它能把你从“从零敲一个脚本”的重复劳动里解放出来把更多精力放到测试设计本身——也就是想清楚测什么、怎么断言、边界在哪。这些东西才是自动化测试真正的含金量。一个只会把AI生成的脚本贴进项目里的人和那个“会用工具打开浏览器点两下”的人本质上没有区别只是更快一点而已。给新人的建议也很直接用AI辅助入门完全没问题让大模型给你解释报错、给你生成示例代码都很好。但自己在成长阶段一定要亲手写若干条用例不要所有代码都是AI生成的不然基本功不牢出了问题无从下手。7. 大厂自动化测试都在干什么7.1 从“写脚本”到“搭平台”很多人以为大厂自动化测试就是一群测试开发工程师埋着头写脚本其实发展到成熟阶段大家做的事情已经远远超出一条条用例本身了核心在于“平台化”和“体系化”。首先是自动化测试平台。一个团队有几百上千条用例靠每个人在自己电脑上跑肯定不行。实际的做法是把用例集中管理放到统一的平台上平台负责定时调度执行比如每天晚上跑全量回归、收集执行结果、生成可视化报告、失败时自动通知相关人员。更进一步平台还提供在线编辑用例、在线调试、失败用例自动重跑、历史趋势分析这些能力。测试同学不再需要和命令行打交道点一点就能看到整个团队的自动化健康度。其次是测试环境治理。大厂里接口依赖多、链路长测试数据需要准备和隔离否则你跑完一个用例把数据改掉了别人再跑就挂了。所以他们会做数据工厂、Mock服务、环境隔离这些基础设施让每条用例在可控的环境里运行不会互相干扰。这些基建工作很多时候比写用例本身更耗精力也是资深测试开发工程师的核心工作。7.2 自动化项目能不能落地看的是维护与基建我在团队里见过太多自动化的“表面繁荣”用例数几百条覆盖率报表很漂亮但实际大部分用例都不稳定每天报一堆红没人管最后整个自动化项目被管理层质疑。这一类问题是有共性的总结起来就是三个原因第一用例没有真正融入CI流水线。只是几个人在自己电脑上跑跑挂了对团队没影响自然没人重视。真正有效的做法是每次代码提交自动触发相关测试失败了阻塞发布这样团队才会把自动化用例当成头等大事来维护。第二用例太脆没有人维护。前端改一个样式、一个文案脚本就挂了然后就这样躺在报告里长年标红。规范做法是页面结构变了测试用例要同步更新并且要有明确的责任人谁写的用例谁负责维护。第三追求数量而不是价值。有些团队为了向上面汇报“我们自动化覆盖率到80%了”把大量临时性、不稳定、甚至没有实际断言的用例堆了上去。这种数字没有任何意义。真正有效的自动化项目看的是能不能在每次发布前稳定兜住核心流程能不能在环境出问题时第一时间发出准确告警。大厂自动化测试对人的能力要求其实已经不只是“会写脚本”而是代码能力能封装框架、能写公共库、业务理解能力知道核心链路有哪些、风险点在哪、架构和运维能力能搭平台、治理环境、分析数据。这套能力模型对普通团队的同学来说同样是职业发展的方向。7.3 新人怎么在工作里找到自动化的切入口很多测试同学想学自动化但所在的团队没有现成的自动化项目无从下手。我的建议很务实别等公司给你搭好平台先从自己手头最重复的那件事开始。比如每次发版前你都要反复测一个核心流程那就把它脚本化每次验证多组数据都要手工改参数那就用参数化把它跑起来。哪怕只是一条用例先跑起来、稳定住再慢慢扩展。很多团队的自动化项目最初就是这么长出来的——不是领导规划的而是某个人把自己手头的重复工作自动化了大家觉得好用才逐渐做大的。写在最后的一点体会这篇文章写下来我自己也有一些感触想分享。学自动化测试这么多年见过太多人一开始热情高涨买课、装环境、跟着教程敲了几个脚本然后就没有然后了。最大的分水岭不是智商也不是学历而是能不能在工作里找到一个真实场景把一个脚本长期维护下去。你能把一个用例跑到三个月不挂和你十天写二十个跑一次就扔的用例是完全不同的两个层次。如果让我给你一个最小可行的行动建议我建议你从下周开始找一个自己每周都要重复做一次的测试场景用接口自动化或UI自动化把它变成脚本。第一版丑一点没关系跑通就是胜利然后每周花一点点时间迭代它加断言、优化等待、处理异常。三个月后回头看你对自动化的理解一定会比刷十篇教程都深。这条路我走过确实有效。
返回列表