第1章 CI/CD基础与集成测试概述

说到CI/CD和集成测试,我做了快十年 DevOps,踩过的坑比吃过的盐还多。你想想看,一个项目从代码提交到上线,中间要经过多少道坎?如果连集成测试这关都过不了,后面全是瞎忙活。

说白了,CI/CD 就是让机器帮你干活——自动拉代码、自动构建、自动跑测试。集成测试呢,就是验证你的新代码跟现有系统能不能好好过日子。我见过太多人把单元测试跑绿了就认为万事大吉,结果一合并就炸。

三大主流工具,到底选哪个?

目前在业界主流的 CI/CD 工具就三把:GitLab CI、Jenkins、GitHub Actions。我每个都用烂了,给你说说真实感受。

对比维度 GitLab CI Jenkins GitHub Actions
配置方式 .gitlab-ci.yml 声明式,简洁 GUI 配置 + Jenkinsfile (Groovy) .github/workflows/*.yml 声明式
部署模式 SaaS 或自托管 Runner 自托管为主,功能全面 SaaS 为主,也支持自托管
适用场景 GitLab 全家桶用户;中小团队 复杂流水线;大型企业;重度自定义 GitHub 生态;开源项目;快速启动
核心优势 内置 CI/CD,零运维成本 插件生态强大,几乎无所不能 与代码仓库深度绑定,社区市场活跃
避坑点 高级功能收费, Runner 资源有限 维护成本高,新手容易配出“屎山” 免费额度有限,调试日志只有 7 天

别不信,选错工具真的会死人。 我有个朋友的公司,老板听销售忽悠上了 Jenkins,结果光搭集群就折腾了两周,之后每次更新插件都要停服务。他私下跟我说:早知道用 GitLab CI,代码一推就完事了。

GitLab CI:小团队的真香之选

如果你公司用 GitLab 管理代码,直接用它的 CI 是最省心的。我前两年带一个 20 人的团队,从 Jenkins 迁移到 GitLab CI,流水线配置量直接砍掉 60%。

配置很简单,一个 .gitlab-ci.yml 文件搞定。比如最基础的流水线:

stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  script:
    - mvn clean package

test-job:
  stage: test
  script:
    - mvn test

嗯,就这么几行,自动触发构建和测试。集成测试阶段通常放在 test 阶段之后,你可以加个 stage 专门跑:

integration-test-job:
  stage: integration-test
  script:
    - docker-compose up -d
    - mvn verify
    - docker-compose down

我习惯把集成测试环境用 Docker Compose 管理,跑完自动销毁,不占地方。

小技巧: 在 .gitlab-ci.yml 里用 only 和 except 控制触发条件,避免每次 commit 都跑一遍完整集成测试。

Jenkins:大而全,但请善待你的运维

Jenkins 出道早,插件多到能铺满一个足球场。但说实话,现在新项目我基本不推荐它了——除非你们公司有专职的 CI/CD 运维团队。

Jenkins 的流水线有两种写法:声明式和脚本式。我更喜欢脚本式的 Jenkinsfile,灵活性高:

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
        stage('Integration Test') {
            steps {
                sh 'docker-compose up -d'
                sh 'mvn verify'
                sh 'docker-compose down'
            }
        }
        stage('Deploy') {
            steps {
                sh 'scp target/*.war deploy@server:/opt/tomcat/webapps/'
            }
        }
    }
    post {
        always {
            junit '**/target/surefire-reports/*.xml'
        }
    }
}

我曾经遇到过 Jenkins 的 Master 节点内存泄漏,排查了整整两天才发现是某个插件版本不兼容。你想想看,如果 Jenkins 崩了,所有构建都停了,那酸爽。

注意: Jenkins 的插件安全漏洞层出不穷,记得定期更新并备份 JENKINS_HOME。我用过一个叫 "Build Timeout" 的插件后来被爆严重漏洞,被迫紧急升级。

GitHub Actions:开源项目的最佳拍档

如果你的代码在 GitHub 上,又不想自己搭服务器,GitHub Actions 是最省事的。免费额度对于个人项目和中小公司完全够了,每小时 2000 分钟,还支持 Linux/macOS/Windows。

配置文件和 GitLab CI 很像,也是 YAML 格式。比如这样一个工作流:

name: CI Pipeline
on:
  push:
    branches: [ main ]
jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
      - name: Build and Integration Test
        run: |
          docker-compose up -d
          mvn verify
          docker-compose down

它最方便的是可以直接复用社区写好的 Action,比如数据库、缓存服务,一行 uses 就搞定。我帮一个客户做项目时,用 GitHub Actions 跑集成测试,从零到上线只花了一个下午。

集成测试到底该在哪跑?

很多新手把集成测试和单元测试放在同一个阶段。我明确告诉你:不要这么做。单元测试应该跑得飞快(秒级),集成测试通常需要启动外部服务(分钟级)。混在一起会让反馈变得很慢。

正确做法是分阶段——单元测试先跑,失败了就立刻终止,然后才跑集成测试。你可以用流水线中的 when: on_success 控制。这样开发人员提交代码后,5 秒内收到单元测试结果,如果过了再等几分钟跑集成测试,心理压力小很多。

避坑指南: 我曾经把集成测试的数据库配置写死了,导致每次 CI 都要连生产环境的测试库,差点把线上数据冲掉。后来我要求所有集成测试都必须在独立容器里跑,用完就删,绝不混用环境。

CI/CD 与集成测试工具对比概览 CI/CD 与集成测试 选型与核心逻辑 GitLab CI 内置CI · YAML配置 Jenkins 插件丰富 · 自托管 GitHub Actions 市场Action · 集成仓库 集成测试 阶段分离 · 容器化 选型建议:GitLab CI 适合 GitLab 生态用户; Jenkins 适合需要高度自定义的大型团队; GitHub Actions 是开源项目和中小团队的捷径。

选型怎么做?我给你的真心建议

直接给结论吧,方便你抄作业:

  • 如果你用 GitLab 管理代码,且团队小于 50 人 —— 无脑选 GitLab CI。不需要运维,Pipeline 配置简单。
  • 如果你们是大型企业,有专职 DevOps,需要对接一堆老旧系统 —— 选 Jenkins。但要做好心理准备,维护 Jenkins 就像养了个祖宗,每周都得伺候。
  • 如果你是独立开发者、开源项目,或者公司代码全在 GitHub —— 选 GitHub Actions。免费额度足够用,社区 Action 让你少写很多代码。
  • 集成测试环境一定要容器化 —— 不管用哪个工具,都把依赖的服务(数据库、消息队列、缓存)用 Docker 跑起来。我见过太多人因为环境不一致,本地跑绿了,CI 上就红。

最后提醒一句: 别为了炫技而选工具。我见过有团队把 Jenkins Pipeline 写得无比复杂,结果出了问题没人敢动。简单、可维护,比什么都重要。