Day 11|每個結論都要有證據:讓證據包能交棒

前言

教會新同事從畫面觀察 API 並收集相關證據,今天終於有空可以來仔細看看這份證據包。

我記得自己是測試新手的時候,常常因為興奮而發現 Bug,我迅速寫好標題、列出重現步驟,甚至附上 log ,開票給開發人員,送出。但卻常常因 log 未完整收集或缺少關鍵資訊,就必須要重現問題再收集 log,這樣一來一回超級浪費時間的。為了避免我們的新同事重蹈覆轍,作為一個資深前輩,我們要檢查這位新同事是否已完整收集證據,還是草率了事。

為什麼證據包要能交棒

「留了證據」跟「這包證據能交給別人」是兩件事,而中間那道差距只有在你需要交出去的那一刻才會現形 —— 通常是你已經把單開出去、工程師回你一句「我這邊重現不出來」的時候。

那道差距長什麼樣?把同一包東西放在兩個讀者面前就看得出來:

你自己讀 別人讀
「登入成功」 記得是用哪個帳號 哪個帳號?哪個環境?
一張購物車截圖 記得那是按下去之後 按之前還是之後?
「network 沒問題」 記得看過哪幾筆 哪幾筆?在哪個檔案?

你腦子裡那些「記得」,就是這包證據缺的東西。它們不在檔案裡,所以交出去的瞬間就蒸發了。

所以今天的驗收不看它留了幾個檔案,看一件事:把這包交給一個沒看過你操作的人,他重建得出你走過的路嗎?

實驗:一輪跑完,交回 21 個檔案

/sdet-skills:evidence-package 在 with-bugs 版登入後加一件商品進購物車,比對按鈕前後的 network 差異

經過我這位同事的一番努力之後,收集這些測試證據,我們今天就來看看有哪些證據,這些證據是不是足夠的。

output/evidence/20260806-with-bugs-add-to-cart/
  01-home-before.png
  02-login-before.png
  03-login-after.png              welcome01 被拒,POST /users/login → 401
  04-register-before.png
  05-register-after.png           POST /users/register → 201
  06-login-before.png
  07-login-after.png              新帳號登入,POST /users/login → 200
  08-account-after.png            導覽列顯示「User Data not found」
  09-product-before.png
  10-addtocart-before.png         按鈕前基準
  11-addtocart-after.png          按鈕後
  12-cart-after.png               小計 $00.00、總計 $14.15
  13-cart-after-reload.png
  console.log                     1 筆訊息、1 筆 error(broken.png 404)
  network.log                     收工導出(只涵蓋當下那一頁)
  network-before-click.log        按鈕前的請求清單,11 筆
  network-after-click.log         按鈕後的請求清單,11 筆
  network-diff.txt                前後併排與 diff 結果
  manifest.md
  notes.md
  trace.zip                       19 MB

截圖

首先,將點選購物車前後的畫面都截圖,並依編號排序,檔名以狀態命名,甚至依指令在檔名加上 -before、-after。如此閱讀者可直觀了解測試者操作前後的關聯,例如,使用 welcome01 時登入失敗,能清楚看到輸入的帳號、密碼以及系統返回的錯誤訊息。我的同事一開始使用 welcome01 登入失敗,並未因此中止測試,而是直接建立新帳號再登入。因為此次測試的驗證是商品加入購物車的前後的行為,只要帳號能夠登入就可以,我的同事避開了這個錯誤。

08-account-after.png:登入成功了,導覽列卻說查無使用者。

另外,08-account-after.png 裡導覽列顯示的「User Data not found」也很可疑,但同一頁的 GET /users/me 明明回 200 OK。這一輪要驗的是加入購物車的前後行為,所以我沒有往下追,只把它記成待查項 —— 看到異常不一定要當場定罪,但一定要留在證據包裡,這件事第 13 天會專門講。

console.log

有時候,我們會需要看一下 console 有沒噴一些錯誤或是洩漏一些機密的資訊出來(例如:帳號密碼等等)。由收到的訊息看來,左上角圖片載入失敗是因為找不到對應的資源,整輪只有這一筆錯誤,其餘畫面上的問題 console 一聲都沒吭。乾淨的 console 也要留 —— 「畫面壞了但 console 沒有錯誤」本身就是一項判斷依據,沒留這份檔,下次還得重跑一次才知道。

Total messages: 1 (Errors: 1, Warnings: 0)

[ERROR] Failed to load resource: the server responded with a status of 404 () @ https://with-bugs.practicesoftwaretesting.com/broken.png:0

network-before-click.log 和 network-after-click.log

[GET] https://api-with-bugs.practicesoftwaretesting.com/products/1 => [200] OK
[GET] https://api-with-bugs.practicesoftwaretesting.com/products/1/related => [200] OK
[POST] https://with-bugs.practicesoftwaretesting.com/cdn-cgi/rum? => [FAILED] net::ERR_ABORTED
[POST] https://with-bugs.practicesoftwaretesting.com/cdn-cgi/rum? => [FAILED] net::ERR_ABORTED
[GET] https://api-with-bugs.practicesoftwaretesting.com/users/me => [200] OK
[GET] https://api-with-bugs.practicesoftwaretesting.com/users/me => [200] OK
[GET] https://api-with-bugs.practicesoftwaretesting.com/products/1 => [200] OK
[GET] https://api-with-bugs.practicesoftwaretesting.com/products/1/related => [200] OK
[GET] https://with-bugs.practicesoftwaretesting.com/broken.png => [404] 
[POST] https://with-bugs.practicesoftwaretesting.com/cdn-cgi/challenge-platform/h/b/jsd/oneshot/8eb6d5cd556e/0.3101194504382597:1785945635:Mz0a1CtDwFXr-fAvYAYNRKEkXnF0dwJovkMqM3w9j7Y/a267493629977d50 => [200] 
[POST] https://with-bugs.practicesoftwaretesting.com/cdn-cgi/rum? => [204] 

如果仔細比對兩份 log 你會發現,加入購物車沒有發送任何一個 API 請求,表示沒有送出任何一個 POST /carts 請求,這個不一定是錯誤,因為這份證據顯示出購物車的資料會放在 sessionStorage.cart 有值:

[{"id":1,"is_rental":0,"name":"Combination Pliers","quantity":1,"price":14.15,"total":14.15}]

12-cart-after.png:同一張表裡兩個數字打架,這一筆不需要對照組就判得動。

而且同一份資料還牽出另一個問題:sessionStorage.cart 裡的 total 明明是 14.15,購物車頁面那一列的小計卻顯示 $00.00,表格底部的總計又算回 $14.15,同一張表自己跟自己打架。這一筆跟前面那個「沒發請求」不一樣 —— 它不需要拿乾淨版來比對,光讀畫面上的兩個數字就知道不對。

如果想要知道所有證據的用途可以參考 manifest.md,這個檔案列出所有證據的目的、環境、當下截圖的原因,和比較,同時你也可以看到新同事會把看到的結論寫在 notes.md 裡面,對我們而言,你可以把 manifest 當作是給其他 Agent 看的,結論則是給我們做判斷。

如果想要知道每個步驟的流程,如同我們之前介紹的一樣,可以使用 https://trace.playwright.dev/ 開啟 trace.zip 就會得到下列這個畫面:

  1. 最上方會依時間軸顯示每個時間點的畫面
  2. 左邊則會顯示每個步驟的順序與花費時間
  3. 右邊則會顯示當下動作的畫面
  4. 下方則是可以看到新同事點選哪個元件、是不是有任何 Error 產生,甚至整個網路流量都會被記錄下來。

透過這樣的測試證據,彷彿你人就在現場,一張圖就會搭配一個步驟,甚至過了幾天再打開,你都可以很清楚當時做了哪些事情。

檔名 目標
manifest.md 可以知道這個是什麼環境、或是使用哪個帳號執行
trace.zip 可以知道當下回放的畫面
console.log 可以知道有沒有任何前端的錯誤
before 截圖 可以比較前後行為的差異
合規的檔名 10-addtocart-before.pngnetwork-before-click.log 讀檔名就知道是哪一步、哪個時間點

這樣的證據足夠了嗎

所以,我們要回到一開始的問題,這樣的證據是足夠了嗎?如果要重現 UI 或是 API 問題,當時的步驟與流程也完整重現得出來,我想應該是足夠的,我們甚至可以問自己幾個問題:

問題 答得出來嗎 靠哪一份
你在哪個環境、用哪個帳號 可以 manifest.md
按鈕按下去到底發生什麼事情 可以 network-diff.txttrace.zip
「小計 0」這是發生在哪個情況下 可以 12-cart-after.png

manifest.md 與 notes.md 有什麼不一樣

兩份都是 markdown,都是同一輪寫出來的,第一次看到會覺得內容很類似。但其實它們的閱讀對象和內容是針對不同的問題。

manifest.md 回答「證據裡有什麼」:任務目標、環境(哪個網站、哪個帳號)、時間、trace 狀態、步驟與截圖的對應表、每個檔案有哪些、這一包的測試證據有哪些限制。

notes.md 回答的是「我看到什麼、所以我主張什麼」:步驟、觀察、結論,每條結論至少連結至一項證據。

「Add to cart」一支請求都沒發,是 finding。 證據:network-diff.txt(前後 11 筆全同)、sessionStorage.cart 有值而無 cart id;對照組 ../20260806-clean-add-to-cart/network-diff.txt 同一動作發 2 支(POST /carts → 201、POST /carts/{id} → 200)。沒有對照組,這個 0 只是「不知道正不正常」。

同一件事,manifest.md 只會寫「按鈕前後的請求清單各一份,diff 結果在 network-diff.txt」,不會說那是不是問題。一份負責讓你找得到東西,一份負責主張。

小結

一份能交棒的證據包要湊齊四樣:狀態命名且編號連續的截圖、獨立成檔的 console 與 network(乾淨也要留)、能回放的 trace,還有 manifest.mdnotes.md 這兩份分工明確的說明。驗收方法不是數檔案有幾個,是拿三個問題去問這一包 —— 你在哪個環境用哪個帳號、按下去到底發生什麼事、那個異常出現在哪一格 —— 三題都指得到檔案,別人才不必重跑一次。而且看到但這輪不打算追的東西(像那句 User Data not found)也要留在包裡,別讓它消失在你的記憶中。

        一輪操作 → 21 個檔案
                  │
    ┌─────────┬───┴────┬─────────┬─────────┐
    ▼         ▼        ▼         ▼         ▼
  截圖    console.log network-*  trace.zip  manifest
 狀態命名   乾淨也要留  前/後/diff  可回放    + notes
 編號連續                                      │
    │         │        │         │            │
    └─────────┴────┬───┴─────────┴────────────┘
                   ▼
            拿三個問題去問這一包
      哪個環境哪個帳號?按下去發生什麼事?
            那個異常在哪一格?
                   │
       ┌───────────┴───────────┐
       ▼                       ▼
   三題都指得到檔案         有一題答不出來
       │                       │
       ▼                       ▼
   可以交棒                 那是感想,要補
                   │
                   ▼
        manifest = 這包裡有什麼(找得到)
        notes    = 我主張什麼(每條掛證據)

證據包的驗收標準是別人不必重跑,湊不齊就會變成一來一回的重現地獄,那正是新手最常付的學費。乾淨的檔案也要留,「畫面壞了但 console 一聲都沒吭」本身就是一項判斷依據。而 manifestnotes 不能合成一份,一份負責讓你找得到東西,一份負責主張,混在一起就分不出哪句是觀察、哪句是推論。

下一步

即使拿到這麼完整的一包,有件事它還是答不出來:這一輪到底幾件事符合預期、幾件不符、幾件是根本沒測到。

notes.md 每條結論都掛著證據,這對人類閱讀已經足夠了 —— 換成人以外的讀者,它就答不上來。因為它是散文:「登入成功」「加入購物車沒發請求」「小計顯示 $00.00」寫在同一段裡,人讀得懂,機器數不出來,沒辦法統計、沒辦法比對上一輪、也沒辦法交給下游的 skill 自動接手。

而且散文只有兩個結局:是問題、不是問題。真實情況遠不只這兩種 —— 環境掛掉根本沒測到、時好時壞、看到了但證據不足以判斷,全都被塞進「不是問題」這一格。

明天就來處理這件事:測試結果不能只有 Pass 和 Fail

---

參考資料

  1. Simon Tatham — How to Report Bugs Effectively - 1999 年的文章,「可重現」這條標準的原型
  2. Playwright — Trace Viewer - 逐步回放這一輪操作,截圖與 network 都在同一份檔案裡
  3. Playwright Trace Viewer 線上版 - 純前端,把 trace.zip 拖進去就能看,對方不用裝任何東西
  4. Playwright — Network - 前後兩份請求清單是怎麼導出來的
  5. Toolshop(Practice Software Testing)正常版本 - 對照組,用來量出 with-bugs 版少發了哪幾支請求
  6. with-bugs 版 - 本篇的文章的測試網站