測試策略的全知讀者視角:從金字塔到 AI 時代的多次轉變

測試策略的全知讀者視角:從金字塔到 AI 時代的多次轉變

測試策略的全知讀者視角:從金字塔到 AI 時代的多次轉變 本文由作者撰寫主要觀點,AI 協助資料蒐集、結構編排與文字潤飾,最終由作者審定。 前言 在現代軟體開發中,測試已不再是開發完成後才啟動的獨立階段,而是必須貫穿整個開發流程的核心實踐。 但隨著前後端分離、微服務架構的普及,以及 AI 輔助開發的崛起,「應該怎麼分配測試資源」這個問題也開始有了不同的答案。測試金字塔(Testing Pyramid)作為敏捷時代的經典模型,正在被測試獎盃(Testing Trophy)、測試蜂窩(Honeycomb)、測試鑽石(Diamond)、測試螃蟹(Crab)等新模型挑戰與補充。 本文將從歷史脈絡出發,梳理這些模型的起源、適用場景與侷限,幫助你在不同的架構與團隊情境下,做出更合適的測試策略決策。 測試金字塔 起源與架構邏輯 測試金字塔最早由 Mike Cohn 在其 2009 年的著作《Succeeding with Agile》

拒絕加班的藝術:為什麼「測試左移」是測試工程師準時下班的救星?

拒絕加班的藝術:為什麼「測試左移」是測試工程師準時下班的救星?

前言 常常上線前三天才開始測新功能,結果一跑測試才發現功能與當初的文件不符合,於是開始與 PM 和開發釐清,花了幾天的時間,才搞清楚功能規格,但上線日期不會因為這些事情而延後,但我的下班時間會? 我曾經試著將測試左移引導至開發流程裡,對於釐清使用者需求的效果不錯,但涉及團隊的開發習慣、公司組織架構與產品特性,落地的困難度不一。如果你和我真的很想準時下班,我們可以來重新看看「測試左移」會不會是測試工程師準時下班的救星。 測試左移的起源與定義 要理解左移能不能真的幫上忙,先看看它從哪裡來。 2001 年的時空背景 測試左移在 2001 年被提出,想要理解為什麼被提出,需要先理解當時的開發環境。首先要介紹瀑布模型(Waterfall Model)和 V 模型(V-Model)這兩個當時主流的開發模型。 瀑布模型(Waterfall Model) 由 Winston Royce 在 1970 年的論文中首次描述(諷刺的是,Royce 本人其實是在論述這個模型的缺陷)

你的 async 真的是 async 嗎?FastAPI 平行處理踩坑紀錄

你的 async 真的是 async 嗎?FastAPI 平行處理踩坑紀錄

#開發筆記 前言 這是一個 RTSP 攝影機串流模擬工具。主要功能是當收到 API 的請求後,用 ffmpeg 將原本錄製好的 mp4 檔案透過 RTSP 推出去,模擬多台攝影機同時輸入的情境。 但當我同時送出兩個 API request,我發現第二個請求一定會等到第一個請求跑完才開始處理。可是程式碼裡面我明明宣告了 async def,為什麼沒有同時平行處理呢? ThreadPoolExecutor 是什麼 Python 的程式預設是單執行緒,也就是說同一個時間只會有一條執行路徑在執行。ThreadPoolExecutor 是標準函式庫 concurrent.futures 所提供的工具,讓我們可以同時間執行多個執行緒來處理工作。 基本概念 from concurrent.futures import ThreadPoolExecutor def do_work(n): return n * 2 with ThreadPoolExecutor(

最新

Day 26|替購物車寫支自動化測試

Day 26|替購物車寫支自動化測試

前言 前 25 天幾乎沒碰測試碼。Day 25 那支回歸測試是第一次動筆,而且是為了釘住一個 bug 才寫的。今天把它當起點正式寫測試,讓探索一次性找到的東西,變成每次都會重跑的東西。 開始之前 把測試放在第 26 天是刻意的。 寫腳本這件事,現在很便宜。你可以在 Day 2 就叫模型生一支會跑的 Playwright 測試,它會跑、會綠、看起來很像回事。真正的問題在下一層:這支測試在驗什麼,以及它綠的時候你能不能相信它。 前 25 天做的就是這件事。你先學會判斷什麼算異常、什麼算 bug、證據要留成什麼樣、結論怎麼被獨立重現。有了這些,你才知道哪一條路徑值得固化成測試,也才知道斷言該卡在哪裡。 順序反過來的後果很具體:先寫一大批測試,然後花整年維護一批你不確定在測什麼的東西。 還有一條決定要說清楚。多一支測試就是多一份要養一輩子的資產,所以 test-author

Day 25|第一次修 Bug,才發現原本的測試也錯了

Day 25|第一次修 Bug,才發現原本的測試也錯了

前言 Day 24 放行之後,單開出去了。但有些 bug 不必等人排進 sprint,它自己就修得掉。今天讓它先重現、用先紅後綠的回歸測試釘住行為、最小幅度改產品碼,最後開一張 PR。開,但絕不自行合併。 開始之前 讓測試變綠最快的方法,是把測試改爛。刪掉那支測試、加個 .skip、把 toBe 放寬成 toBeTruthy,CI 立刻一片綠,PR 看起來很漂亮。 危險在於它跟真的修好長得一模一樣。報告上都是綠的,差別要打開 diff 才看得出來,而 diff 沒人逐行看。 所以修 bug 的順序不是流程建議,是防作弊機制。先重現,確定問題真的存在;再寫一支現在就會紅的測試,把「錯的行為」釘成一個看得見的失敗;然後才改碼,

Day 24|新同事找到八個問題,只有六個能開單

Day 24|新同事找到八個問題,只有六個能開單

前言 Hunter 說是 bug、Verifier 說重現得了,還要再看一次開單需要的資料有沒有齊。今天請一位同事守在開單前,照六項清單逐一檢查,全部通過才放行。這就是 Issue Quality Gate。 當時的紀錄是 6 筆 pass、2 筆 hold。不過,這兩筆 hold 的分法有問題,下面會一起說明。 開始之前 前面五天立了一堆規矩:要有證據、要命中 oracle、要算分、要查誤報名單、要去重、要獨立重現。每一條當時都同意,問題是它們現在都只是好習慣。 好習慣會被跳過。趕著收班的時候、只差一條的時候、覺得「這個一看就是 bug」的時候,人會自己放行。放行一次沒事,第三次之後前面五天等於白做。 閘門的作用是把這六條從「最好有」變成「

Day 23|請另一位同事照步驟重做,確認 Bug 能不能重現

Day 23|請另一位同事照步驟重做,確認 Bug 能不能重現

前言 讓新同事花了 30 分鐘竟然真的找出有問題的地方,可惡!這個地方我明明就測試了好幾次,甚至還有自動化測試涵蓋到,但新同事覺得有問題的地方,是不是真的是產品 Bug 呢? 畢竟由我這個資深的前輩來判斷的話,可能有失公正。於是請另一位同事交叉比對,看看照步驟從頭操作一次,是否同樣的現象會出現。 開始之前 bug-verify 執行前會需要前一天留下的完整證據,而這份證據包含保留待測試網址、前置條件、操作步驟、看到的現象、原始證據,以及哪些東西不在這次測試的範圍內,並且把為什麼是 Bug 的理由、信心分數和結論都會拿掉。 由 bug-verify 執行完的結果會有三種: * 獨立重現成功(confirmed):照著步驟重現問題成功 * 照著步驟跑不出來(not reproduced):照著步驟無法重現問題 * 證據不足判斷(inconclusive):證據不足於判斷這個問題 動手試試 昨天的完整證據整理一份給負責重現問題的同事的資料:保留受測網址、前置條件、操作步驟、看到的現象、

Day 22|讓 Bug Hunter 自己找問題,再交證據給我

Day 22|讓 Bug Hunter 自己找問題,再交證據給我

前言 經過前幾天的培養,新同事終於可以當我的代理人,開始獨立處理事情了。之前得由我一步步下指令,今天可以讓它照流程自己跑,最後列出結果,再讓我幫忙審核就好。 這一步也是為了將來輪值做準備。輪值時我可能不在身旁,新同事得靠自己處理,總不能每一步都停下來等我,畢竟我可不想在半夜的時候被叫起來上廁所。 回歸正傳,前面幾天我們已經學會怎麼探索問題、判斷是不是 bug、打信心指數,以及去除重複的問題。今天把這些步驟串起來,交給一位代理人(Agent)執行。 我們只需要給它一句話,它就會跑完整個流程,交回候選問題和證據,讓我這個資深的前輩審核。不過,今天先讓它找問題、交證據,開單的權限還沒給它,後面再說。 開始之前 bug-hunter 開跑前會先檢查三件事,缺一項就先停下來補齊: * charter(探索任務書)檔案存在且可讀:沒有 charter,代理人不知道要巡查哪個範圍、邊界在哪裡。若沒有,先叫 exploration-charter 產生一份 charter。

Day 21|報過的 Bug 別再開單,誤報也要記下來

Day 21|報過的 Bug 別再開單,誤報也要記下來

前言 Day 20 的分數只管單筆。可是跑多輪之後,同一個症狀會被重複撿到,判錯的那幾筆也會一再回頭。今天處理兩件事:確認過的誤判記進名單別再報,同一個指紋認得出來就不開第二張單。 為什麼需要去重與誤報名單 Day 20 的分數解決「哪一筆先看」,但它一次只看一筆。跑到第四輪你會發現另一個問題:同一個 bug 被撿到四次,四筆各自都拿到 high,分數看不出它們其實是同一件事。 本專案的索引現在是 18 張單,背後是 34 次觀察。不去重的話,issue tracker 收到的是 34 張,其中有 4 張都在講數量欄。開發者打開 tracker 第一件事不是修 bug,是先花時間判斷哪幾張是同一張。 誤報是另一個方向的浪費。有些症狀已經有人拍板過不是缺陷,例如未登入頁面打 /users/me 回 401。

Day 20|新同事報了八個問題,我該先看哪個?

Day 20|新同事報了八個問題,我該先看哪個?

前言 Day 19 放手跑完三輪,它交回三份檔案、七條 Oracle,判了三條 FAIL,還附上 needs-spec 與 inconclusive。問題是這些判定全出自它自己的嘴。今天替每一筆發現標一個信心指數,把「它說有問題」換算成「你要不要親自看一眼」。 為什麼需要信心指數 一輪探索交回來的東西是混在一起的:pass、fail、needs-spec、inconclusive、順手撿到的異常。你沒有時間逐筆讀完再決定要不要處理。 沒有分數只剩兩個選擇,兩個都不能用。全部自己看,Day 19 的放手等於白放;全部相信它,issue tracker 兩週就被塞爆。 分數的工作是排序與分流:哪些高到可以自動送去獨立驗證,哪些進人工佇列,哪些只留紀錄不往下走。 還有一個副作用同樣重要。要算分就得列出憑哪幾個因子,這逼它把「我覺得是 bug」拆成「複現幾次、

Day 19|讓新同事自己測一輪,結果卡在登入頁

Day 19|讓新同事自己測一輪,結果卡在登入頁

前言 前幾天我們給了新同事一份 charter,他學會自己選下一步,也學會去挑戰那些不在正常路線上的流程,最後還會判斷自己看到的東西算不算問題。 今天把這些接起來跑一次。我們只給目標,中間不插手,最後看他交回來什麼。 這篇不介紹新的 skill,跑的還是 explore。差別在於前四天是拆開來講每個零件,今天是完整走一遍,然後學會怎麼審。 為什麼放手之前要先定死交付物 放手最常見的失敗不是它做錯事,是它做完了你不知道該看哪裡。過程沒人盯,你手上只剩它交回來的東西,那批東西如果沒有固定形狀,審這件事就無從開始,最後只能整段重跑一次,等於沒放。 所以管控點要從過程搬到交付物:事前把目標、判準、邊界寫死,事後只審那三份檔案。交出去的東西定死了,中間怎麼走才可以完全不管。 放手不是把電腦推過去就走。要交出去的只有三樣,全部寫在 charter 裡: * 目標:goal 與 scope,這輪要走哪些畫面、找哪一類問題 * 判準:oracles,憑什麼說某個行為是錯的 * 邊界:out_of_

Day 18|它說這是 Bug,判斷的依據在哪裡?

Day 18|它說這是 Bug,判斷的依據在哪裡?

前言 昨天那一輪交回來的東西裡,有一筆很刺眼。 結帳地址那一步,postcode 欄位預填的值是字串 missing value。任何人看到都會皺眉:那明顯是程式內部代表「查不到值」的字面字串,怎麼會跑到使用者的表單裡,而且還通得過必填驗證。 value="missing value"、placeholder="Your Postcode *"。它是真的值,不是提示文字,不改就會被送出去。 但 finding 上寫的是 status: anomaly,不是 fail。 它看到了,卻不敢說那是錯的。今天要回答為什麼,答案是判準沒寫進 charter,它就不敢判。 為什麼沒有 oracle 就沒有 bug 「這是錯的」這句話,比大多數人以為的難講。 你說 postcode 不該顯示

Day 17|登入前先進結帳頁,會發生什麼事?

Day 17|登入前先進結帳頁,會發生什麼事?

前言 昨天新同事學會了如何收集證據,並且學會自己決定如何去探索我們給他的目標。然而在測試功能的時候,除了快樂路徑( Happy Path)之外,我們也必須要去檢查一些不是正常路線的非正常路徑。 所以今天要教這位新同事,怎麼走 Happy Path 以外的路徑。 為什麼要離開 happy path Happy path 有個很誘人的性質:它幾乎不會紅。 使用者照順序走、每一步都填對、不重整不返回不開第二個分頁 —— 這條路是產品被設計出來的樣子,也是開發自己測過最多次的路。你沿著它跑一百輪,得到的是一百次「正常」。 問題是缺陷不住在那裡。真實使用者會按上一步、會連點兩下、會把分頁放到隔天再回來、會直接把網址貼給同事。這些行為在 happy path 上一條都不會發生,所以那條路上的一百次綠燈,證明不了它們。 那為什麼不乾脆隨便亂點?因為亂點沒有依據,你事後說不出自己測了什麼、還有哪裡沒測。「非 happy path」不是一個地方,是無限多個地方,沒有一張表幫你挑,

Day 16|讓它自己選下一步,別一直測同樣的地方

Day 16|讓它自己選下一步,別一直測同樣的地方

前言 探索章程(Charter)的目標與內容都寫好了,今天讓新同事拿著它,自己決定怎麼探索這個產品。 今天的主角是 explore,它是 model-invoked,agent 遇到「依照這份 charter 去探索」這類任務會自行觸發,名字不用記。 用 charters/toolshop-checkout-payment.yaml 跑一輪探索 但如果你想指定 skill,可以這樣把它明確叫出來。 /sdet-skills:explore 用 charters/toolshop-checkout-payment.yaml 跑一輪探索 如果手上還沒有章程,先照昨天那篇把它生出來。 第三種方式是你可以不寫成 charter 檔。你可以在告訴這位新同事時,把目標、範圍、oracle、邊界四樣直接講給他聽。 這種方式適合一次性、不打算重跑的探索。

Day 15|這次只給測試目標,操作步驟讓它自己想

Day 15|這次只給測試目標,操作步驟讓它自己想

前言 在前幾天,我們都是告訴新同事我們需要什麼,而新同事幫我們去做這些工作。但今天呢,我們希望我們的同事可以更獨立一點,所以我們將不會告訴他要做哪些事情了。 從今天開始,新同事自己決定目標、自己決定界線,並且要如何探索。我們的角色將會從原本決策者變成一個 Mentor,而新同事則是除了執行者也是決策者。 而今天要教會他的東西就是,撰寫一份 Exploration Charter。 為什麼不繼續寫 test case Test case 有個很難承認的限制:它只驗得到你已經想到的那條路。 你寫「購買兩件商品,把數量改成零,檢查總金額不是負數」,它就永遠只會做這件事。負數這個點子是你想到的,那 charter 產生的價值就等於你的想像力,一個字都不會多。 這件事在人身上還算划算,因為人邊走邊想。但交給 agent 之後就不划算了:你多寫一步,它就多走一步,你沒寫的它一步都不會走。把每一步都寫死,等於花錢請它幫你按滑鼠。 要讓它走出你沒想過的路,你能給的就只剩三樣:要達成什麼、憑什麼算對、哪裡不准去。