新增接口自动化测试自定义步骤

Summary
  • 新增环境相关的自定义步骤,以新增robotframework接口自动化测试为例子

新增接口自动化测试自定义步骤

  • 以新增robotframework接口自动化测试为例子,让DORY支持在执行应用发布后进行接口自动化测试
  • 所谓环境无关是指不依赖于应用的发布环境,例如代码扫描,不同发布环境代码扫描的参数没有区别
  • 所谓环境相关是指依赖于应用的发布环境,例如接口自动化测试,不同发布环境接口自动化测试的测试用例参数会有所不同

任务演示视频

  • 演示如何让DORY支持在应用发布后执行接口自动化测试

制作robotframework接口自动化测试镜像

DORY自定义步骤的输入参数与输出参数:

  • 输入参数文件: 输入参数文件由DORY自动创建。DORY执行自定义步骤过程中会自动把运行以及步骤的执行参数(内置参数)以及用户输入的参数自动保存到步骤执行容器的输入参数文件中,输入参数文件默认保存在/tmp/dory-param-input.json或者/tmp/dory-param-input.yaml文件中(注意,输入参数文件路径可以配置,请根据实际配置进行相关设置)
    • 输入参数文件支持保存成json格式或者yaml格式,步骤执行容器中的代码可以读取输入参数文件作为输入参数,执行相关的步骤脚本
  • 输出参数文件: 输出参数文件由步骤执行容器在步骤执行过程中的步骤脚本创建。DORY执行自定义步骤结束的时候,会读取步骤执行容器中的输出参数文件输出参数文件默认保存在/tmp/dory-param-output.json或者/tmp/dory-param-output.yaml文件中(注意,输出参数文件路径可以配置,请根据实际配置进行相关设置)
    • 输出参数文件支持保存成json格式或者yaml格式,DORY在步骤执行结束后会读取输出参数文件,用于控制步骤执行结果、输出文件以及需要保存到步骤执行记录中的所有参数
    • 输出参数文件doryStepFail参数: 用于控制步骤执行结果是否失败,假如设置为true,即使步骤执行过程没有错误,步骤也会被标记为失败
    • 输出参数文件doryOutputFiles参数: 用于控制步骤执行结果是否有文件需要输出,例如自动化测试的测试报告,如果需要保存出来,那么需要把测试报告的文件路径设置到doryOutputFiles参数中
    • 输出参数文件的其他参数: 将会保存到步骤执行记录的输出参数中,用于后续执行结果检索用途
  • 制作robotframework镜像,DORY使用robotframework镜像进行接口自动化测试
1
2
# 拉取robotframework镜像
docker pull ppodgorsek/robot-framework:latest
  • robotframework镜像包含python3的运行环境,需要编写python3步骤执行脚本:

    • run_api_test.py脚本,读取DORY的输入参数文件,根据测试文件目录和环境信息,在目录下搜索所有接口自动化测试用例,并执行接口自动化测试用例,最后根据执行结果设置步骤的执行结果以及输出测试报告
      1. 读取DORY的输入参数文件/tmp/dory-param-input.json,格式例如:
      1
      2
      3
      4
      5
      6
      
      {
        "projectName": "test-project1",
        "moduleName": "tp1-gin-demo",
        "envName": "test",
        "path": "Tests"
      }
      
      1. 查找目录下所有*.robot测试用例,并执行测试用例(支持不同目录多个测试用例)
      2. 判断测试用例状态是否正常,如果不正常,设置输出参数文件的doryStepFail参数为true,把本步骤状态设置为FAIL
      3. 输出测试报告到/tmp/dory-file-output目录,并设置doryOutputFiles参数为对应的接口自动化测试结果
  • run_api_test.py脚本文件:

 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
# run_api_test.py
import json
import os
import glob
from pathlib import Path
output_dir = "/tmp/dory-file-output"
results = []
doryStepFail = False
doryOutputFiles = []
for name in glob.glob("./**/*.robot", recursive = True):
  path = str(Path(name).parent)
  file = Path(name).name
  log_file = path + "/" + file.replace(".robot", "-log.html")
  output_file = path + "/" + file.replace(".robot", "-output.xml")
  report_file = path + "/" + file.replace(".robot", "-report.html")
  prefix = "./"
  if name.startswith("./"):
    name = name[len(prefix):]
  if log_file.startswith("./"):
    log_file = log_file[len(prefix):]
  if output_file.startswith("./"):
    output_file = output_file[len(prefix):]
  if report_file.startswith("./"):
    report_file = report_file[len(prefix):]
  os.system("mkdir -p {0}/{1}".format(output_dir, path))
  cmd = "robot -l {0}/{1} -o {0}/{2} -r {0}/{3} {4}".format(output_dir, log_file, output_file, report_file, name)
  print(cmd)
  ok = os.system(cmd)
  isOK = False
  if ok == 0:
    isOK = True
  else:
    doryStepFail = True    
  result = {"name": name, "log_file": log_file, "output_file": output_file, "report_file": report_file, "ok": isOK}
  results.append(result)
  doryOutputFiles.append(log_file)
  doryOutputFiles.append(output_file)
  doryOutputFiles.append(report_file)
  print(result)

test_results = {"results": results, "doryStepFail": doryStepFail, "doryOutputFiles": doryOutputFiles}
test_results_pretty = json.dumps(test_results, indent=4, sort_keys=True)
print(test_results_pretty)
f = open("/tmp/dory-param-output.json", "w")
f.write(test_results_pretty)
f.close()
  • robotframework镜像的Dockerfile
1
2
3
4
5
6
7
FROM ppodgorsek/robot-framework:latest
LABEL maintainer="cookeem"
LABEL email="cookeem@qq.com"
LABEL version="latest"
COPY run_api_test.py /tmp/
WORKDIR /tmp/
USER 1000:1000
  • 制作robotframework镜像
1
2
docker build -t ${HARBOR_DOMAIN_NAME}/public/ppodgorsek/robot-framework:dory .
docker push ${HARBOR_DOMAIN_NAME}/public/ppodgorsek/robot-framework:dory

设置自定义步骤配置

  • 在dory-dashboard的管理控制台 - 自定义步骤 中新增接口自动化测试的自定义步骤配置,样例如下图:

/docs_old/tasks/add-customize-step-api-test/images/robot-custom-step-config.png

  • 详细配置参见下边定义:
 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
customStepName: testApi
customStepActionDesc: 'api test with robotframework'
customStepDesc: 接口自动化测试
customStepUsage: |
  robotframework的接口测试用例请存放在{{ $.path }}/{{ $.envName }}/,支持多个测试用例
  测试用例文件名必须以.robot结尾  
customStepDockerConf:
  dockerImage: 'public/ppodgorsek/robot-framework:dory'
  dockerCommands:
    - 'python3 /tmp/run_api_test.py'
  dockerRunAsRoot: false
  dockerVolumes:
    - '{{ $.path }}:/{{ $.path }}'
  dockerEnvs: null
  dockerWorkDir: '/{{ $.path }}/{{ $.envName }}'
  paramInputFormat: json
  paramOutputFormat: json
paramInputYamlDef: |
  # 接口自动化脚本存放路径
  path: Tests  
paramOutputYamlDef: |
  # 测试结果
  results: []  
isEnvDiff: true
projectNames:
  - test-project1

在项目定义中设置接口自动化测试的模块定义

  • 在dory-dashboard的项目定义中新增testApi自定义步骤的自定义步骤模块定义,样例如下图:

/docs_old/tasks/add-customize-step-api-test/images/robot-custom-step-def.png

  • 详细配置参见下边定义:
1
2
3
4
5
6
7
8
enableMode: deploy
customStepModuleDefs:
  - moduleName: tp1-gin-demo
    relatedStepModules:
      - tp1-gin-demo
    paramInputYaml: |
      # 接口自动化脚本存放路径
      path: Tests      

在流水线定义中插入接口自动化测试步骤

  • 在dory-dashboard的项目定义流水线定义checkDeploy步骤后边插入自定义步骤testApi,样例如下图:

/docs_old/tasks/add-customize-step-api-test/images/robot-pipeline-def.png

  • 详细配置参见下边定义:
 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
isAutoDetectBuild: false
isQueue: false
builds:
  - name: tp1-gin-demo
    run: true
  - name: tp1-go-demo
    run: false
  - name: tp1-gradle-demo
    run: false
  - name: tp1-new-demo
    run: false
  - name: tp1-node-demo
    run: false
  - name: tp1-python-demo
    run: false
  - name: tp1-rust-demo
    run: false
  - name: tp1-spring-demo
    run: false
pipelineStep:
  gitPull:
    timeout: 60
  build:
    enable: true
    timeout: 0
    retry: 0
  packageImage:
    enable: true
    timeout: 0
    retry: 0
  syncImage:
    enable: true
    retry: 0
  deploy:
    enable: true
    retry: 0
  applyIngress:
    enable: true
    retry: 0
  checkDeploy:
    enable: true
    ignoreError: false
    retry: 0
  checkQuota:
    enable: true
    retry: 0
customStepPhaseDefs:
  scanCode:
    enable: true
    ignoreError: true
    timeout: 0
    retry: 0
  testApi:
    enable: true
    ignoreError: true
    timeout: 0
    retry: 0
customStepInsertDefs:
  checkDeploy:
    - testApi

在代码仓库下对应目录创建测试用例

  • 在代码仓库Tests/test目录下创建tp1-gin-demo.robot测试用例
  • 该测试用例调用tp1-gin-demo微服务的接口,并校验接口返回的message字段是否等于hello world
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
*** Settings ***
Library     RequestsLibrary

*** Test Cases ***
Get Gin Demo Message
    Create Session    gin    http://tp1-gin-demo.test-project1:8000
    ${resp}=    GET On Session    gin    /
    Should Be Equal As Strings    ${resp.status_code}    200
    ${ret}=    Convert To String    ${resp.content}
    Log    ${ret}
    ${message}=    Convert To String    ${resp.json()['message']}
    Log    ${message}
    Should Be Equal As Strings    ${message}    hello world

*** Keywords ***

执行流水线,在检测服务发布正常后进行接口自动化测试

  • 在检测服务发布正常后插入了接口自动化测试

/docs_old/tasks/add-customize-step-api-test/images/robot-pipeline-run-result.png

查看接口自动化测试报告

  • 在步骤执行记录中可以看到相关输出的测试报告文件

/docs_old/tasks/add-customize-step-api-test/images/robot-api-test-step-detail-output.png

  • 测试报告如下图:

/docs_old/tasks/add-customize-step-api-test/images/robot-api-test-result-report.png

  • 测试日志如下图:

/docs_old/tasks/add-customize-step-api-test/images/robot-api-test-result-log.png