GitLab CI/CD集成MeterSphere自动化测试

发布于 2022年07月15日

7月15日,MeterSphere一站式开源持续测试平台发布v1.20.10 LTS版本。

本文将分享如何通过GitLab CI/CD集成MeterSphere一站式开源持续测试平台,助力企业的DevOps落地。

一、DevOps与QA的关系

在落地并实践DevOps(开发运营一体化)的过程中,深入人们脑海中的是“Dev+Ops”的组成与融合,它形象地揭示了敏捷化软件工程致力于打破部门墙的努力,并从软件全生命周期的视角来管理并优化端到端的交付流程。DevOps发端于敏捷运动,也是敏捷软件研发的进一步延伸,它是一种实践,也是一种文化。维基百科曾经将DevOps诠释为软件研发、质量保障和技术运营三者的结合。

GitLab CI/CD集成MeterSphere自动化测试

个人认为,这在一定程度上强调了QA(即Quality Assurance,质量保障)在DevOps体系中不可或缺的地位与存在。在DevOps发展的初期,人们曾经疑惑测试在未来软件研发中的地位,导致很多测试人员甚至产生了职业危机感。

但是伴随着DevOps实践的不断深入,QA非但没有消失,反而越来越被重视。测试被分散并融入到了研发与交付过程的各个不同阶段,对测试人员的技能及其对专业技能的掌握有了更高的要求,也要求其更多地从质量保障的角度参与软件交付的过程。

诚然,不同的人对于DevOps也许有着不同的理解和定义,但是一些基本的共识被证明可以助力DevOps的持续价值交付。例如:

■ 质量内建:团队所有成员对质量负责,而不仅仅是测试人员对质量负责。质量保障活动贯穿于软件研发的各个阶段,并通过流程与工具形成自我管理的组织;

■ 自动化:更多地采用自动化和自动化测试,它是DevOps持续交付能运转的基础与驱动,努力朝着测试金字塔的模型迈进;

■ 持续反馈:在每一个阶段、每一个代码分支上都有测试活动的介入,依托于自动化测试,尽早测试、频繁测试、按需测试,将问题尽可能地消灭在萌芽之中。

二、GitLab及其CI/CD

GitLab是主流的研发管理和DevOps平台之一,内置了Git代码管理、持续集成、发布包管理、Issue问题跟踪、研发过程跟踪等从设计到投产的DevOps全流程。

GitLab CI/CD是Gitlab内置的免费CI/CD引擎。作为持续集成的工具载体,它通过Git仓库根目录下的.gitlab-ci.yml进行Pipeline编排,并通过GitLab Runner执行脚本。GitLab CI/CD这种跟代码仓库紧密绑定、开发友好的编排和使用方式,决定了其在DevOps自动化流水线中,更适合使用Shell脚本来实现包括测试在内的自动化任务。

三、MeterSphere一站式开源持续测试平台

MeterSphere作为一款一站式的开源持续测试平台,遵循GPL v3开源许可协议,涵盖测试跟踪、接口测试、UI测试和性能测试等功能,全面兼容JMeter、Selenium等主流开源标准,帮助企业用户在持续开发、持续集成和持续部署的基础上,构建全生命周期的持续测试平台,应对DevOps企业环境落地的挑战。

四、GitLab CI/CD为什么要集成MeterSphere?

■ DevOps的天然要求

在DevOps时代,开发人员在“右移”,运维人员在“左移”,而测试人员既“左移”又“右移”。测试是融入在DevOps交付全过程中的,在代码的开发分支、集成分支、构建分支、发布分支,甚至分支的合并与制品包的部署时,都需要测试介入,尽管这中间涉及的可能是不同类型的测试。

GitLab CI/CD集成MeterSphere自动化测试

图片来源:Dan Ashby

对于上述这些发布前的测试,尤其是开发阶段的测试,基于API接口进行自动化测试实现功能验证,是较为经济高效的方式,也是现在软件从业者们普遍采用的方式。这种自动化测试不是为了发现更多的Bug,而是为了以高效的方式验证功能的正确性。

■ 工具使然

GitLab是强大且优秀的DevOps平台,拥有广泛的使用群体。如前所述,其涵盖的功能涉及研发、安全合规、监控、分析、反馈等多方面。但是GitLab本身并不包含自动化测试的功能,也没有集成特定的自动化工具。而MeterSphere开源持续测试平台本身拥有良好的开源生态、活跃的社区用户、简单易用的产品特性和完善的REST API接口。

同时,得益于gitlab-ci的灵活性,使得GitLab CI/CD与MeterSphere形成很好的优势互补。在MeterSphere中创建并维护自动化测试用例,GitLab CI/CD通过API调用远程触发自动化测试用例。开发人员在检入代码时,可以随时触发开发分支的流水线,执行构建、部署、测试等一系列检查验证,保障代码质量。

五、集成案例展示

本例子主要演示GitLab CI/CD通过gitlab-ci调用MeterSphere中已经维护好的自动化测试计划并返回报告URL,自动化测试计划关联了2个自动化场景用例。被测系统是额外搭建的另外一套独立的MeterSphere环境,MeterSphere eats its own dog food : - )

GitLab CI/CD集成MeterSphere自动化测试

1. MeterSphere自动化用例准备

MeterSphere开源持续测试平台最近上线了MeterSphere专业测试云(www.metersphere.com),本示例采用专业测试云作为自动化测试的用例管理与执行环境。

2. 搭建被测系统

准备一台配置4C8G以上的CentOS 7 x64 Linux虚拟机,磁盘容量可以配置100GB左右,最好能访问互联网。如果不能访问互联网,也可以通过MeterSphere开源社区获取离线安装包。

具体安装过程比较简单,参考MeterSphere官方文档(
https://metersphere.io/docs/quick_start/quick_start/),一键部署即可。

3. 注册专业测试云

访问MeterSphere专业测试云主页(www.metersphere.com)进行注册。

注册完成后就进入租户管理页面,点击右侧绿色的“进入工作台”按钮,进入测试的工作页面(这点不好找,首次使用很容易迷路 )。

GitLab CI/CD集成MeterSphere自动化测试

4. 准备自动化用例

进入MeterSphere专业测试云工作台后,依次创建项目、接口定义、单接口用例和场景用例。

① 导入接口定义

② 创建项目环境

在环境中设置accessKey、secretKey等通用环境变量;

GitLab CI/CD集成MeterSphere自动化测试

设置全局前置脚本,如被测系统鉴权相关的Signature生产方法;

GitLab CI/CD集成MeterSphere自动化测试

③ 创建场景1

通过接口/project/listAll获取项目列表;

GitLab CI/CD集成MeterSphere自动化测试

④ 创建场景2

循环创建用户并验证,再通过循环清理数据,将所创建的用户删除并验证;

GitLab CI/CD集成MeterSphere自动化测试

5. 创建测试计划

创建测试计划Sprint-1,并关联所创建的场景1和场景2;

GitLab CI/CD集成MeterSphere自动化测试

6. GitLab CI/CD配置

① 注册GitLab账号

在极狐https://jihulab.com创建项目,并检入代码;

② 提交脚本至Git仓库

将脚本triggerTestPlan.sh检入到git仓库;

脚本用法:triggerTestPlan.sh $accessKey $secretKey $projectName $envName $testPlanName $host

其中:

■ accessKey与secretKey在登录MeterSphere后,事先生成;

■ projectName为自动化测试用例、测试计划所在的MeterSphere项目名称;

■ envName为测试计划所执行的运行环境,在MeterSphere项目设置中事先配置好;

■ testPlanName为将要执行的MeterSphere测试计划名称,它创建在“测试跟踪”模块下;

■ Host为MeterSphere服务器域名或IP地址,如”cloud.metersphere.com“(不带“http://” 或 “https://” 前缀 )。

以下为triggerTestPlan.sh脚本:

#!/bin/bash
accessKey=${1}
secretKey=${2}
projectName=${3}
envName=${4}
testPlanName=${5}
HOST=${6}
 
projectId="projectId"
envId="environmentId"
testPlanId="testPlanId"
userId="userId"
reportURL="reportURL"
testReportId="retrieveReportId"
 
keySpec=$(echo -n "${secretKey}" | od -A n -t x1 | tr -d ' ')
iv=$(echo -n "${accessKey}" | od -A n -t x1 | tr -d ' ')
 
currentTimeMillis=$(date +%s000)
seed=${accessKey}\|$currentTimeMillis
signature=$(printf %s "${seed}" | openssl enc -e -aes-128-cbc -base64 -K ${keySpec} -iv ${iv})
 
# get Project ID through project name
getProjectId()
{
    RESULT=$(curl -k -s -H "accesskey: ${accessKey}" -H "signature: ${signature}" -H "Content-Type: application/json" https://${HOST}/project/listAll)
    projectId=$(printf '%s\n' "${RESULT}" | jq '.data[] | select(.name == "'"${projectName}"'")' |jq .id)
}
 
getEnvId()
{
    proj_id=`echo $1|awk -F "\"" '{print $2}'`
    RESULT=$(curl -k -s -H "accesskey: ${accessKey}" -H "signature: ${signature}" -H "Content-Type: application/json" https://${HOST}/api/environment/list/${proj_id})
    envId=$(printf '%s\n' "${RESULT}" | jq '.data[] | select(.name == "'"${envName}"'")' |jq .id)
}
 
# get Test Plan ID through plan name
getTestPlanId()
{
    proj_id=$1
    plan_name=$2
    BODY='{"projectId": '$proj_id'}'
    RESULT=$(curl -k -s -X POST -H "accesskey: ${accessKey}" -H "signature: ${signature}" -H "Content-Type: application/json" https://${HOST}/test/plan/list/1/100 -d "${BODY}")
    testPlanId=$(printf '%s\n' "${RESULT}" | jq '.data.listObject[] | select(.name == "'"${plan_name}"'")' |jq .id)
}
 
# get current user ID
getUserId()
{
    RESULT=$(curl -k -s -H "accesskey: ${accessKey}" -H "signature: ${signature}" -H "Content-Type: application/json" https://${HOST}/currentUser)
    userId=$(printf '%s\n' "${RESULT}" | jq '.data.id')
}
 
#Execute the Test Plan which associated the api test scenarios
runTestPlan()
{
    proj_id=$1
    plan_id=$2
    user_id=$3
    env_id=$4
    BODY='{"mode": "serial", "testPlanId": '${plan_id}',"envMap":{'${proj_id}':'${env_id}'}, "tirggerMode": "API","userId": '${user_id}' }'
    #In addtion to the above JSON,the request body could be composed of more parameters
 
    RESULT=$(curl -k -s -X POST -H "accessKey: ${accessKey}" -H "signature: ${signature}" -H "Content-Type: application/json" https://${HOST}/test/plan/run -d "${BODY}")
    testReportId=$(echo $RESULT | jq -r '.data')
}
 
getReportSharedId()
{
    report_id=$1
    BODY='{"customData":"'${report_id}'","shareType":"PLAN_DB_REPORT","lang":null}'
    RESULT=$(curl -k -s -X POST -H "accessKey: ${accessKey}" -H "signature: ${signature}" -H 'Content-Type: application/json' https://${HOST}/share/info/generateShareInfoWithExpired -d "${BODY}")
    reportSharedId=$(echo $RESULT | jq -r '.data.shareUrl')
}
 
getProjectId
#echo "PROJECT_ID: ${projectId}"
 
getEnvId $projectId
#echo "Env_ID: ${envId}"
 
getTestPlanId $projectId ${testPlanName}
#echo "TestPlanId: ${testPlanId}"
 
getUserId
 
runTestPlan $projectId $testPlanId $userId $envId
getReportSharedId $testReportId
 
REPORTURL="https://${HOST}/sharePlanReport${reportSharedId}"
echo "Please visit URL: ${REPORTURL} for test report"

③ 配置流水线

GitLab中配置CI/CD流水线,通过脚本triggerTestPlan.sh触发MeterSphere自动化测试计划;

GitLab CI/CD集成MeterSphere自动化测试
image: alpine:latest
 
stages:
  - build
  - deploy
  - api test
 
build-job:
  stage: build
  script:
    - echo "Thid is a build job"
 
deploy-job:
  stage: deploy
  script:
    - echo "Thid is a deploy job"
 
test-job:       # This job calls MeterSphere API to run API test.
  stage: api test
  before_script:
    - sh env_prepare.sh #必要的测试环境准备
 
  script:
    - sh triggerTestPlan.sh $accessKey $secretKey $projectName $envName $testPlanName $host

④ 配置变量

CI/CD脚本中的变量,可以事先设置相应的变量值,将执行相关的值参数化,实现脚本的重用;

GitLab CI/CD集成MeterSphere自动化测试

⑤ 执行流水线

在执行流水线过程中,可以打印执行过程的日志,并在执行结束后,将MeterSphere的测试报告URL返回给GitLab,开发或测试人员可以在GitLab界面直接打开测试报告;

GitLab CI/CD集成MeterSphere自动化测试

通过点击执行结果中的测试报告URL,可以跳转至MeterSphere报告页面。

GitLab CI/CD集成MeterSphere自动化测试

六、总结与展望

作为在研发测试领域被大家认可并采纳的优秀工具平台,GitLab和MeterSphere都采用了开源的模式,通过社区与一线使用者保持密切的互动。

GitLab CI/CD与MeterSphere的集成为DevOps的落地和使用提供了新的选择。在未来,我们希望将这种集成进一步地固化成GitLab CI/CD的模版,以开箱即得的方式助力企业的DevOps落地。