點(diǎn)點(diǎn)到年薪50萬(wàn):自動(dòng)化測(cè)試與AI實(shí)戰(zhàn)突圍指南)
做了五六年測(cè)試天天被開(kāi)發(fā)叫“點(diǎn)點(diǎn)的”年終匯報(bào)憋不出一個(gè)字漲薪永遠(yuǎn)墊底。說(shuō)真的“測(cè)試沒(méi)前途”這句話(huà)我聽(tīng)了無(wú)數(shù)次自己也動(dòng)搖過(guò)無(wú)數(shù)次。但后來(lái)我換了條路把自動(dòng)化測(cè)試這套東西徹底吃透了從月薪八千跳到年薪五十萬(wàn)前后也就用了兩年多。這篇文章就說(shuō)說(shuō)我是怎么從手工點(diǎn)點(diǎn)點(diǎn)一步步搭起自動(dòng)化測(cè)試體系、用AI把測(cè)試效率提上去、最后靠這套技術(shù)棧完成職業(yè)突圍的。不灌雞湯只講實(shí)操該給的代碼給代碼該說(shuō)的坑說(shuō)透。1. 先想明白一件事自動(dòng)化測(cè)試到底值多少錢(qián)很多測(cè)試同行覺(jué)得自動(dòng)化測(cè)試就是“會(huì)寫(xiě)個(gè)腳本”會(huì)Selenium能跑個(gè)瀏覽器就算自動(dòng)化了。如果真這么想那薪資天花板確實(shí)低。但實(shí)際職場(chǎng)里企業(yè)愿意為自動(dòng)化測(cè)試付高薪買(mǎi)的不是“寫(xiě)代碼”這個(gè)動(dòng)作而是“一套可持續(xù)運(yùn)行的測(cè)試保障體系”。1.1 手工測(cè)試的天花板在哪里手工測(cè)試的核心問(wèn)題是它無(wú)法規(guī)?;R粋€(gè)人一天能執(zhí)行多少條用例老老實(shí)實(shí)點(diǎn)幾十條到一百條頂天了。而且每次版本迭代這些用例要全部重跑一遍回歸成本高到離譜。更致命的是手工測(cè)試的“經(jīng)驗(yàn)”很難沉淀到組織層面——老測(cè)試走了那些藏在腦子里的業(yè)務(wù)流程知識(shí)、邊界場(chǎng)景意識(shí)全跟著一起流失了。企業(yè)不是不認(rèn)可測(cè)試的價(jià)值而是沒(méi)法為“不可沉淀、不可復(fù)制、不可量化”的工作支付高溢價(jià)。這就是很多人做了三五年手工測(cè)試薪資依舊原地踏步的根本原因。1.2 自動(dòng)化測(cè)試真正的價(jià)值點(diǎn)自動(dòng)化測(cè)試的核心價(jià)值在于把“人肉執(zhí)行”變成“機(jī)器執(zhí)行”把“一次性的手工勞動(dòng)”變成“可重復(fù)的資產(chǎn)”。我在面試候選人時(shí)經(jīng)常說(shuō)一句話(huà)自動(dòng)化測(cè)試的價(jià)值不在于省掉了點(diǎn)鼠標(biāo)的時(shí)間而在于它改變了測(cè)試在整個(gè)研發(fā)流程里的位置。手工測(cè)試時(shí)代測(cè)試是最后一個(gè)環(huán)節(jié)只能被動(dòng)等版本提測(cè)有了自動(dòng)化測(cè)試之后測(cè)試可以前置到開(kāi)發(fā)階段。開(kāi)發(fā)每次提交代碼流水線(xiàn)自動(dòng)觸發(fā)接口測(cè)試、UI冒煙測(cè)試有問(wèn)題當(dāng)場(chǎng)暴露而不是等到提測(cè)日才發(fā)現(xiàn)一堆低級(jí)bug。這種“質(zhì)量左移”的能力才是企業(yè)真正愿意花錢(qián)買(mǎi)的東西。而且自動(dòng)化測(cè)試跑得越多單次執(zhí)行成本越低。我搭過(guò)的一套接口自動(dòng)化回歸用例大概四千多條手工跑需要三個(gè)測(cè)試干兩周自動(dòng)化跑只需要四十分鐘。四十分鐘換兩周的人力這筆賬任何技術(shù)管理者都會(huì)算。1.3 年入50萬(wàn)的構(gòu)成拆解有人好奇年入50萬(wàn)是怎么來(lái)的簡(jiǎn)單拆一下我這50萬(wàn)不是純純的死工資而是“基礎(chǔ)薪資績(jī)效獎(jiǎng)金技術(shù)津貼副業(yè)/顧問(wèn)收入”的組合。核心邏輯是我把自動(dòng)化測(cè)試能力做成了“可遷移的基礎(chǔ)設(shè)施”在公司內(nèi)部我能搭平臺(tái)、帶團(tuán)隊(duì)、鋪落地在市場(chǎng)上我這些經(jīng)驗(yàn)又可以轉(zhuǎn)化成課程、咨詢(xún)、開(kāi)源項(xiàng)目的回報(bào)。想拿到這個(gè)收入級(jí)別單純會(huì)寫(xiě)腳本不行你得讓人家看到你構(gòu)建體系和解決復(fù)雜問(wèn)題的能力。后面的內(nèi)容我會(huì)把實(shí)現(xiàn)路徑一步步拆開(kāi)講。2. 學(xué)習(xí)路線(xiàn)自動(dòng)化測(cè)試到底要學(xué)什么我見(jiàn)過(guò)太多人在自動(dòng)化測(cè)試門(mén)口徘徊今天學(xué)Selenium明天學(xué)Appium后天又跑去學(xué)性能測(cè)試折騰半年什么都沒(méi)精通。原因很簡(jiǎn)單沒(méi)有一條清晰的主線(xiàn)。2.1 語(yǔ)言選型Java還是Python這是所有入門(mén)者第一個(gè)糾結(jié)的問(wèn)題。我的答案是如果你想快速上手、馬上看到效果選Python如果你準(zhǔn)備在大型互聯(lián)網(wǎng)公司長(zhǎng)期發(fā)展且團(tuán)隊(duì)技術(shù)棧偏Java那就學(xué)Java。Python的優(yōu)勢(shì)是語(yǔ)法簡(jiǎn)單、生態(tài)豐富尤其適合做測(cè)試腳本和數(shù)據(jù)處理。Pytest、Requests、Appium-Python-Client這些庫(kù)都非常成熟一個(gè)熟悉Python的人從零搭一套接口自動(dòng)化框架一周左右就能跑起來(lái)。Java的優(yōu)勢(shì)在于和主流的微服務(wù)架構(gòu)、Spring生態(tài)無(wú)縫銜接企業(yè)級(jí)測(cè)試平臺(tái)的二次開(kāi)發(fā)往往更依賴(lài)Java。我自己是Python起家后來(lái)團(tuán)隊(duì)全面轉(zhuǎn)Java我也跟著啃下了Java接口自動(dòng)化框架。我的建議是不要貪多先把一門(mén)語(yǔ)言練到能獨(dú)立寫(xiě)工程級(jí)代碼的水平再學(xué)第二門(mén)。兩門(mén)語(yǔ)言在自動(dòng)化測(cè)試領(lǐng)域的差異并不大核心是編程思維和框架設(shè)計(jì)能力。2.2 三大方向怎么選接口、UI、App自動(dòng)化測(cè)試的主流方向就三個(gè)接口自動(dòng)化、Web UI自動(dòng)化、App自動(dòng)化。接口自動(dòng)化優(yōu)先級(jí)最高也最值得下功夫。理由很簡(jiǎn)單接口是系統(tǒng)的最小可測(cè)單元接口穩(wěn)定了大部分業(yè)務(wù)邏輯問(wèn)題都能提前暴露。而且接口自動(dòng)化執(zhí)行速度快、維護(hù)成本低、在CI/CD里最好集成。我搭的回歸體系里接口用例占八成以上。Web UI自動(dòng)化適合做核心流程的冒煙驗(yàn)證典型工具就是Selenium和Playwright。它的問(wèn)題也很明顯——UI元素變化頻繁腳本維護(hù)成本高。所以我從不建議把UI自動(dòng)化比例做太高覆蓋核心主流程就夠。App自動(dòng)化主要靠Appium但比Web UI自動(dòng)化更折騰涉及設(shè)備管理、系統(tǒng)差異、控件定位。我的經(jīng)驗(yàn)是先把接口自動(dòng)化玩透再去碰App自動(dòng)化不然容易勸退。2.3 從入門(mén)到進(jìn)階的核心知識(shí)清單想靠自動(dòng)化測(cè)試達(dá)到高薪水平下面這些能力項(xiàng)建議一條條打勾編程基礎(chǔ)數(shù)據(jù)類(lèi)型、流程控制、函數(shù)、類(lèi)、異常處理、文件操作、日志庫(kù)接口測(cè)試HTTP協(xié)議、RESTful API設(shè)計(jì)、Requests/OkHttp使用、JSON/XML數(shù)據(jù)處理、斷言技巧自動(dòng)化框架Pytest/TestNG、數(shù)據(jù)驅(qū)動(dòng)、關(guān)鍵字驅(qū)動(dòng)、Page Object模式持續(xù)集成Git、Jenkins/GitLab CI、流水線(xiàn)配置、定時(shí)觸發(fā)與報(bào)告推送基礎(chǔ)設(shè)施Linux常用命令、Docker容器、MySQL/Redis基礎(chǔ)操作、日志與服務(wù)排查平臺(tái)化能力測(cè)試平臺(tái)后端開(kāi)發(fā)、前端Vue/React基礎(chǔ)、Agent節(jié)點(diǎn)管理AI工程化大模型API接入、Prompt工程、測(cè)試用例生成、智能斷言、Agent搭建這里面的每一項(xiàng)都不是孤立的。比如你寫(xiě)一條接口自動(dòng)化用例可能涉及HTTP協(xié)議、JSON解析、測(cè)試數(shù)據(jù)準(zhǔn)備、斷言策略、失敗重試、結(jié)果上報(bào)最后還要接入CI流水線(xiàn)。一個(gè)“能跑”的測(cè)試腳本誰(shuí)都會(huì)寫(xiě)但一個(gè)“穩(wěn)定、可控、可維護(hù)、可擴(kuò)展”的測(cè)試體系才是拉開(kāi)差距的關(guān)鍵。3. 親手搭一套PythonPytestAllure自動(dòng)化測(cè)試框架理論說(shuō)再多不如直接上手實(shí)操。這一節(jié)我把最常用的一套接口自動(dòng)化框架從零到一講清楚。3.1 框架選型與目錄設(shè)計(jì)我選的組合是Python Pytest Requests Allure。Pytest是目前Python系最主流的測(cè)試框架斷言直觀(guān)、插件豐富、支持參數(shù)化和FixtureRequests是HTTP客戶(hù)端的事實(shí)標(biāo)準(zhǔn)Allure用來(lái)生成美觀(guān)的測(cè)試報(bào)告。目錄結(jié)構(gòu)參考如下auto_test/ ├── conf/ # 配置文件目錄 │ ├── settings.py # 全局配置環(huán)境、超時(shí)、數(shù)據(jù)庫(kù)連接 │ └── config.yaml # 環(huán)境相關(guān)配置 ├── common/ # 公共封裝 │ ├── request_util.py # 請(qǐng)求封裝 │ ├── assert_util.py # 斷言工具 │ ├── log_util.py # 日志封裝 │ └── db_util.py # 數(shù)據(jù)庫(kù)操作封裝 ├── testcases/ # 測(cè)試用例 │ ├── test_user.py │ └── test_order.py ├── data/ # 測(cè)試數(shù)據(jù) │ ├── user_data.yaml │ └── order_data.json ├── reports/ # 測(cè)試報(bào)告與日志 ├── conftest.py # Pytest夾具Fixture ├── pytest.ini # Pytest配置 └── requirements.txt # 依賴(lài)清單這樣分層的邏輯很明確配置和代碼分離公共方法沉淀在common層測(cè)試用例只關(guān)注業(yè)務(wù)邏輯和斷言數(shù)據(jù)和腳本解耦。維護(hù)起來(lái)不累。3.2 核心代碼實(shí)現(xiàn)第一步先封裝一個(gè)統(tǒng)一的請(qǐng)求工具把get、post、put、delete這些操作收斂起來(lái)統(tǒng)一加日志、超時(shí)、異常處理# common/request_util.py import requests import logging from conf.settings import BASE_URL, TIMEOUT logger logging.getLogger(__name__) class RequestUtil: 統(tǒng)一請(qǐng)求封裝支持get/post/put/delete staticmethod def request(method, url, **kwargs): full_url BASE_URL url kwargs.setdefault(timeout, TIMEOUT) logger.info(f請(qǐng)求方式: {method}, 請(qǐng)求地址: {full_url}, 參數(shù): {kwargs}) try: resp requests.request(method, full_url, **kwargs) logger.info(f響應(yīng)狀態(tài)碼: {resp.status_code}, 響應(yīng)體: {resp.text[:500]}) return resp except Exception as e: logger.error(f請(qǐng)求異常: {e}) raise def get(self, url, **kwargs): return self.request(GET, url, **kwargs) def post(self, url, **kwargs): return self.request(POST, url, **kwargs)第二步寫(xiě)幾個(gè)常用的Fixture在conftest.py里管理測(cè)試前置和后置# conftest.py import pytest from common.request_util import RequestUtil pytest.fixture(scopesession) def base_url(): return https://api.example.com pytest.fixture(scopefunction) def login_token(base_url): 登錄獲取token測(cè)試用例依賴(lài)此fixture resp RequestUtil().post(/login, json{username: test, password: 123456}) token resp.json().get(data, {}).get(token) assert token is not None, 登錄失敗無(wú)法獲取token return token第三步寫(xiě)一條真實(shí)的業(yè)務(wù)測(cè)試用例# testcases/test_user.py import pytest from common.request_util import RequestUtil class TestUser: 用戶(hù)模塊接口測(cè)試 def test_get_user_info(self, login_token): headers {Authorization: fBearer {login_token}} resp RequestUtil().get(/user/info, headersheaders) assert resp.status_code 200 assert resp.json()[code] 0 assert username in resp.json()[data]3.3 參數(shù)化與數(shù)據(jù)驅(qū)動(dòng)測(cè)試用例寫(xiě)多了你會(huì)發(fā)現(xiàn)大部分用例只是參數(shù)不同邏輯完全一樣。這時(shí)候用Pytest的參數(shù)化功能可以把數(shù)據(jù)從代碼里抽出來(lái)# testcases/test_order.py import pytest from common.request_util import RequestUtil class TestOrder: 訂單模塊測(cè)試 pytest.mark.parametrize(order_id, expected_status, [ (A10001, 200), (A10002, 200), (NOT_EXIST, 404), ]) def test_get_order(self, login_token, order_id, expected_status): headers {Authorization: fBearer {login_token}} resp RequestUtil().get(f/order/{order_id}, headersheaders) assert resp.status_code expected_status數(shù)據(jù)量更大的時(shí)候建議把測(cè)試數(shù)據(jù)放到Y(jié)AML或Excel里用Pytest的鉤子函數(shù)讀取并生成用例。這樣測(cè)試人員維護(hù)用例時(shí)不需要改代碼只維護(hù)數(shù)據(jù)文件整體效率會(huì)高很多。3.4 執(zhí)行、報(bào)告與CI接入在項(xiàng)目根目錄執(zhí)行pytest -s -q --alluredir./reports/allure-results然后生成并打開(kāi)Allure報(bào)告allure generate ./reports/allure-results -o ./reports/allure-report --clean allure open ./reports/allure-report真正落到企業(yè)場(chǎng)景里是沒(méi)有人在本地手動(dòng)執(zhí)行測(cè)試的。我一般會(huì)在Jenkins/GitLab CI里配置流水線(xiàn)開(kāi)發(fā)代碼合并到主干分支之后自動(dòng)拉取代碼、構(gòu)建環(huán)境、執(zhí)行自動(dòng)化測(cè)試測(cè)試結(jié)束把Allure報(bào)告和測(cè)試結(jié)論推送到企業(yè)微信或釘釘群。版本質(zhì)量好不好看群里的報(bào)告就知道。這一套框架從零搭好大概需要兩三天但它帶來(lái)的價(jià)值是持續(xù)性的——之后每條新增用例都是在上面積累資產(chǎn)。4. AI自動(dòng)化測(cè)試從“自己能跑”到“自動(dòng)生成用例”2024年以來(lái)AI對(duì)整個(gè)測(cè)試行業(yè)的影響是顛覆性的。現(xiàn)在面試測(cè)試崗不問(wèn)AI相關(guān)的問(wèn)題反而奇怪。我大概從2023年下半年開(kāi)始認(rèn)真研究AI輔助測(cè)試到2024年已經(jīng)在自己團(tuán)隊(duì)里陸續(xù)落地了幾個(gè)場(chǎng)景。4.1 大模型怎么和自動(dòng)化測(cè)試結(jié)合AI在自動(dòng)化測(cè)試?yán)镒钪苯拥膽?yīng)用有三類(lèi)自然語(yǔ)言生成測(cè)試用例、元素定位優(yōu)化、智能斷言。自然語(yǔ)言生成測(cè)試用例不用多說(shuō)你告訴大模型“用戶(hù)注冊(cè)后能用手機(jī)號(hào)登錄”它能輸出一整套測(cè)試用例設(shè)計(jì)包括正常流、異常流、邊界值、安全性測(cè)試點(diǎn)。這個(gè)能力對(duì)測(cè)試人員來(lái)說(shuō)非常實(shí)用相當(dāng)于一個(gè)隨叫隨到的測(cè)試設(shè)計(jì)顧問(wèn)。智能斷言這塊最有意思。傳統(tǒng)斷言你得手寫(xiě)“響應(yīng)里的code等于0”但很多時(shí)候業(yè)務(wù)邏輯復(fù)雜你根本不知道什么樣的響應(yīng)才是“正確”的。我們可以把接口文檔、請(qǐng)求參數(shù)、響應(yīng)體一起丟給大模型讓它判斷這個(gè)響應(yīng)是否符合業(yè)務(wù)預(yù)期甚至讓它解釋判斷理由。這樣用例的魯棒性會(huì)提升不少。我在實(shí)際項(xiàng)目中用大模型做了第一版測(cè)試用例自動(dòng)生成腳本效果相當(dāng)不錯(cuò)。當(dāng)時(shí)我搭了一個(gè)Agent輸入一段需求描述它自動(dòng)拆解成用例列表然后調(diào)用一個(gè)“用例轉(zhuǎn)Pytest”的工具函數(shù)自動(dòng)生成可直接運(yùn)行的測(cè)試代碼。最后人工只需要審核和補(bǔ)充邊界場(chǎng)景效率至少翻了一倍。4.2 自己搭一個(gè)AI自動(dòng)化測(cè)試Agent很多人問(wèn)AI自動(dòng)化測(cè)試平臺(tái)到底怎么搭。其實(shí)核心思路并不復(fù)雜一個(gè)大模型接口比如國(guó)內(nèi)各家的大模型API都行一段Prompt模板再加上一個(gè)能調(diào)用工具的外部框架。給個(gè)簡(jiǎn)單示例用Python實(shí)現(xiàn)一個(gè)“需求描述轉(zhuǎn)測(cè)試用例”的Agent雛形from openai import OpenAI client OpenAI( api_keyyour_api_key, base_urlhttps://your_llm_endpoint ) def generate_test_cases(requirement: str) - list: prompt f 你是一名資深測(cè)試工程師請(qǐng)根據(jù)以下需求描述輸出測(cè)試用例。 要求每個(gè)用例包含用例名稱(chēng)、前置條件、操作步驟、預(yù)期結(jié)果。 只輸出JSON數(shù)組不要其他內(nèi)容。 需求描述{requirement} resp client.chat.completions.create( modelyour_model_name, messages[{role: user, content: prompt}], response_format{type: json_object} ) return resp.choices[0].message.content這段代碼雖然簡(jiǎn)單但已經(jīng)是“Agent”的雛形了有輸入、有思考提示詞、有結(jié)構(gòu)化輸出。進(jìn)一步可以加工具調(diào)用讓Agent能直接查詢(xún)數(shù)據(jù)庫(kù)、調(diào)用測(cè)試平臺(tái)API生成腳本甚至根據(jù)測(cè)試失敗日志自主分析原因并修復(fù)腳本。我自己搭A(yù)gent的時(shí)候踩過(guò)最大的坑是“想一口吃個(gè)胖子”——一開(kāi)始就想做一個(gè)全自動(dòng)的、不需要人工干預(yù)的測(cè)試平臺(tái)。后來(lái)發(fā)現(xiàn)不現(xiàn)實(shí)AI生成的用例準(zhǔn)確率大概八成的樣子剩下兩成需要人工修正。后來(lái)我把定位調(diào)整為“AI輔助測(cè)試人員干活”通過(guò)人機(jī)協(xié)同的方式落地效果立刻好了起來(lái)。4.3 小程序如何利用AI做自動(dòng)化測(cè)試小程序的自動(dòng)化測(cè)試一直是個(gè)痛點(diǎn)官方工具雖然能用但配置復(fù)雜對(duì)普通測(cè)試人員不友好。我的思路是利用AI把“手工操作路徑”翻譯成“自動(dòng)化腳本”。具體做法是用小程序開(kāi)發(fā)者工具錄制一段用戶(hù)操作路徑把操作日志導(dǎo)出然后讓大模型把這段操作日志翻譯成Miniprogram Automator或小程序云測(cè)平臺(tái)可執(zhí)行的腳本。相當(dāng)于你把“人怎么點(diǎn)”的過(guò)程描述一遍AI直接幫你生成“機(jī)器怎么點(diǎn)”的代碼。另外一個(gè)低成本方案是直接用Airtest這類(lèi)跨平臺(tái)UI自動(dòng)化工具。Airtest支持小程序web-view控件的識(shí)別配合圖像識(shí)別的兜底策略比純手工寫(xiě)控件定位要省力不少。再加上AI對(duì)控件樹(shù)的解析能力整體落地門(mén)檻已經(jīng)降到很低了。4.4 傳統(tǒng)測(cè)試和自動(dòng)化測(cè)試怎么融合很多小團(tuán)隊(duì)的情況是既有老一輩的手工測(cè)試又有新招的自動(dòng)化測(cè)試工程師兩邊經(jīng)?;ハ嗲撇簧?。手工測(cè)試覺(jué)得自動(dòng)化測(cè)試脫離業(yè)務(wù)自動(dòng)化測(cè)試覺(jué)得手工測(cè)試沒(méi)有技術(shù)含量。這個(gè)矛盾不解決團(tuán)隊(duì)效率一定起不來(lái)。我自己的做法是“分層融合”。把測(cè)試工作按功能分成三層核心回歸層由自動(dòng)化測(cè)試全量覆蓋每次迭代必須全量跑通新功能探索層以手工測(cè)試為主但手工測(cè)試人員必須邊測(cè)邊把穩(wěn)定模塊的用例補(bǔ)充到自動(dòng)化用例庫(kù)里全鏈路驗(yàn)收層靠自動(dòng)化冒煙關(guān)鍵業(yè)務(wù)人工走查雙保險(xiǎn)這個(gè)模式跑起來(lái)之后手工測(cè)試和自動(dòng)化測(cè)試不再是兩條線(xiàn)而是合在一起。手工測(cè)試釋放出來(lái)的時(shí)間可以用來(lái)設(shè)計(jì)更復(fù)雜的場(chǎng)景、做更多的探索性測(cè)試整體測(cè)試深度反而提升了。5. 持續(xù)集成與測(cè)試平臺(tái)從單機(jī)腳本到企業(yè)級(jí)基礎(chǔ)設(shè)施靠個(gè)人能力強(qiáng)薪資能到一個(gè)上限但想突破這個(gè)上限必須能把能力沉淀成系統(tǒng)和平臺(tái)。這也是我從“測(cè)試工程師”往“測(cè)試開(kāi)發(fā)專(zhuān)家”轉(zhuǎn)型的核心轉(zhuǎn)折點(diǎn)。5.1 把自動(dòng)化測(cè)試接入CI/CD流水線(xiàn)自動(dòng)化測(cè)試跑在本地價(jià)值打折一半。真正讓自動(dòng)化測(cè)試發(fā)揮威力的是把它嵌入研發(fā)流水線(xiàn)讓它成為代碼質(zhì)量的門(mén)禁。我自己常用的一套CI流水線(xiàn)邏輯是這樣的開(kāi)發(fā)提交代碼到主干分支觸發(fā)GitLab CI流水線(xiàn)流水線(xiàn)先執(zhí)行靜態(tài)代碼掃描和單元測(cè)試單元測(cè)試通過(guò)后自動(dòng)部署到測(cè)試環(huán)境測(cè)試環(huán)境部署完成后自動(dòng)觸發(fā)接口自動(dòng)化測(cè)試套件接口測(cè)試通過(guò)后再跑UI冒煙用例所有自動(dòng)化都過(guò)了機(jī)器人自動(dòng)在群里發(fā)布“提測(cè)通過(guò)”的消息任何一個(gè)環(huán)節(jié)失敗了流水線(xiàn)中斷開(kāi)發(fā)會(huì)第一時(shí)間收到失敗通知和失敗日志。這個(gè)過(guò)程聽(tīng)起來(lái)不復(fù)雜但實(shí)際落地的時(shí)候很多坑要踩測(cè)試環(huán)境不穩(wěn)定導(dǎo)致誤報(bào)、自動(dòng)化用例偶發(fā)失敗需要重試機(jī)制、不同分支并行部署導(dǎo)致環(huán)境互相污染。這些問(wèn)題不解決CI流水線(xiàn)就是一紙空文。我最后一般會(huì)給關(guān)鍵用例加“失敗自動(dòng)重試一次”的機(jī)制同時(shí)把重試也失敗的用例單獨(dú)標(biāo)記出來(lái)方便排查是環(huán)境問(wèn)題還是代碼問(wèn)題。日志一定要留全不然失敗了還要登服務(wù)器去翻日志效率太低了。5.2 自動(dòng)化測(cè)試平臺(tái)應(yīng)該具備哪些模塊單機(jī)版的pytest腳本可以自己用但沒(méi)法服務(wù)整個(gè)團(tuán)隊(duì)。企業(yè)級(jí)的自動(dòng)化測(cè)試平臺(tái)在我心目中的最低配置是這樣的用例管理模塊支持用例的在線(xiàn)編輯、分組、標(biāo)簽、責(zé)任人、關(guān)聯(lián)需求執(zhí)行調(diào)度模塊支持手動(dòng)觸發(fā)、定時(shí)觸發(fā)、代碼變更觸發(fā)三種方式節(jié)點(diǎn)管理模塊管理執(zhí)行機(jī)集群支持分布式執(zhí)行報(bào)告展示模塊匯總Allure或自研報(bào)告展示通過(guò)率、趨勢(shì)、耗時(shí)數(shù)據(jù)統(tǒng)計(jì)模塊統(tǒng)計(jì)每個(gè)模塊的自動(dòng)化覆蓋率、穩(wěn)定性、維護(hù)頻率告警通知模塊執(zhí)行失敗自動(dòng)通知相關(guān)負(fù)責(zé)人支持釘釘/企業(yè)微信/郵件我見(jiàn)過(guò)很多團(tuán)隊(duì)自己開(kāi)發(fā)平臺(tái)收不住手功能越加越多最后變成一個(gè)比業(yè)務(wù)系統(tǒng)還復(fù)雜的系統(tǒng)。我的經(jīng)驗(yàn)是平臺(tái)開(kāi)發(fā)要克制先滿(mǎn)足核心訴求再逐步完善周邊模塊。一個(gè)“小而穩(wěn)”的平臺(tái)遠(yuǎn)勝過(guò)一個(gè)“大而全”的爛尾項(xiàng)目。5.3 分布式執(zhí)行與耗時(shí)優(yōu)化用例量到幾千條之后單機(jī)串行跑完全部用例可能要兩三個(gè)小時(shí)。這個(gè)等待時(shí)間開(kāi)發(fā)團(tuán)隊(duì)往往接受不了。解決辦法是分布式執(zhí)行。我這邊實(shí)際用過(guò)的方案有兩種一種是Pytest的pytest-xdist插件把用例平均分配給多臺(tái)執(zhí)行機(jī)并行跑另一種是自己搭的執(zhí)行節(jié)點(diǎn)集群把用例按模塊拆分成任務(wù)隊(duì)列分發(fā)給空閑節(jié)點(diǎn)執(zhí)行。后者雖然麻煩但好處是可控性更強(qiáng)節(jié)點(diǎn)資源和任務(wù)優(yōu)先級(jí)都能自定義。我的經(jīng)驗(yàn)是如果團(tuán)隊(duì)規(guī)模不大pytest-xdist就夠用了如果用例量大、執(zhí)行機(jī)多建議還是自己做一個(gè)簡(jiǎn)單的任務(wù)調(diào)度中心。并行執(zhí)行還會(huì)引入另一個(gè)問(wèn)題測(cè)試數(shù)據(jù)隔離。多條用例同時(shí)跑的時(shí)候如果都去改同一條數(shù)據(jù)庫(kù)記錄互相影響會(huì)導(dǎo)致偶發(fā)失敗。我的做法是把用例涉及的數(shù)據(jù)盡量隔離每條用例用獨(dú)立的測(cè)試數(shù)據(jù)或者用事務(wù)回滾的方式恢復(fù)現(xiàn)場(chǎng)。6. 常見(jiàn)問(wèn)題和排查技巧實(shí)錄自動(dòng)化測(cè)試做了幾年踩過(guò)的坑比寫(xiě)過(guò)的代碼還多。挑幾個(gè)最常見(jiàn)的記錄下來(lái)希望能幫大家少走點(diǎn)彎路。6.1 元素定位老失敗腳本今天能跑明天就不行這個(gè)問(wèn)題在Web UI自動(dòng)化里非常常見(jiàn)。原因通常有三個(gè)前端代碼更新導(dǎo)致屬性變化、頁(yè)面加載慢導(dǎo)致元素還沒(méi)渲染出來(lái)就去點(diǎn)擊、按鈕或彈窗遮擋導(dǎo)致click不生效。我的定位策略是優(yōu)先用穩(wěn)定的數(shù)據(jù)屬性比如id或自定義的data-testid盡量不要用會(huì)動(dòng)態(tài)變化的class名和順序索引。同時(shí)所有元素操作前都要強(qiáng)制等待用顯式等待而不是強(qiáng)制sleep。顯式等待的意思是“等這個(gè)元素達(dá)到某個(gè)狀態(tài)再執(zhí)行下一步”而不是“死等3秒”。from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By element WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, submit_btn)) ) element.click()這種寫(xiě)法雖然看著啰嗦但它能穩(wěn)定解決大部分網(wǎng)絡(luò)波動(dòng)和渲染延遲導(dǎo)致的問(wèn)題。6.2 接口自動(dòng)化誤報(bào)率太高怎么辦接口自動(dòng)化跑完報(bào)了20條失敗結(jié)果人工一看15條是環(huán)境問(wèn)題、3條是測(cè)試數(shù)據(jù)問(wèn)題、只有2條才是真bug。這種情況多了團(tuán)隊(duì)就再也不信自動(dòng)化測(cè)試了。降低誤報(bào)率我一般從三個(gè)方向入手第一環(huán)境檢查前置。測(cè)試執(zhí)行前先跑一批“探針用例”檢查依賴(lài)服務(wù)是否可用、數(shù)據(jù)庫(kù)連接是否正常探針不通過(guò)就直接中止執(zhí)行不浪費(fèi)后面的時(shí)間。第二測(cè)試數(shù)據(jù)自動(dòng)準(zhǔn)備。用前置Fixture去創(chuàng)建依賴(lài)的數(shù)據(jù)比如測(cè)試“查詢(xún)訂單”之前先創(chuàng)建一個(gè)指定狀態(tài)的訂單測(cè)試結(jié)束再清理掉從根源上避免數(shù)據(jù)缺失導(dǎo)致的失敗。第三失敗通知里附上足夠的上下文。截圖、請(qǐng)求日志、響應(yīng)體、運(yùn)行時(shí)錯(cuò)誤棧都要收集齊全。這樣開(kāi)發(fā)拿到失敗通知的時(shí)候不需要登錄服務(wù)器就能定位是環(huán)境原因還是代碼問(wèn)題。6.3 自動(dòng)化測(cè)試腳本維護(hù)成本太高這是自動(dòng)化測(cè)試推行中最常見(jiàn)、最致命的難題。很多團(tuán)隊(duì)測(cè)試腳本寫(xiě)了一堆但每次前端一改版光維護(hù)定位符就要花掉一個(gè)測(cè)試人員一天的時(shí)間。維護(hù)成本大于節(jié)省成本自動(dòng)化就開(kāi)始變成負(fù)擔(dān)了。我自己的對(duì)策是嚴(yán)格限制UI自動(dòng)化的范圍只覆蓋最核心的業(yè)務(wù)主流程比如登錄、下單、支付這些高頻高價(jià)值的場(chǎng)景。細(xì)枝末節(jié)的頁(yè)面驗(yàn)證交給接口測(cè)試來(lái)覆蓋。接口層的請(qǐng)求參數(shù)和響應(yīng)報(bào)文比UI元素穩(wěn)定得多維護(hù)成本天然就低。另外元素定位器寫(xiě)好后盡量統(tǒng)一管理抽到單獨(dú)的定位文件里頁(yè)面結(jié)構(gòu)變化時(shí)只需要改一個(gè)文件不需要到每個(gè)用例里去找。6.4 測(cè)試環(huán)境不穩(wěn)定怎么處理測(cè)試環(huán)境不穩(wěn)定是自動(dòng)化測(cè)試的頭號(hào)殺手。經(jīng)常碰到的情況是被測(cè)服務(wù)掛了、上下游聯(lián)調(diào)環(huán)境沒(méi)通、數(shù)據(jù)庫(kù)被測(cè)試數(shù)據(jù)搞臟了、定時(shí)任務(wù)抽風(fēng)把關(guān)鍵數(shù)據(jù)寫(xiě)壞了。我處理環(huán)境不穩(wěn)定的經(jīng)驗(yàn)是給自動(dòng)化測(cè)試準(zhǔn)備一套獨(dú)立的測(cè)試環(huán)境和生產(chǎn)環(huán)境物理隔離避免相互影響環(huán)境上的服務(wù)、中間件、數(shù)據(jù)庫(kù)全部容器化壞了幾分鐘就能重置每次測(cè)試執(zhí)行前強(qiáng)制重置環(huán)境用腳本把所有服務(wù)的狀態(tài)和數(shù)據(jù)庫(kù)恢復(fù)到初始快照在流水線(xiàn)里加環(huán)境健康檢查環(huán)境不健康就不執(zhí)行測(cè)試直接報(bào)“環(huán)境異?!庇腥丝赡苡X(jué)得重置環(huán)境太麻煩但如果環(huán)境不穩(wěn)定導(dǎo)致的誤報(bào)浪費(fèi)的時(shí)間比重置環(huán)境的時(shí)間多得多這個(gè)賬算清楚就值了。7. 職業(yè)突圍的最后一步項(xiàng)目經(jīng)驗(yàn)、面試與薪資談判技術(shù)到位之后怎么讓市場(chǎng)給你開(kāi)高薪這是個(gè)信息差的問(wèn)題。很多測(cè)試同行技術(shù)不差但不會(huì)包裝自己結(jié)果面試拿不到好的Offer非常可惜。7.1 怎么把自動(dòng)化測(cè)試項(xiàng)目經(jīng)驗(yàn)寫(xiě)出含金量簡(jiǎn)歷和面試?yán)镏v項(xiàng)目經(jīng)驗(yàn)一定要避免“只會(huì)列工具”的寫(xiě)法。比如“負(fù)責(zé)搭建自動(dòng)化測(cè)試框架使用PytestRequestsAllure實(shí)現(xiàn)接口自動(dòng)化”這種描述說(shuō)實(shí)話(huà)放十年前還行現(xiàn)在看起來(lái)完全沒(méi)有區(qū)分度。我建議用“業(yè)務(wù)問(wèn)題-解決方案-量化收益”的框架來(lái)講項(xiàng)目。舉一個(gè)我自己的真實(shí)例子業(yè)務(wù)問(wèn)題項(xiàng)目每次發(fā)版前需要2名測(cè)試人員投入5天做全量回歸版本交付效率低解決方案搭建接口自動(dòng)化測(cè)試平臺(tái)覆蓋主流程和核心模塊接口用例3800條接入CI流水線(xiàn)代碼合并后自動(dòng)觸發(fā)測(cè)試用AI輔助生成用例提升用例編寫(xiě)效率量化收益全量回歸時(shí)間從5天縮短到4個(gè)小時(shí)版本發(fā)布頻率從每月1次提高到每周2次線(xiàn)上漏測(cè)率下降了60%這種寫(xiě)法把一個(gè)普通的自動(dòng)化測(cè)試項(xiàng)目講成了業(yè)務(wù)價(jià)值故事面試官一聽(tīng)就知道你不只是會(huì)寫(xiě)代碼而是能解決實(shí)際業(yè)務(wù)問(wèn)題。7.2 高頻面試題怎么答近幾年自動(dòng)化測(cè)試相關(guān)的面試題基本圍繞幾個(gè)方向一是框架原理類(lèi)Pytest的Fixture工作原理、Selenium的運(yùn)行機(jī)制、Appium的架構(gòu)分層。這類(lèi)題考察你有沒(méi)有真正深入理解工具背后的原理。二是場(chǎng)景設(shè)計(jì)類(lèi)給你一個(gè)被測(cè)系統(tǒng)讓你現(xiàn)場(chǎng)設(shè)計(jì)自動(dòng)化測(cè)試方案。這類(lèi)題考察的是系統(tǒng)設(shè)計(jì)能力回答時(shí)建議從分層架構(gòu)、環(huán)境管理、數(shù)據(jù)管理、執(zhí)行與報(bào)告、穩(wěn)定性保障幾個(gè)維度展開(kāi)。三是項(xiàng)目復(fù)盤(pán)類(lèi)你做過(guò)最復(fù)雜的自動(dòng)化測(cè)試項(xiàng)目是什么遇到的最大難點(diǎn)是什么怎么解決的這類(lèi)題不準(zhǔn)備好特別容易翻車(chē)。我有個(gè)技巧準(zhǔn)備三個(gè)有細(xì)節(jié)的“項(xiàng)目故事”每個(gè)故事講清楚背景、難點(diǎn)、行動(dòng)、結(jié)果面試基本穩(wěn)。四是AI結(jié)合類(lèi)有沒(méi)有用過(guò)AI輔助測(cè)試怎么用的效果如何建議沒(méi)有真實(shí)經(jīng)驗(yàn)的至少自己動(dòng)手寫(xiě)一個(gè)AI生成測(cè)試用例的小工具哪怕只在本地跑通面試時(shí)能講出細(xì)節(jié)就很有競(jìng)爭(zhēng)力。7.3 薪資談判的思路自動(dòng)化測(cè)試崗位的薪資范圍差異極大月薪15K到40K都有可能。除了城市和公司的差異更大的變量是你怎么證明自己的價(jià)值。我談判時(shí)一般會(huì)準(zhǔn)備一組數(shù)據(jù)我搭建的自動(dòng)化測(cè)試體系覆蓋了多少用例、節(jié)省了多少回歸時(shí)間、攔截了多少線(xiàn)上事故、支撐了多大的業(yè)務(wù)體量。然后結(jié)合這些數(shù)據(jù)說(shuō)明我能為團(tuán)隊(duì)帶來(lái)什么級(jí)別的效率提升。另外我建議大家不要只盯著薪資數(shù)字談而是談“角色定位”。比如你面試的崗位寫(xiě)著“測(cè)試工程師”但你可以主動(dòng)說(shuō)明自己可以承擔(dān)“測(cè)試開(kāi)發(fā)測(cè)試平臺(tái)建設(shè)質(zhì)量效能提升”的工作把崗位的想象空間撐大。薪資自然就有議價(jià)空間了。7.4 個(gè)人發(fā)展的一點(diǎn)真實(shí)心得最后聊點(diǎn)個(gè)人感受。測(cè)試這個(gè)崗位真的不是沒(méi)前途但“只會(huì)手工點(diǎn)點(diǎn)的測(cè)試”確實(shí)沒(méi)前途。技術(shù)的浪潮一直在往前走從手工測(cè)試到自動(dòng)化測(cè)試從自動(dòng)化測(cè)試到AI輔助測(cè)試每一次技術(shù)躍遷都會(huì)重新分配行業(yè)內(nèi)的薪資結(jié)構(gòu)。愿意持續(xù)學(xué)習(xí)、不斷把新工具、新方法引入到自己工作里的人永遠(yuǎn)有機(jī)會(huì)吃到這一波紅利。我見(jiàn)過(guò)不少同行學(xué)歷背景一般、起點(diǎn)也一般但就是因?yàn)榉较驅(qū)α恕⒎椒▽?duì)了幾年時(shí)間就實(shí)現(xiàn)了薪資翻幾倍。反觀(guān)那些一直在舒適區(qū)里不愿意走出來(lái)的確實(shí)會(huì)被行業(yè)慢慢淘汰。這篇文章沒(méi)有把自動(dòng)化測(cè)試吹得天花亂墜它確實(shí)有維護(hù)成本、有技術(shù)門(mén)檻、有落地阻力。但只要你掌握了正確的方法把它做成一套真正好用的體系市場(chǎng)和公司一定會(huì)用真金白銀為你的能力買(mǎi)單。