Jenkins | 多命令行持续集成

Jenkins + Newman + Nodejs + python3 + Nginx 实现自动化测试

Posted by Haauleon on April 20, 2021

一、背景

目前已实现的 jenkins 持续集成如下:

  • 使用 jenkins 定时构建自动化测试
  • 使用 postman + newman 执行自动化测试并生成测试报告
  • 使用 python3 脚本对测试报告进行解析,若接口异常数不为 0 则发送钉钉消息
  • 使用 nodejs 工具包 publish-sftp 自动上传测试报告至阿里云服务器,可远程访问测试报告



二、测试目录结构分析



三、Jenkins 配置

1.配置定时构建

  当前定时构建的日程表为 H/10 * * * *,即为每十分钟执行一次。



2.配置构建内容

  Jenkins 的构建内容的填写:由于是使用本地的解释器、工具包,因此均需要指定环境路径。若不想使用环境路径,则需要在 Jenkins 服务器中安装环境。



1
2
3
4
5
6
7
8
9
10
11
# newman 自动化测试并生成测试报告
/usr/local/lib/node_modules/newman/bin/newman.js run /Users/haauleon/PythonTest/jsonRequest/saas/saas-collection.json -e /Users/haauleon/PythonTest/jsonRequest/saas/saas-env-online.json -g /Users/haauleon/PythonTest/jsonRequest/saas/saas-globals.json --reporters html --reporter-html-export /Users/haauleon/PythonTest/jsonRequest/report/saas_online_report.html

# python3 解析测试报告并发送钉钉消息预警
/usr/local/bin/python3 /Users/haauleon/PythonTest/jsonRequest/saas/online_notice.py

# 进入报告所在目录 (新建的 sftp.json 配置文件在此 report 目录,目前只能有一个配置文件,两个配置文件的我还没试过,估计会报错)
cd /Users/haauleon/PythonTest/jsonRequest/report

# 上传文件至服务器
/usr/local/lib/node_modules/publish-sftp/index.js -c



四、Jenkins 构建内容分析

1.Newman 自动化测试

  在 Postman 上调试通过之后,下载 环境变量文件全局变量文件测试集合文件 至本地,通过 Newman 命令行执行自动化测试并生成测试报告。可指定测试报告生成的路径。
  下面通过 json 格式来描述我从 Postman 导出的文件路径和自定义的测试报告路径。

1
2
3
4
5
6
{
    "测试集合文件": "/Users/haauleon/PythonTest/jsonRequest/saas/saas-collection.json",
    "环境变量文件": "/Users/haauleon/PythonTest/jsonRequest/saas/saas-env-online.json",
    "全局变量文件": "/Users/haauleon/PythonTest/jsonRequest/saas/saas-globals.json",
    "测试报告路径": "/Users/haauleon/PythonTest/jsonRequest/report/saas_online_report.html"
}


  在本地终端使用 newman 命令行进行自动化测试。
格式

1
$ newman run "测试集合文件" -e "环境变量文件" -g "全局变量文件" -reportershtml --reporter-html-export "测试报告路径"


实例:   在 Jenkins 服务器上使用本地的解释器或者 nodejs 工具,需要指定环境路径,我这里的路径是 /usr/local/lib/node_modules/newman/bin/newman.js

1
/usr/local/lib/node_modules/newman/bin/newman.js run /Users/haauleon/PythonTest/jsonRequest/saas/saas-collection.json -e /Users/haauleon/PythonTest/jsonRequest/saas/saas-env-online.json -g /Users/haauleon/PythonTest/jsonRequest/saas/saas-globals.json --reporters html --reporter-html-export /Users/haauleon/PythonTest/jsonRequest/report/saas_online_report.html



2.Python3 解析测试报告

  写 python3 脚本解析 html 测试报告,若接口数量数量不为 0 则使用 outgoing 向钉钉群组发送消息。
  由 newman 生成的测试报告样式如下:

消息模板如下:

1
2
3
项目运行环境: saas生产环境
接口异常数量: 4
测试报告路径: http://112.74.205.108/saas_online_report.html



具体脚本如下:

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
#!/usr/local/bin/python3 python3
# -*- coding:utf-8 -*-
import requests,json
# from utils.traceback_error import traceback_error
from functools import wraps
import os
import sys
import time
from lxml import etree


def traceback_error(func):
    @wraps(func)
    def wraper(self, *args, **kwargs):
        try:
            result = func(self,*args, **kwargs)
        except Exception as e:
            import traceback
            ex_msg = '{exception}'.format(exception=traceback.format_exc())
            print(ex_msg)
            result=ex_msg
        return result
    return wraper

'''钉钉发送通知方法'''
class dingding_notice():

    def __init__(self,ding_token=None,atMobiles=None,isAtAll=None):
        # 根据电话@用户
        self.atMobiles = ['13976062467',] if atMobiles==None else atMobiles
        # self.token = 'cbb3b771657ef' if ding_token==None else ding_token
        # 是否@所有人
        self.isAtAll = True if isAtAll==None else isAtAll
        self.token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxfd00eab47ab8b9a26cd734c20d34fdfec641d97'
        self.api = 'https://oapi.dingtalk.com/robot/send?access_token={}'.format(self.token)
        self.headers = {'Content-Type': 'application/json;charset=utf-8'}

    @traceback_error
    def send_msg(self,content):
        msg = {
            'msgtype': 'text',
            'text': {'content': content},
            'at': {'atMobiles': self.atMobiles, 'isAtAll': self.isAtAll}
        }
        data = requests.post(self.api, data=json.dumps(msg), headers=self.headers).json()
        return json.dumps(data)


if __name__ == '__main__':
    try:
        service = dingding_notice()
        testdir = sys.path[0]
        # command_url = "/usr/local/lib/node_modules/newman/bin/newman.js run {base}/saas-collection.json -e {base}/saas-env-online.json -g {base}/saas-globals.json --reporters html --reporter-html-export {base}/saas_online_report.html".format(base=testdir)
        # print(command_url)
        # pipeline = os.popen(command_url)
        # pipeline.read()
        report_name = '%s/saas_online_report.html' %testdir
        with open (report_name, 'r', encoding="utf-8") as htmlf:
            htmlt = htmlf.read()
        html = etree.HTML(htmlt)
        fail_count = int(html.xpath("/html/body/div/div[1]/div[35]/strong/text()")[0])  # 提取测试报告中断言失败数量字段的值。
        if fail_count:
            content = "项目运行环境: saas生产环境 \n"      \
                      "接口异常数量: %s \n"               \
                      "测试报告路径: %s" %(fail_count,"http://112.74.205.108/saas_online_report.html")
            result=service.send_msg(content=content)
            print(result)
        else:
            print("saas生产环境接口测试执行完成且无任何异常")
    except Exception as e:
        import traceback
        ex_msg = '{exception}'.format(exception=traceback.format_exc())
        print(ex_msg)



3.上传文件至服务器

  使用 nodejs 工具包 sftp-publish 将本地文件自动上传至阿里云服务器,需要新建一个自定义命名的配置文件,当前 sftp.json 文件配置如下:

1
2
3
4
5
6
7
8
9
10
11
{
    "localPath": "./",
    "remotePath": "/usr/test-haauleon",
    "protectedRemotePath": "/usr/test-haauleon",
    "connect": {
        "host": "112.74.205.108",
        "port": 22,
        "username": "root",
        "password": "服务器root密码"
    }
}


  使用该工具时,需要 cd 进入到配置文件 sftp.json 所在的 report 目录,然后使用命令行进行文件上传。若不指定配置文件所在的目录,则命令执行失败且会提示在 xxxxx 目录下找不到 sftp.json 文件。

1
2
3
4
5
# 进入报告所在目录(由于我将配置文件放在 report 目录下,所以需要先进入 sftp.json 配置文件所在的目录。否则会报错,提示此配置文件在 report 目录找不到)
cd /Users/haauleon/PythonTest/jsonRequest/report

# 使用命令行上传文件至服务器(在 Jenkins 服务器使用本地环境的 nodejs 包,需要指定环境路径)
/usr/local/lib/node_modules/publish-sftp/index.js -c



五、结论

  愉快的构建,省了很多麻烦。