現代軟體開發講求快速迭代和高品質交付,因此CI/CD流程中,自動化測試至關重要。本文將探討如何在Jenkins Pipeline中,利用平行測試策略,搭配ESLint、Mocha等工具,顯著提升測試效率與程式碼品質。同時,我們也會示範如何整合Docker和模擬資料函式庫,建構更穩定可靠的測試環境。此外,Blue Ocean檢視的使用,也能幫助團隊更清晰地掌握測試進度和結果,進而快速識別和解決問題。最後,透過整合SonarQube,我們可以更全面地分析程式碼,提升整體軟體品質。

在Jenkins中執行平行測試與提升程式碼品質

在現代化的持續整合(CI)流程中,測試的效率和程式碼品質是至關重要的。本篇文章將探討如何在Jenkins中執行平行測試,以及如何透過程式碼分析提升程式碼品質。

使用Jenkins執行平行測試

Jenkins提供了強大的平行測試功能,可以顯著提升測試效率。透過使用parallel指令,可以將多個測試階段平行執行。

node('workers'){
    stage('Checkout'){
        checkout scm
    }
    def imageTest = docker.build("${imageName}-test", "-f Dockerfile.test .")
    stage('Pre-integration Tests'){
        parallel(
            'Quality Tests': {
                imageTest.inside{
                    sh 'golint'
                }
            },
            'Unit Tests': {
                imageTest.inside{
                    sh 'go test'
                }
            },
            'Security Tests': {
                imageTest.inside('-u root:root'){
                    sh 'nancy Gopkg.lock'
                }
            }
        )
    }
}

內容解密:

  1. node('workers'):指定Jenkins代理節點來執行任務。
  2. stage('Checkout'):簽出原始碼。
  3. docker.build:建立Docker映像檔。
  4. parallel:定義平行執行的多個測試階段。
    • Quality Tests:執行程式碼品品檢查。
    • Unit Tests:執行單元測試。
    • Security Tests:執行安全性測試。

提升程式碼品質與靜態程式碼分析

靜態程式碼分析是提升程式碼品質的重要手段。ESLint是一個流行的JavaScript/TypeScript靜態程式碼分析工具。

FROM node:14.0.0
WORKDIR /app
COPY package-lock.json .
COPY package.json .
RUN npm i
COPY . .

內容解密:

  1. FROM node:14.0.0:根據Node.js 14.0.0映像檔建立新的Docker映像檔。
  2. WORKDIR /app:設定工作目錄。
  3. COPY package*.json ./:複製package.jsonpackage-lock.json到工作目錄。
  4. RUN npm i:安裝依賴套件。
  5. COPY . .:複製應用程式原始碼到工作目錄。

設定ESLint

eslintrc.json中設定ESLint規則,啟用Mocha環境。

{
    "env": {
        "node": true,
        "commonjs": true,
        "es6": true,
        "mocha": true
    }
}

內容解密:

  1. "env":定義環境變數。
    • "mocha": true:啟用Mocha環境,避免將Mocha的全域性變數標記為未定義。

執行整合測試與模擬資料函式庫

在進行整合測試時,使用模擬資料函式庫可以提高測試效率和可靠性。Mongo-unit是一個Node.js套件,可以在記憶體中執行MongoDB。

const Expect = require('chai').expect
const MongoUnit = require('mongo-unit')
const DAO = require('../dao')
const TestData = require('./movies.json')

describe('StoreDAO', () => {
    before(() => MongoUnit.start().then(() => {
        process.env.MONGO_URI = MongoUnit.getUrl()
        DAO.init()
    }))
    
    beforeEach(() => MongoUnit.load(TestData))
    afterEach(() => MongoUnit.drop())
    after(() => {
        DAO.close()
        return MongoUnit.stop()
    })
    
    it('should find all movies', () => {
        return DAO.Movie.find()
            .then(movies => {
                Expect(movies.length).to.equal(8)
                Expect(movies[0].title).to.equal('Pulp Fiction (1994)')
            })
    })
})

內容解密:

  1. MongoUnit.start():啟動記憶體中的MongoDB。
  2. MongoUnit.load(TestData):載入測試資料。
  3. DAO.init():初始化DAO層,使用MongoUnit提供的URL。
  4. it('should find all movies', () => { ... }):測試案例,驗證能夠正確檢索所有電影。

Blue Ocean檢視

Jenkins的Blue Ocean檢視提供了更直觀的平行測試執行結果展示。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Jenkins平行測試與程式碼品質提升

package "Docker 架構" {
    actor "開發者" as dev

    package "Docker Engine" {
        component [Docker Daemon] as daemon
        component [Docker CLI] as cli
        component [REST API] as api
    }

    package "容器運行時" {
        component [containerd] as containerd
        component [runc] as runc
    }

    package "儲存" {
        database [Images] as images
        database [Volumes] as volumes
        database [Networks] as networks
    }

    cloud "Registry" as registry
}

dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置

@enduml

圖表翻譯: 此圖示展示了Jenkins Pipeline的執行流程,從簽出程式碼到執行平行測試,最終完成整個流程。

使用 Jenkins 執行自動化測試

在現代軟體開發流程中,自動化測試是確保程式碼品質的重要環節。Jenkins 作為一個強大的持續整合(CI)和持續佈署(CD)工具,可以幫助我們自動化測試流程。本文將介紹如何使用 Jenkins 執行自動化測試,並產生程式碼覆寫率報告。

執行自動化測試

首先,我們需要在 package.json 檔案中定義測試命令。在本例中,我們使用 Mocha 作為測試框架。

"scripts": {
  "start": "node index.js",
  "test": "mocha ./test/*.spec.js",
  "lint": "eslint .",
  "coverage-text": "nyc --reporter=text mocha",
  "coverage-html": "nyc --reporter=html mocha"
}

內容解密:

  • test 命令使用 Mocha 執行 test 資料夾中的測試案例。
  • coverage-textcoverage-html 命令使用 Istanbul(nyc)產生程式碼覆寫率報告。

產生 HTML 程式碼覆寫率報告

為了產生 HTML 程式碼覆寫率報告,我們需要在 Jenkinsfile 中新增一個階段。

stage('Coverage Reports'){
  sh "docker run --rm -v $PWD/coverage:/app/coverage ${imageName}-test npm run coverage-html"
  publishHTML (target: [
    allowMissing: false,
    alwaysLinkToLastBuild: false,
    keepAll: true,
    reportDir: "$PWD/coverage",
    reportFiles: "index.html",
    reportName: "Coverage Report"
  ])
}

內容解密:

  • 使用 Docker 執行測試容器,並掛載本機的 coverage 資料夾到容器的 /app/coverage 資料夾。
  • 執行 npm run coverage-html 命令產生 HTML 程式碼覆寫率報告。
  • 使用 Jenkins 的 HTML Publisher 外掛程式釋出報告。

平行執行測試

為了減少測試的等待時間,我們可以平行執行多個測試階段。

stage('Tests'){
  parallel(
    'Quality Tests': {
      sh "docker run --rm ${imageName}-test npm run lint"
    },
    'Integration Tests': {
      sh "docker run --rm ${imageName}-test npm run test"
    },
    'Coverage Reports': {
      sh "docker run --rm -v $PWD/coverage:/app/coverage ${imageName}-test npm run coverage-html"
      publishHTML (target: [
        allowMissing: false,
        alwaysLinkToLastBuild: false,
        keepAll: true,
        reportDir: "$PWD/coverage",
        reportFiles: "index.html",
        reportName: "Coverage Report"
      ])
    }
  )
}

內容解密:

  • 使用 parallel 指令平行執行多個測試階段。
  • 每個階段執行不同的測試命令。

自動化 UI 測試

對於 Angular 應用程式,我們可以使用 Headless Chrome 執行自動化 UI 測試。首先,我們需要建立一個 Dockerfile.test 檔案。

FROM node:14.0.0
ENV CHROME_BIN=chromium
WORKDIR /app
COPY package-lock.json .
COPY package.json .
RUN npm i && npm i -g @angular/cli
COPY . .

內容解密:

  • 使用 Node.js 14.0.0 作為基礎映像。
  • 安裝 Angular CLI 和相關依賴套件。

接下來,我們需要在 package.json 檔案中定義 UI 測試命令。

"scripts": {
  "start": "ng serve",
  "build": "ng build",
  "test": "ng test --browsers=ChromeHeadlessCI --code-coverage=true",
  "lint": "ng lint",
  "e2e": "ng e2e"
}

內容解密:

  • test 命令使用 Headless Chrome 執行 UI 測試,並產生程式碼覆寫率報告。

最後,我們需要在 Jenkinsfile 中更新測試階段。

def imageName = 'mlabouardy/movies-marketplace'
node('workers'){
  stage('Checkout'){
    checkout scm
  }
  def imageTest = docker.build("${imageName}-test", "-f Dockerfile.test .")
  stage('Pre-integration Tests'){
    parallel(
      'Quality Tests': {
        sh "docker run --rm ${imageName}-test npm run lint"
      }
    )
  }
}

內容解密:

  • 建立測試映像並執行測試階段。

自動化測試與Jenkins整合實務

提升前端自動化測試的效率與品質

在現代化的軟體開發流程中,自動化測試扮演著至關重要的角色。透過Jenkins與相關工具的整合,開發團隊能夠有效提升測試的效率與程式碼的品質。本文將探討如何利用Jenkins實作前端自動化測試,以及如何結合SonarQube進行深入的程式碼分析。

設定TSLint以提升程式碼品質

為了確保程式碼的一致性與可維護性,TSLint是一個不可或缺的工具。若要讓TSLint在程式碼中順利透過(如圖8.26所示),需要更新tslint.json檔案以停用強制規則,或在每個檔案的開頭加入/* tslint:disable */指令,以跳過對這些檔案的檢查。

{
  "rules": {
    // 自定義TSLint規則
  }
}

內容解密:

  • TSLint規則的自定義能夠幫助團隊根據專案需求調整程式碼檢查的標準。
  • 適當地停用某些規則可以避免不必要的錯誤提示,但需謹慎使用以免影響程式碼品質。

使用Jasmine與Karma進行Angular單元測試

對於Angular應用程式的單元測試,我們採用Jasmine與Karma這兩個框架。它們支援BDD(Behavior-Driven Development)實踐,能夠以人類可讀的格式描述測試,使非技術人員也能理解。

import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        AppComponent
      ],
    }).compileComponents();
  }));

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  });

  it('should render title', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('.toolbar span').textContent).toContain('Watchlist');
  });
});

內容解密:

  • 使用TestBed來組態測試模組,並編譯元件。
  • it區塊定義了具體的測試案例,例如檢查元件是否成功建立,或特定文字是否正確渲染。

利用Headless Chrome進行UI測試

在Docker容器中執行單元測試時,由於缺乏圖形環境,直接執行瀏覽器測試會面臨挑戰。Headless Chrome提供了一個無介面瀏覽器環境,非常適合此類別需求。

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    customLaunchers: {
      ChromeHeadlessCI: {
        base: 'Chrome',
        flags: [
          '--headless',
          '--disable-gpu',
          '--no-sandbox',
          '--remote-debugging-port=9222'
        ]
      }
    },
    browsers: ['ChromeHeadless', 'Chrome'],
    singleRun: true,
  });
};

內容解密:

  • customLaunchers定義了自定義的瀏覽器啟動器,組態Headless Chrome的執行引數。
  • --no-sandbox旗標是為了避免在某些環境下因許可權問題導致Headless Chrome無法執行的解決方案。

將SonarQube整合至Jenkins

SonarQube是一個強大的工具,能夠對程式碼進行靜態分析,檢測潛在的錯誤和漏洞。透過與Jenkins的整合,每次程式碼提交都會觸發分析,提供360度的程式碼品質視角。

{
  "variables": {...},
  "builders": [
    {
      "type": "amazon-ebs",
      "profile": "{{user `aws_profile`}}",
      "region": "{{user `region`}}",
      "instance_type": "{{user `instance_type`}}",
      "source_ami": "{{user `source_ami`}}",
      "ssh_username": "ubuntu",
      "ami_name": "sonarqube-8.2.0.32929",
      "ami_description": "SonarQube community edition"
    }
  ],
  "provisioners": [
    {
      "type": "file",
      "source": "sonar.init.d",
      "destination": "/tmp/"
    },
    {
      "type": "shell",
      "script": "./setup.sh",
      "execute_command": "sudo -E -S sh '{{ .Path }}'"
    }
  ]
}

內容解密:

  • 使用Packer建立包含SonarQube的AMI(Amazon Machine Image),簡化佈署流程。
  • provisioners部分定義了檔案複製和指令碼執行的步驟,用於安裝和組態SonarQube。