实战执行流程

image-20210308151155757

工程准备

SpringBoot系统

接口自动化测试工程

SpringBoot系统持续交付

  1. git clone SpringBoot项目,使用Idea打开该项目,查看工程的目录

    image-20210308152810994

  2. 下载jacoco相关包到部署服务器上,下载地址:https://www.jacoco.org/jacoco/

    1
    2
    3
    4
    5
    6
    [root@lvjing ~]# cd /usr/local/
    [root@lvjing local]# ls
    aegis bin etc games include jacoco jdk1.8 lib lib64 libexec maven sbin share sonar-scanner src tomcat9
    [root@lvjing local]# cd jacoco/
    [root@lvjing jacoco]# ls
    coverage doc index.html lib test
  1. Dockerfile镜像打包的内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    FROM java:8
    MAINTAINER jinglv
    ENV TZ "Asia/Shanghai"
    ENV LANG C.UTF-8
    VOLUME /tmp
    ADD spring-boot-restful-api-0.0.1-SNAPSHOT.jar restful.jar
    ENTRYPOINT ["java","-javaagent:/usr/local/jacocoagent.jar=includes=*,output=tcpserver,append=true,address=*,port=6301,destfile=/usr/local/jacoco.exec","-Djava.security.egd=file:/dev/./urandom","-jar","restful.jar"]
    EXPOSE 8988

    项目需要统计测试覆盖率,则在项目启动的时候需要使用jacocoagent.jar,因此我们在启动Docker实例时需要引入jacocoagent.jar

  2. Jenkinsfile pipeline脚本如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    pipeline {
    agent {
    label 'master'
    }

    environment {
    cred_id = 'b4d58207-0fa3-43f5-bf1d-c635025a7684124'
    docker_image_name = 'restful_api'
    docker_container_name = 'irestful_api'
    }

    parameters {
    string(name: 'branch', defaultValue: 'main', description: 'Git branch')
    string(name: 'pomPath', defaultValue: 'pom.xml', description: 'pom.xml的相对路径')
    string(name: 'lineCoverage', defaultValue: '20', description: '单元测试代码覆盖率要求(%),小于此值pipeline将会失败!')
    }

    stages {
    stage('检出代码') {
    steps {
    git credentialsId: cred_id, url: 'https://gitee.com/jeanlv/spring-boot-restful-api.git', branch: "$params.branch"
    }
    }

    stage('Maven编译打包并单元测试') {
    steps {
    // 注入jacoco插件配置,clean test执行单元测试代码. All tests should pass.
    sh '''
    . ~/.bash_profile

    cd ${WORKSPACE}
    mvn org.jacoco:jacoco-maven-plugin:prepare-agent -f ${pomPath} clean install -Dautoconfig.skip=true -Dmaven.test.skip=false
    '''
    }
    }

    stage('SonarQube代码质量扫描') {
    steps {
    sh '''
    . ~/.bash_profile

    cd ${WORKSPACE}
    mvn sonar:sonar -Dsonar.projectKey=spring-boot-restful-api -Dsonar.host.url=http://60.205.228.49:9000/ -Dsonar.login=053ed1077e82a2bb36eebf619d24d75b8c5738b9 -Dsonar.branch.name=${branch}
    '''
    junit '**/target/surefire-reports/*.xml'
    // 配置单元测试覆盖率要求,未达到要求pipeline将会fail,code coverage.LineCoverage>20%.
    jacoco changeBuildStatus: true, maximumLineCoverage: "$params.lineCoverage"
    }
    }

    stage('停止 / 删除 现有Docker Container/Image ') {
    steps {
    script {
    try {
    sh 'docker stop $docker_container_name'
    } catch (exc) {
    echo 'The container $docker_container_name does not exist'
    }

    try {
    sh 'docker rm $docker_container_name'
    } catch (exc) {
    echo 'The container $docker_container_name does not exist'
    }

    try {
    sh 'docker rmi $docker_image_name'
    } catch (exc) {
    echo 'The docker image $docker_image_name does not exist'
    }
    }
    }
    }

    stage('生成新的Docker Image') {
    steps {
    sh '''
    cd ${WORKSPACE}/docker
    rm -f spring-boot-restful-api-0.0.1-SNAPSHOT.jar
    cp ${WORKSPACE}/target/spring-boot-restful-api-0.0.1-SNAPSHOT.jar .
    docker build -t $docker_image_name .
    '''
    }
    }

    stage('启动新Docker实例') {
    steps {
    sh '''
    docker run -d --name $docker_container_name -p 8988:8988 -p 6301:6301 -v /usr/local/jacoco/lib/jacocoagent.jar:/usr/local/jacocoagent.jar $docker_image_name
    '''
    }
    }
    }

    post {
    always {
    script {
    println "Do some actions when always need."
    }
    }
    failure {
    script {
    println "Do some actions when build failed."
    }
    }
    success {
    script {
    println "Here we kickoff run job SpringBoot-Restful-Api-Test-Pipeline"
    job_run_result = build job: 'SpringBoot-Restful-Api-Test-Pipeline', propagate: false, wait: true
    println job_run_result.getResult()
    }
    }
    }
    }

    查看pipeline脚本的节点,了解到持续交付执行的节点步骤,并在执行成功后触发’SpringBoot-Restful-Api-Test-Pipeline’Job,当中只要有一个节点执行失败,则Job会输出失败,在此我们可以配置邮件、企业微信、钉钉通知等。

注意:该SpringBoot工程为演示方便,没有使用数据库存储数据,如果涉及数据库,则需要添加数据库配置,具体介绍详看文章Jenkins Docker部署持续交付实战

接口自动化测试持续集成

  1. git clone接口自动化测试工程,使用Idea打开该项目,查看工程的目录

    image-20210308153115182

  2. 下载sonar-scanner到Jenkins部署服务器上,下载地址:https://docs.sonarqube.org/latest/analysis/scan/sonarscanner/

    1
    2
    3
    4
    5
    6
    [root@lvjing ~]# cd /usr/local/
    [root@lvjing local]# ls
    aegis bin etc games include jacoco jdk1.8 lib lib64 libexec maven sbin share sonar-scanner src tomcat9
    [root@lvjing local]# cd sonar-scanner/
    [root@lvjing sonar-scanner]# ls
    bin conf jre lib

    下载完成后,需要在conf/sonar-scanner.properties文件中,配置SonarQube平台的地址及登录用户名和密码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #Configure here general information about the environment, such as SonarQube server connection details for example
    #No information about specific project should appear here

    #----- Default SonarQube server
    sonar.host.url=http://60.205.228.49:9000/

    #----- Default source code encoding
    #sonar.sourceEncoding=UTF-8

    sonar.login=admin
    sonar.password=admin1234567
  1. Jenkinsfile pipeline脚本如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    pipeline {
    agent {
    label 'master'
    }

    environment {
    cred_id = 'b4d58207-0fa3-43f5-bf1d-c635025a7684'
    }

    parameters {
    string(name: 'branch', defaultValue: 'master', description: 'Git branch')
    }

    stages {
    stage('检出代码') {
    steps {
    git credentialsId: cred_id, url: 'https://gitee.com/jeanlv/api-object-auto.git', branch: "$params.branch"
    }
    }

    stage('Maven执行测试') {
    steps {
    sh '''
    . ~/.bash_profile

    cd ${WORKSPACE}
    mvn clean install
    '''
    }
    }

    stage('JaCOCO Dump数据') {
    steps {
    sh '''
    java -jar /usr/local/jacoco/lib/jacococli.jar dump --address 127.0.0.1 --port 6301 --destfile /root/jacoco-project/jacoco_docker.exec
    '''
    }
    }

    stage('JaCOCO测试报告生成') {
    steps {
    sh '''
    cd ..
    cd SpringBoot-Restful-Api-Docker-Pipeline
    pwd
    java -jar /usr/local/jacoco/lib/jacococli.jar report /root/jacoco-project/jacoco_docker.exec --classfiles=./target/classes --sourcefiles=./src/main/java --html /root/jacoco-project/report/ --xml /root/jacoco-project/report/jacoco.xml
    '''
    }
    }

    stage('SonarQube分析') {
    steps {
    sh '''
    cd ..
    cd SpringBoot-Restful-Api-Docker-Pipeline
    pwd
    /usr/local/sonar-scanner/bin/sonar-scanner -Dsonar.coverage.jacoco.xmlReportPaths=/root/jacoco-project/report/jacoco.xml -Dsonar.projectKey=spring-boot-restful-api-test -Dsonar.projectName=spring-boot-restful-api-test -Dsonar.language=java -Dsonar.sourceEncoding=UTF-8 -Dsonar.core.codeCoveragePlugin=jacoco -Dsonar.sources=./src/main/java -Dsonar.java.binaries=./target
    '''
    }
    }
    }

    post {
    always {
    script {
    println "Do some actions when always need."
    allure includeProperties: false, jdk: '', results: [[path: 'target/allure-results']]
    }
    }
    failure {
    script {
    println "Do some actions when build failed."
    }
    }
    success {
    script {
    println "Do some actions when build success."
    }
    }
    }
    }

    查看pipeline脚本的节点,了解到持续集成执行的节点步骤,在脚本执行完成后,输出Allure接口测试报告

Jenkins创建Job并执行

需要创建两个Job,一个是SpringBoot系统持续交付和接口自动化测试持续集成,两个Job均为Jenkins流水线,具体配置详见Jenkins介绍,本篇不在具体介绍

image-20210308164930502

SpringBoot-Restful-Api-Docker-Pipeline在执行成功后,会自动触发SpringBoot-Restful-Api-Test-Pipeline Job,下面我们查看两个Job具体执行的流水线

  • SpringBoot-Restful-Api-Docker-Pipeline的流水线流程

    image-20210308165120471

  • SpringBoot-Restful-Api-Test-Pipeline的流水线流程

    image-20210308165234070

SonarQube平台查看结果

我们看到上面的Jenkins Job都已执行成功,结果也均已上传到SonarQube平台上,这是我们可以到SonarQube平台查看结果

image-20210308165700643

我们明确的看到,单元测试和接口测试完成后,Jacoco得出的结果,略有不同。

其实我们看到的结果,差的不是很多,为什么又要做单元测试还要做接口测试呢?我们可以从以下几方面开看:

  1. 角色不同
    • 单元测试 – 开发工程师
    • 接口测试 – 测试工程师
  2. 测试重点不同
    • 单元测试 – 系统内部逻辑
    • 接口测试 – 接口的输入和输出
  3. 单元测试和接口测试的关系
    • 接口测试是对单元测试的一个补充,在接口测试阶段我们可以考虑到业务需求相关数据,对数据的可行性、容错性都可以在该阶段进行充分的测试