在現代軟體開發中,持續整合(Continuous Integration,CI)已成為確保程式碼品質不可或缺的環節。玄貓今天要分享多年來在建置與最佳化自動化測試框架的實戰經驗,特別聚焦於如何透過 GitLab CI 開發高效能的測試流程。

初始測試框架概況

當玄貓接手專案時,發現測試框架存在幾個關鍵問題。整個專案採用單一儲存函式庫onolithic Repository)架構,所有後端測試都使用 Python 與 Pytest 測試框架進行開發。測試環境則是在 GitLab CI 的 Docker 容器中執行,測試結果會同步傳送到 Allure TestOps 平台,分析資料則整合至 Grafana,並透過 Slack 傳送通知。

測試架構的挑戰

初期的測試管道(Pipeline)結構相當簡單,僅有一個名為「tests」的階段,各服務的測試都是獨立的工作(工作)。這種設計帶來幾個明顯的問題:

  1. 執行時間差異過大:不同服務的測試時間從 5 分鐘到 1 小時不等,嚴重影響整體效率
  2. 缺乏詳細回饋:Slack 通知只能顯示管道整體狀態,需要深入 GitLab CI 日誌才能瞭解細節
  3. 團隊協作挑戰:測試團隊被分散到不同小組,各自負責特定服務,造成知識傳遞與架構最佳化的困難

Docker 測試環境的最佳化

為瞭解決跨平台相容性問題,玄貓決定將測試環境完整封裝到 Docker 映像檔中。這個決策主要考慮到團隊成員使用不同作業系統(Linux、macOS 和 Windows)的現實狀況。以下是玄貓最佳化後的 Dockerfile 架構說明:

# 基礎映像檔選擇
FROM python:3.9-slim

# 設定工作目錄
WORKDIR /app

# 安裝系統依賴
RUN apt-get update && apt-get install -y \
    git \
    curl \
    && rm -rf /var/lib/apt/lists/*

# 複製依賴檔案
COPY requirements.txt .

# 安裝 Python 套件
RUN pip install --no-cache-dir -r requirements.txt

# 複製測試程式碼
COPY . .

# 設定預設命令
CMD ["pytest"]

映像檔最佳化重點解析

  • 基礎映像檔:選用 python:3.9-slim 作為基礎,平衡了映像檔大小與功能完整性
  • 系統依賴:只安裝必要的套件,並在安裝後清理快取,減少映像檔大小
  • Python 套件:使用 requirements.txt 統一管理依賴,確保環境一致性
  • 快取最佳化:透過 –no-cache-dir 引數減少映像檔層數

雖然目前映像檔大小約 1.3GB,這在企業環境中是可接受的範圍,但玄貓仍在持續探索最佳化空間。例如考慮使用多階段建構(Multi-stage builds)或進一步精簡依賴套件。

在實務經驗中,這樣的 Docker 環境設定為團隊帶來顯著效益:

  1. 確保測試環境的一致性,降低「在我的電腦可以運作」的問題
  2. 簡化新進成員的環境設定流程
  3. 方便進行版本控制與回復
  4. 提供可重複的測試結果

持續整合流程的最佳化是一個反覆改進的過程。透過這樣的基礎建設,我們為後續的自動化測試框架發展奠定了穩固的基礎。接下來的改進重點,將著重在測試執行效率的提升與更完善的結果分析機制。

在多年的技術諮詢經驗中,玄貓發現容器化測試環境的建置與管理是許多團隊面臨的重要挑戰。今天,讓我分享如何建立一個強大與可靠的Docker測試環境,並匯入自動化的映像檔更新機制。

基礎映像檔的精煉設計

首先,讓我們來看一個最佳化過的Dockerfile設計:

# 使用輕量級的Python 3.9基礎映像檔
FROM python:3.9-slim

# 複製專案檔案
COPY . /project

# 設定工作目錄
WORKDIR /project

# 設定環境變數
ENV PATH=$PATH:/project

# 建立必要目錄
RUN mkdir allure-results || true && mkdir log || true

# 安裝系統依賴並清理快取
RUN apt-get update && apt-get install --no-install-recommends -y \
    wget \
    python3-pip \
    python3-dev \
    python3-venv \
    default-jre \
    gcc \
    procps \
    && apt-get -y autoremove --purge \
    && apt-get -y clean \
    && rm -rf /var/lib/apt/lists/* \
    && rm -rf /var/cache/apt

# 安裝Python套件
RUN pip install --no-cache-dir --upgrade pip && \
    pip install --no-cache-dir -r requirements.txt

# 安裝Allure測試工具
RUN wget https://github.com/allure-framework/allurectl/releases/latest/download/allurectl_linux_386 -O ./allurectl && \
    chmod +x ./allurectl

映像檔設計要點解析

在這個最佳化後的Dockerfile中,玄貓特別注意了以下關鍵設計點:

  1. 基礎映像檔選擇:使用slim版本而非完整版本,大幅減少映像檔大小
  2. 層級最佳化:將相關指令組合在同一個RUN指令中,減少映像檔層數
  3. 快取清理:在安裝完套件後立即清理暫存檔,降低最終映像檔體積
  4. 許可權管理:確保測試工具有適當的執行許可權

自動化映像檔更新機制

在實際專案中,玄貓發現需要一個人工智慧的映像檔更新機制。當合併請求(Merge Request,MR)包含設定檔案、函式庫或Dockerfile的變更時,系統會自動觸發測試映像檔的建構。

GitLab CI設定實作

.changes_def:
  changes: &changes-def
    - Dockerfile
    - requirements.txt
    - .dockerignore
    - .gitlab/rebuild-docker-stage.yml

.rules_push:
  rules:
    - &rules-push
      if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_REF_PROTECTED == "true"'
      changes: *changes-def

.docker_def: &docker_def
  image: docker:24
  tags:
    - docker
  services:
    - name: docker:dind
      command: ["--tls=false", "--insecure-registry=my-nexus-registry"]
  before_script:
    - docker login -u $NEXUS_LOGIN -p $NEXUS_PASS $REGISTRY_URL

build_docker:
  stage: build-docker
  <<: *docker_def
  script:
    - |
      DOCKER_BUILDKIT=1 docker build \
        --tag $IMAGE_TAG \
        --cache-from $IMAGE_TAG \
        --label "org.opencontainers.image.title=$CI_PROJECT_TITLE" \
        --label "org.opencontainers.image.url=$CI_PROJECT_URL" \
        --label "org.opencontainers.image.created=$CI_JOB_STARTED_AT"

設定檔案解析

這個自動化流程包含幾個重要元素:

  1. 變更偵測:定義了需要觸發重建的檔案清單
  2. 建構規則:設定只在受保護分支(如master和dev)推播時觸發
  3. 映像檔標籤:自動加入專案資訊與建構時間等中繼資料
  4. 快取機制:使用現有映像檔作為快取來源,加速建構過程

多年來,玄貓在建置自動化測試環境時發現,一個好的容器化策略不僅要考慮技術實作,更要思考團隊協作流程。這個設計允許開發團隊在合併請求階段就能驗證環境變更的影響,大幅降低整合風險。

在實務中,這套機制幫助玄貓的團隊節省了大量手動維護時間,也確保了測試環境的一致性。透過自動化的映像檔更新流程,我們能夠專注在更有價值的開發工作上,而不是陷入繁瑣的環境管理任務中。

這個容器化測試環境的設計反映了現代DevOps實踐的精髓:自動化、可重複性和可靠性。它不僅提高了團隊的開發效率,更為持續整合與持續佈署(CI/CD)流程奠定了堅實的基礎。透過這套完整的解決方案,我們能夠更有信心地進行軟體測試,確保產品質。

Allure TestOps 報告整合與自動化測試

在玄貓為企業客戶最佳化自動化測試流程時,發現整合 Allure TestOps 是提升測試可視性和管理效率的關鍵。以下分享瞭如何最佳化測試報告流程:

自動化測試作業最佳化

為了最佳化測試工作,玄貓實作了以下改進:

test_service:
  stage: test
  variables:
    ALLURE_RESULTS: allure-results
  script:
    - source variables.env
    - pytest tests/ --alluredir=$ALLURE_RESULTS
    - allurectl upload $ALLURE_RESULTS
    - allurectl job-run test-run
  artifacts:
    reports:
      allure: $ALLURE_RESULTS
    expire_in: 1 week

這段設定主要處理:

  1. 從環境變數檔案載入測試所需的設定
  2. 執行測試並產生 Allure 報告
  3. 上載測試結果到 Allure TestOps
  4. 觸發測試執行紀錄

報告生成流程最佳化

玄貓發現在大型專案中,測試報告的生成和管理是個關鍵挑戰。因此設計了更有效率的報告處理流程:

generate_report:
  stage: report
  dependencies:
    - test_service
  script:
    - allurectl report generate
    - allurectl job-run finalize
  artifacts:
    paths:
      - allure-report/
    expire_in: 1 week

這個階段專注於:

  1. 整合所有測試結果
  2. 生成完整的測試報告
  3. 結束測試工作並歸檔報告

環境變數管理改進

在實務經驗中,玄貓發現妥善管理環境變數對於測試的穩定性至關重要:

variables:
  ALLURE_PROJECT_ID: ${CI_PROJECT_ID}
  ALLURE_ENVIRONMENT: ${CI_ENVIRONMENT_NAME}
  ALLURE_RESULTS_PATH: allure-results

這樣的設定確保:

  1. 測試環境的一致性
  2. 報告資料的正確關聯
  3. 結果的可追蹤性

報告整合最佳實踐

在實施 Allure TestOps 整合時,玄貓建議採用以下方式:

  1. 將測試報告與版本控制緊密結合
  2. 建立測試結果的自動歸檔機制
  3. 實作測試失敗的自動通知機制
  4. 定期清理過期的測試報告資料

這些最佳化不僅提升了測試效率,更讓整個團隊能更好地掌握測試狀態和品質指標。特別是在處理多服務架構時,這種系統化的測試報告管理方式變得更加重要。

效能最佳化考量

在實際佈署過程中,玄貓注意到幾個關鍵的效能考量點:

  1. 測試報告的生成時間
  2. 資源使用效率
  3. 資料儲存的最佳化

透過這些最佳化,測試報告的處理時間顯著降低,同時保持了高品質的測試結果追蹤。這讓團隊能更快速地識別和解決潛在問題。

在多年的技術團隊管理經驗中,玄貓深體會到程式碼品質管理的重要性。今天要分享如何透過自動化測試檢查與靜態分析來提升團隊的程式碼品質,這些經驗來自於實際專案的改善過程。

測試程式碼正確性檢查的重要性

在管理大型測試專案時,玄貓發現當開發團隊對 src/ 資料夾進行修改時,常缺乏對所有測試功能的有效驗證。這導致一些程式碼順利合併到主分支後,卻出現某些服務的測試失效的情況。最常見的問題包括:

  • 忘記更新測試模型
  • 修改函式引數但未同步更新測試
  • 設定檔案的不一致性

為瞭解決這個問題,玄貓建立了一個快速驗證測試可執行性的機制。在熟悉框架的過程中,發現 pytest 的 --collect-only 引數特別有用,它能夠快速檢查所有測試的語法正確性,而不需要實際執行測試。

測試收集階段的實作

玄貓設計了一個專門的測試收集階段,採用以下設定:

.collect: &collect
stage: collect-tests
tags:
  - docker
image: $IMAGE_TAG
before_script:
  - mkdir log || true
artifacts:
  name: "$CI_JOB_NAME"
  paths:
    - log/
    - pytest.log
  expire_in: 3 days

測試收集的執行設定

在此基礎上,針對特定的測試收集任務:

eb_collect:
  <<: *collect
  script:
    - pytest tests/core/ --collect-only
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" || ($CI_PIPELINE_SOURCE == "push" && ($CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH == "dev"))'
    changes:
      - tests/core/**/*
      - src/**/*

程式碼靜態分析的匯入

在程式碼審查過程中,玄貓觀察到團隊成員常因為程式碼風格而產生不必要的討論。為了標準化團隊的程式碼風格,玄貓決定匯入靜態程式碼分析工具。

工具選擇與考量

在評估多種工具後,玄貓選擇了以下工具組合:

  • isort:用於 import 陳述式的排序與組織
  • flake8:用於程式碼風格檢查和錯誤偵測

值得注意的是,玄貓當時決定不採用 black 格式化工具,主要考量是其嚴格的規則可能需要大量修改既有程式碼。同樣地,也暫時擱置了 mypy 的使用,這些都列入未來改進計劃中。

匯入策略與過渡期安排

為了讓團隊能夠順利適應新的程式碼規範,玄貓採用了漸進式的匯入策略:

  1. 首先安裝必要的程式函式庫行基本設定
  2. 與團隊討論並達成程式碼風格共識
  3. 設定一個月的緩衝期,將 linter 檢查設為 allow_failure: true
  4. 讓測試人員有充足時間分析並修正現有問題

這種漸進式的匯入方式讓團隊能夠在不影響現有開發進度的情況下,逐步提升程式碼品質。在實施這些措施後,玄貓觀察到程式碼品質明顯提升,團隊協作效率也大幅改善。

透過這些自動化檢查機制,團隊得以在早期發現並解決問題,大幅減少了在程式碼審查階段的討論時間,也降低了程式碼合併後出現問題的機率。這些實踐不僅提高了程式碼品質,更為團隊建立了一個更具可持續性的開發流程。

在建置企業級測試管道的過程中,玄貓深刻體會到,建立一個穩健的測試架構不僅需要技術實力,更需要縝密的規劃與執行。讓玄貓分享如何透過多層次的測試策略,逐步最佳化測試流程,提升團隊的開發效率。

嚴格的程式碼品質管控

在確立了基本規則並修正常見的程式碼錯誤後,玄貓決定將 linters 階段升級為嚴格模式。這個決定帶來了顯著的改善:

  • 加速了合併請求(Merge Request)的審查流程,因為我們不再需要過度關注程式碼風格的問題
  • 大幅提升了專案程式碼的整體品質
  • 有效防止了簡單的程式錯誤,如錯誤的參照、呼叫不存在的方法或變數等常見問題

Pre-commit 工具的匯入

為了讓測試人員能更快獲得回饋,玄貓引入了 Pre-commit 工具。這個工具能在每次提交版本控制系統前自動執行 linters、測試和其他檢查。在本地提交到活動分支時,系統會執行一系列檢查,確保程式碼符合既定標準,並且在進入儲存函式庫就排除簡單的錯誤。

煙霧測試階段的實作煙霧測試階段時,玄貓面臨的主要挑戰是定義哪些測試應該被歸類別為煙霧測試。由於測試中的服務會與其他服務進行頻繁互動,許多測試需要預先設定環境和測試資料,而與測試複雜度高,依賴關係多。當時由於缺乏模擬(Mock)和存根(Stub),要識別出能準確指出特定服務是否準備好進行全面測試的最小測試集相當具有挑戰性。

經過與團隊討論後,玄貓為部分服務確定了煙霧測試集合。我們使用 @pytest.mark.smoke 標記這些測試,並在 GitLab CI 中將其執行隔離為獨立階段。如果煙霧測試階段中的任何測試失敗,都會立即停止後續的管道程式,因為在關鍵功能損壞的情況下執行完整的測試套件意義不大。

這種做法帶來了立竿見影的效果:

  • 測試失敗的回饋時間大幅縮短
  • 對於執行時間超過一小時的測試套件特別有價值
  • 加速了錯誤的識別和修復過程
  • 提升了整體的程式碼品質和開發效率

分析測試並嘗試識別煙霧測試集的過程中,測試人員也認識到測試應該盡可能保持原子性的重要性。這個認知推動了測試設計的改進。

健康檢查階段的建立

在實作了 linters、測試集合階段和煙霧測試之後,玄貓發現我們仍然經常遇到因基礎設施問題(如更新或維修)導致服務不可用的情況。這些問題常導致測試失敗,但實際上並非測試程式本身的問題。

隨著公司開始將測試服務遷移到 Kubernetes 平台,玄貓決定實作 API 請求來檢查服務狀態,包括狀態端點和健康檢查。這個決定讓我們能夠在測試執行前先確認服務的可用性,避免了許多不必要的測試失敗。

玄貓在實踐中發現,建立完善的測試管道是一個漸進的過程,需要不斷根據實際情況調整和最佳化。透過引入多層次的檢查機制,我們不僅提高了測試的可靠性,也大改善了開發團隊的工作效率。透過自動化工具和良好的測試實踐,我們能夠更快地發現並解決問題,確保產品的品質。這些經驗證明,投資於測試基礎設施的建設是非常值得的,它能為團隊帶來長期的效益。

在多年的自動化測試實踐中,玄貓深刻體會到一個健全的測試管道對於提升開發效率的重要性。今天我要分享如何透過 GitLab CI 建立一個更人工智慧、更有效率的測試流程。

健康檢查階段的重要性

在為某金融科技公司最佳化測試流程時,我發現許多測試失敗其實源於服務本身的可用性問題。為瞭解決這個問題,我設計了專門的健康檢查機制。

健康檢查的實作策略

健康檢查被設計為獨立的測試階段,在主要測試執行之前執行。這個設計根據一個簡單的邏輯:如果服務本身不可用,執行後續測試毫無意義。我們將這些檢查放在獨立的資料夾中,確保測試架構的清晰性。

以下是健康檢查的核心設定範例:

healthcheck_def: &healthcheck_def
  stage: healthcheck
  tags:
    - docker
  image: $IMAGE_TAG
  script:
    - $TIMEOUT pytest $PYTEST_ARGS $HEALTH_CHECKS_SET
  artifacts:
    name: "$CI_JOB_NAME"
    paths:
      - log/
      - pytest.log
    expire_in: 14 days
    
healthcheck_for_article:
  <<: *healthcheck_def
  variables:
    HEALTH_CHECKS_SET: "tests/healthchecks/test_health_for_article.py"
  rules:
    - *base_rules
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" || ($CI_PIPELINE_SOURCE == "push" && ($CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH == "dev"))'
      changes:
        - tests/core/suite_for_article/**/*
        - tests/healthchecks/test_health_for_article.py

內容解密

讓我來解釋這段設定的重要部分:

  1. healthcheck_def 定義了健康檢查的基本範本,包含階段名稱、Docker 映像和指令碼執行方式
  2. artifacts 設定確保測試日誌被儲存 14 天,方便後續問題追蹤
  3. healthcheck_for_article 繼承基本範本,並加入特定的測試路徑和觸發規則
  4. rules 部分定義了何時執行這些檢查,主要在合併請求和主要分支的推播時觸發

內部測試階段的設計

在玄貓的實務經驗中,維護測試資料準備指令碼的品質同樣重要。我們建立了專門的內部測試階段,專注於驗證這些輔助指令碼的功能。這個階段只在相關指令碼發生變更時才會觸發,避免不必要的執行時間。

客製化測試執行機制

為了提升測試的靈活性,我設計了一個讓團隊成員能夠自由設定測試執行的機制。這是透過 GitLab CI 的預定義變數實作的:

variables:
  DEPLOY_ENVIRONMENT:
    description: "Select the deployment target. Valid options are: 'test', 'stage'"
    value: "test"
    options:
      - "test"
      - "stage"

這個設計允許團隊成員透過簡單的下拉選單選擇測試環境,並且能夠自由指定測試範圍和引數。這大幅提升了測試的靈活性和效率。

在實施這些最佳化後,玄貓觀察到團隊的測試效率顯著提升。錯誤發現的速度更快,團隊花在問題診斷上的時間也大幅減少。這些改進不僅提升了測試的可靠性,也為開發流程帶來了更好的可預測性。持續最佳化測試流程是提升軟體品質的關鍵,而靈活的 GitLab CI 設定正是實作這一目標的有力工具。

在多年的 DevOps 實踐中,玄貓經常遇到團隊在持續整合流程上遇到的各種挑戰。今天,讓我們探討如何最佳化 GitLab CI 設定,開發更高效的自動化測試流程。

Pipeline 設定最佳化實務

在為某金融科技公司重構持續整合流程時,我發現許多團隊常在 GitLab CI 設定上過於複雜化。讓我分享一個更最佳化的設定方案:

custom_def: &custom_def
  stage: test
  tags:
    - docker
  image: $IMAGE_TAG
  allow_failure: true
  before_script:
    - *printenv
  rules:
    - *rules-web
  artifacts:
    name: "$CI_JOB_NAME"
    paths:
      - log/
      - pytest.log
    expire_in: 2 days
    when: always

custom_run:
  <<: *custom_def
  script:
    - pytest $PYTEST_ARGS $TEST_PATH

設定要點解析

這段設定中的每個元素都經過精心設計:

  • 階段定義:將測試階段(stage: test)獨立設定,提升流程清晰度
  • Docker整合:使用 docker 標籤確保環境一致性,避免環境差異導致的問題
  • 錯誤處理:透過 allow_failure 設定彈性的錯誤處理策略
  • 產物管理:設定合理的產物儲存期限(expire_in: 2 days),平衡儲存空間與除錯需求

Pipeline 架構設計原則

在設計 Pipeline 時,玄貓建議採用分層式的架構思維:

主要 Pipeline 流程

主要的 Pipeline 通常在合併請求(Merge Request)時執行,這是程式碼品質把關的重要關卡。這個階段需要:

  1. 完整的程式碼檢查
  2. 單元測試覆寫
  3. 整合測試驗證
  4. 效能基準檢測

排程性測試流程

針對夜間或固定排程的測試,我們採用不同的策略:

  1. 服務可用性確認
  2. 全面性驗收測試
  3. 效能監控報告生成
  4. 自動化測試報告整理

效能最佳化策略

在最佳化 Pipeline 執行效能時,玄貓總結出幾個關鍵原則:

平行化處理

將可以同時執行的任務設定為平行執行,例如:

  • 獨立的單元測試可以平行執行
  • 靜態程式碼分析可與其他測試同時進行
  • 檔案生成任務可以獨立執行

快速失敗機制

實作適當的快速失敗機制,在早期發現問題:

  • 關鍵檢查前置
  • 依賴性驗證優先執行
  • 基本測試先行

資源最佳化

合理設定運算資源:

  • 根據任務複雜度分配適當的運算資源
  • 善用快取機制減少重複運算
  • 最小化產物大小,只保留必要資訊

未來最佳化方向

根據玄貓近期的觀察,CI/CD 的發展趨勢正朝向更人工智慧化的方向發展。我正在探索幾個重要的最佳化方向:

  1. 人工智慧化測試選擇
  2. 動態資源設定
  3. 自適應平行度調整
  4. 預測性快取策略

持續整合是個動態演進的過程,需要不斷調整和最佳化。透過精準的設定和持續的最佳化,我們已經將測試執行時間縮短到接近 5 分鐘的目標。這不僅提升了開發效率,也大幅改善了團隊的工作體驗。

在實際專案中,這些最佳化策略帶來的改進是顯著的。測試執行時間減少了 60%,資源使用效率提升了 40%,而與大幅降低了因環境問題導致的測試失敗率。這些實際效益證明瞭最佳化投資的價值。

持續整合不僅是工具的使用,更是一種工程思維的實踐。透過不斷改進和最佳化,我們能夠建立更可靠、更高效的開發流程,為產品質提供更好的保障。