其他博文连接
- Ubuntu Server 16.04LTS 搭建GitLab服务器
- ubuntu server 16.04 使用docker搭建jenkins和sonarqube
- Gitlab配置Gitlab-Runner实现简单的CI/CD
- Gitlab CI集成sonarqube实现静态代码检查
- gitlab CI中单元测试与集成测试的研究与实践
- GitLab持续集成持续部署(CI&CD)
文章目录
gitlab CI中单元测试与集成测试的研究与实践
配置说明
Gitlab
- 系统:Ubuntu 16.04 Server
- 内存:4G
- IP:192.168.23.100
- Dokcer Version : 18.09.0
Gitlab Runner
- 系统:Ubuntu 16.04 Server
- 内存:4G
- IP:192.168.23.102
- Dokcer Version : 18.09.0
Sonarqube
- 系统:Ubuntu 16.04 Server
- 内存:4G
- IP:192.168.23.101
- Dokcer Version : 18.09.0
CI流程图
上图是我理解的整个流程:
- 开发人员提交代码
- Gitlab出发CI
- Gitlab-Runner进行开始流水线
- 进行项目构建,
gradle bootjar
打出一个可执行的Spring Boot的Jar包 - 进行sonar静态代码审查,如果BUG数超过一定限制则CI失败,开发者需要修改相应的BUG后重新提交
- 进行单元测试
gradle test
- 进行自动化集成测试,我的理解是可以模拟第三方应用对接口进行测试。不关心接口内部实现及调用,只关心输入输出
- 当单元测试和集成测试都成功后,进行部署
- 结束
以上只是个人理解,如果有不妥之处请提出来。本篇暂时不讲持续部署(CD)
需要解决的问题
实际开发中,都是多人进行开发。提交的时候也可能是多人同时提交,这时会触发多个CI。因为每个开发者开发的功能点不同,所以需要在不同的环境下进行CI,这样就要求不同的CI环境能够隔离。通过Gitlab-Runner的Docker执行器能够很好的做到这点,但是CI的数据库怎么指定?总不能每个人都改配置文件,修改成自己的数据库吧。所以这时需要实现每个分支的CI能够对应不同的数据库,这点可以通过启动jar时指定环境变量,比如每次提交的Commit号等,通过使用这个环境变量作为数据库名就可以实现这点(当然也可以使用容器内的数据库,这样也可以隔离,但是本人没有实现所以不做介绍了)。
代码编写
项目代码
实现一个简单的新增学生信息来作为示例
代码在最后链接中
单元测试
这里就随便写个示例,单元测试的代码项目中都有
Service单元测试
在最后的代码链接中
Controller单元测试
可参考:博客园的:SpringBoot系列: 单元测试
集成测试
这里我的思路是新建一个仓库,这个仓库的代码模拟服务调用者。数据的话可在integration-test通过gradle命令装载集成测试数据(实现可以在test中实现代码,通过gradle或其他方式执行数据装载)。在gitlab-ci的integration-test阶段,通过git把服务调用者clone下来,通过gradle打成可执行jar,然后运行。具体实现掠过
提供专门用于测试的配置文件application-test.yml
server:
port: 8880
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
# ${CI_COMMIT_SHA}指的是每次提交的commit号,我们每次使用这个作为数据库名,将不同用户的ci隔开,数据库在ci的第一阶段创建
url: jdbc:mysql://192.168.23.102:3306/${CI_COMMIT_SHA}?useUnicode=true&characterEncoding=utf-8&useSSL=false
username : root
password : root123
driverClassName : com.mysql.jdbc.Driver
jpa:
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
ddl-auto: update
show-sql: true
.gitlab-ci.yml编写
gitlab-runner server 安装mysql-client
这里提供一个mysql的镜像,能够通过shell创建数据库: virtuex/mysql_env:mysql-5.7-openjdk-7,dockerhub地址
.gitlab-ci.yml
下面是.gitlab-ci.yml的配饰文件,每部的作用在注释中体现
# 指定基础镜像
image: virtuex/base_java_env:gradle-4.10.2-openjdk-7-openjdk-8-docker-18
# 定义stage
stages:
- build_db
- build
- unit-test
- integration-test
# 这个job主要是为了创建数据库,官方提供的service因为我没有使用成功,所以这里采用alphin镜像,并安装mysql客户端,以执行mysql命令
gitab_mysql_service:
stage: build_db
image: alpine:latest
script:
- apk --no-cache add mysql-client
- sh src/test/bin/create_database.sh
# 因为基础镜像默认用的1.7,这里切换成1.8
before_script:
- echo "Reset JDK..."
- export JAVA_HOME=$JAVA8_HOME
- export PATH=${JAVA_HOME}/bin:$PATH
# 这个job主要是为了生成build/classes/test这个文件夹,否则下个阶段执行sonar命令会失败
build_job:
stage: build
script:
- echo "Release build..."
- gradle testClasses
# 单元测试、代码静态检查、单元测试覆盖率检查等
test_job:
stage: unit-test
script:
- echo "Unit Tests run..."
- gradle test
- gradle jacocoTestReport
- gradle testClasses
- gradle -b sonarqube.gradle sonarqube -Dsonar.analysis.mode="${MODE}" -Dsonar.gitlab.project_id=$CI_PROJECT_PATH -Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
# 集成测试阶段,运行springboot程序,并执行自定义的集成测试流程
integration_test_job:
stage: integration-test
variables:
GRADLE_MODE: "check"
MODE: "preview"
script:
# 打成可直接运行的Springboot的jar
- gradle bootJar
# 切换成1.8的jdk
- export JAVA_HOME=$JAVA8_HOME
- export PATH=${JAVA_HOME}/bin:$PATH
# 指定以用于测试阶段的配置运行,这里使用nohup,否则后打死在这个命令而不往后进行
- nohup java -jar -Dspring.profiles.active=test build/libs/ci_test-1.0-SNAPSHOT.jar &
#####################################################################
# 下面是进行集成测试阶段,具体的流程可自己定义,我这里是我自己的一个思路
#####################################################################
- echo "Integration testing run..."
- echo "git clone xxxx.git"
# 可以结合application插件,打成可执行jar
- echo "gradle distZip"
# zipb包的目录大概是:# - xxx.zip
# -/bin
# -/启动脚本
# -/lib
# -/依赖的jar
- echo "unzio xxx.zip"
- echo "sh /xx/bin/start.sh"
- echo "start integeration testing!"
create_database.sh
通过shel连接到另一台主机并创建数据库
#!/bin/sh
#数据库信息地址,这里的数据库是一个固定的数据库
HOSTNAME="192.168.23.102"
PORT="3306"
USERNAME="root"
PASSWORD="root123"
#创建数据库
#其中CI_COMMIT_SHA是Gitalb Ci提供的变量,保存每次提交的commit号,这里使用commit号作为数据库名以保证每次提交都是不同的
create_db_sql="create database IF NOT EXISTS $CI_COMMIT_SHA"
#远程创建命令
mysql -h${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "${create_db_sql}"
运行结果
首先放一张各个流程的整体运行结果
gitab_mysql_service任务
这一步是为了创建数据库,其中描述了第一阶段的构建流程,我们本次提交的commit号是c96641f6
开头的,可以看到数据库中也成功创建了该数据库,如下图:
test_job任务
这一步为了执行单元测试等
test_job任务
到这里初步完成了设计思路,具体细节还需完善。
项目代码
测试用虚拟机下载地址
因为虚拟机比较大,已上传到百度网盘:
链接:https://pan.baidu.com/s/14vk8gLpblx77B8oB1Kn5lA
提取码:hs3m
- 192.168.23.100 : gitlab的地址,可直接访问:http://192.168.23.100
- 192.168.23.101 :sonarqube地址,可直接访问: http://192.168.23.101:9000 ,应用在docker中,如果不能使用请自行开启
- 192.168.23.102 : gitlab-runner地址,已安装的是docker执行器,可重新注册替换成其他的
其中192.168.23.102是runner的所在地址,如果docker0网络使用过程中出现错误可参考另一篇博文物理机没法访问虚拟机docker中的应用