我看到 Uncle Bob 在 X(連結)上發了一篇貼文(《Clean Code》的作者),獲得數千次轉發。文中提到他已經不再閱讀程式碼。是的,就是那位曾寫過「開發者讀程式碼的時間遠多於寫程式碼,所以程式碼應該易讀」這句話的人。
那 Uncle Bob 的方法是什麼?與其閱讀 AI agent 寫的程式碼,他選擇要求這些 agent 針對程式碼撰寫大量測試。
當然有人贊成,也有人反對。如果你不讀程式碼,程式碼所有權的意義就變得模糊。但如果你把所有程式碼都讀完,你就會失去大部分生產力。我無法在此下判斷或提出我的「寶貴」意見。我決定寫這篇文章(我很少寫文章)是因為這裡或那裡反覆出現同一個議題。
現在有很多討論都在談如何驗證 AI。當然,生物學與生物資訊學的驗證和軟體工程的驗證並不相同,但我覺得兩者之間有一些有價值的重疊。
討論串和轉發提到了程式設計師(包括 Uncle Bob)用來約束 AI agent 的各種測試。深入了解後,我發現測試的世界比我身為生物資訊學家原本預期的還要大得多。
正確性
- 單元測試 – 隔離檢查個別函式或小型程式碼單元。它們檢查邏輯、錯誤處理和邊界條件。這是最廣為人知的軟體測試類型。
- 整合測試 – 檢查不同模組是否能正確一起運作(例如,你的 API 是否能與資料庫溝通)。
-
功能測試 – 從黑箱、需求的角度驗證軟體是否執行其應有的功能。你給軟體輸入資料,並查看輸出結果。例如,如果你撰寫一個新的 SNV 呼叫管線,你會輸入定序資料與參考序列,並檢查管線是否能以所需的靈敏度和特異性輸出已知的 SNV。
功能測試還有一些常見的子類型值得了解:- 冒煙測試 – 快速檢查基本功能是否運作,例如用預設參數執行你的軟體。
- 回歸測試 – 檢查最近的更新是否破壞了現有功能。
- 使用者驗收測試 (UAT) – 檢查真實使用者是否確認其需求已滿足。「真實使用者」可以是從 GitHub 下載你工具的社群科學家,或是早期存取或共同開發計畫中選定的合作夥伴。和其他類別一樣,UAT 也有自己的子世界:alpha 測試、beta 測試、商業價值驗證、軟體是否符合合約標準的驗證,以及是否符合法規要求的驗證(GDPR、HIPAA、FDA)。注意:儘管名稱相似,驗收測試(下文)是由開發人員/QA 執行,而 UAT 是由真實使用者在真實使用情境中執行。
驗收測試 / Gherkin 測試 – 確認完整功能滿足其建立時的商業需求。Gherkin 測試以結構化、可讀的格式撰寫(Given/When/Then),讓非工程師無需閱讀程式碼就能審查預期行為:Given 描述情境,When 描述軟體捕捉到的特定使用者動作或事件,Then 描述預期結果。
-
真值集 / 黃金資料集測試 – 這不是來自 Uncle Bob,而是來自我的生物資訊學經驗。在生物資訊學,特別是臨床生物資訊學中,由於濕實驗的種種因素,很難產生合成測試。因此,生物學非常依賴真值樣本。這值得另開一篇文章,但對於 NGS(我的主要專業領域),MDIC SRS 報告:NGS 體細胞變異參考樣本是一個很好的概覽資源。這份報告來自 2019 年,可能有些過時——其中確實有很多失效連結——但我最近還在使用其中描述的樣本。它描述了幾類參考材料:
- 合成 DNA – 將帶有預先定義遺傳變異的合成 DNA 序列加入高度特徵化的 DNA 中。
- 基因組 DNA – 帶有特徵化變異的 DNA 材料。
- 游離細胞 DNA – 從血液樣本中萃取的 DNA 材料。
- 人類細胞株 – 經過廣泛研究的永生化細胞株。Genome In A Bottle (GIAB) 可能是最著名的,可用來評估你的系統處理高品質 DNA 的能力。
- 組織 / 福馬林固定石蠟包埋 (FFPE) – 許多臨床樣本為了組織學原因被保存為 FFPE。然而,對於 NGS 而言,FFPE 樣本製備過程具有高度破壞性,會產生高度片段化且受損的 DNA。但由於 FFPE 在臨床上的重要性,許多生物資訊 NGS 工作流程都應該在 FFPE 樣本上進行測試。
- 正交驗證測試 – 這是我另一個生物資訊學的貢獻。當你沒有好的、市售的特徵化樣本時,另一種驗證方法是將你的輸出結果與兩種或更多獨立方法進行比對。例如:NGS、Sanger 定序、長讀取技術、光學圖譜、細胞遺傳學等。
壓力下的穩健性
-
效能測試 – 在預期或尖峰負載下測量回應時間、吞吐量和資源使用量,以捕捉回歸問題。這在雲端運算中特別重要,因為高估運算資源會導致超額支付,而低估則可能導致系統崩潰。我認為對生物資訊學家最相關的子類型有:
- 負載測試 – 最簡單的效能測試形式:系統(在我的案例中是生物資訊管線)在正常負載下的表現如何?例如,你預期公司每天處理 100 個 NGS 樣本,每個樣本約 1000 萬讀取對。
- 壓力測試 – 系統在超過正常負載的情況下會如何表現?如果某天需要處理 10,000 個樣本,或是每個樣本有 1 億讀取呢?
- 折磨測試 – 將系統推向極端、高負載或邊界條件,以找出它真正崩潰的地方。你的管線會在 1 億讀取的樣本上崩潰嗎?2 億讀取呢?
關於這些測試成本的一點提醒(FinOps——我最近學到的新術語之一):在雲端環境中,測試太多情境可能會變得很昂貴,而錯過一個長時間無人注意的停滯程序也可能造成高昂代價。本機 HPC 使用者和 DevOps 團隊如果看到你讓節點過載並導致其他工作排隊很久,也會很不高興。
嚴謹性檢查(測試測試本身)
- 突變測試 – 刻意在程式碼中引入小錯誤,並檢查現有測試套件是否能捕捉到這些錯誤——例如,透過替換常數值、改變決策邏輯或跳過程式碼結構。如果測試仍然通過,表示測試套件不夠嚴謹。
- 測試涵蓋率 – 測量程式碼庫中有多少百分比實際被測試執行,標記未測試的區域。當然,測試的品質比涵蓋率數字本身更重要。
- 可重現性 / 確定性測試 – 這不在討論串中,但我覺得這在生物資訊學和 AI 中都很重要。使用機率性方法時,需要多次測試輸入,以確定輸出是否穩定。AI/ML 本質上大多是機率性的,而生物資訊學即使沒有明確使用 AI/ML,也可能涉及取樣或其他機率性技術。
另一個變異來源是切換軟體或套件版本——即使是小版本更新,結果也可能發生戲劇性變化。CLIA/CAP/CLEP 法規要求在軟體變更時重新評估。
非功能性與系統性檢查
- 安全性測試 – 尋找漏洞而非功能正確性:敏感資料是否安全、使用者權限是否如預期運作、系統是否受到程式碼注入保護?
-
架構檢查 – 自動驗證程式碼是否遵守定義的架構邊界和依賴規則:所有模組是否按預期連接、命名慣例是否遵循、套件使用是否一致(例如,你在同一個 Python 專案中不會同時使用
os和pathlib做同一件事)、你的依賴圖是否避免循環? -
品質指標 – 一般程式碼健康指標(循環複雜度、依賴結構、模組大小),它們在不逐行閱讀程式碼的情況下提示可維護性。一些有趣的指標有:
- 缺陷密度 – 每 1000 行程式碼發現的錯誤數量。
- 缺陷逸出率 – 在生產環境中發現的錯誤佔測試中發現錯誤的百分比。
- 缺陷解決時間 – 修復錯誤所需的時間。
Google 的 DORA(DevOps Research and Assessment)小組提出了一套相關但不同的指標。雖然軟體測試品質指標試圖在發布前預測軟體成功,DORA 指標則在程式碼進入生產環境之後評估軟體交付效能。DORA 將其指標分為吞吐量和穩定性:
吞吐量
- 前置時間 – 將已提交的變更帶到生產環境所需的時間。
- 部署頻率 – 在給定時間段內的生產發布次數。
- 失敗部署恢復時間 – 缺陷解決時間的鏡像,但是在生產環境中測量。對我而言,它同時跨越吞吐量和穩定性。
穩定性
- 變更失敗率 – 缺陷逸出率的姊妹指標:需要立即介入才能進入生產環境的部署/發布比例。
- 部署返工率 – 因生產事故而觸發的非計劃性生產發布所佔的比例。
探索性正確性
- 屬性測試 – 不檢查特定的輸入/輸出配對,而是定義程式碼必須始終滿足的一般不變量,然後生成許多不同的輸入來嘗試打破這些不變量。
對我而言,屬性測試感覺與「正確性」一節中的單元/整合/功能測試相似。主要的心態轉變是思考你的函式應該具有什麼屬性,而不是它應該產生什麼確切的輸出。例如,假設你正在測試一個尋找 DNA 基序的函式。在單元測試中,你會思考邊界條件:包含該基序的 DNA 片段,以及不包含該基序的片段。在屬性測試中,你會定義不變量:如果輸入的 DNA 包含該基序,函式返回其座標;如果沒有,返回 -1。然後你生成遵循此規則的隨機 DNA/基序配對,並查看函式破壞了多少次。
流程與人類層面
- QA 程序 – 更廣泛的、通常是手動的品質工作流程,從使用者/產品的角度檢查軟體。
- 生成產物審查 – 審查 agent 在程式碼周圍產生的文件、設定和圖表,作為正確性的另一個代理指標——一種交付物的合理性檢查。
我並沒有使用過所有這些測試,我甚至不確定所有這些測試都屬於典型的生物資訊管線——儘管生物資訊學一直在試圖與軟體工程實務融合。我仍然認為,熟悉這些概念對於與軟體團隊和 AI 編碼代理合作非常有價值。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.