持续交付之.Net项目单测自动化框架落地(入门篇)

网友投稿 672 2022-05-30

前言

落地方案

技术架构

主要特点

技术选型

核心步骤

功能展示

单元测试

覆盖度分析

钉钉通知

前言

落地方案

技术架构

主要特点

技术选型

核心步骤

功能展示

单元测试

覆盖度分析

钉钉通知

遇到的坑

小结

前言

自动化测试框架和平台形形色色,只有最合适项目团队的才是最好的,本文带着大家快速搭建一个属于自己.Net项目的轻型单测自动化框架。

落地方案

技术架构

主要特点

使用 MSTest 作为项目运行框架,方便执行测试用例,生成测试结果

使用开源工具作为报告驱动,二次美化功能,界面更美观,内容清晰,实现在线 HtmlReport

实现测试历史结果趋势分析

实现钉钉自动化通知及跳转功能

实现覆盖度结果上传 SonarQube

使用 Jenkins 作为自助式测试,一站式测试平台,方便自动编译,自动运行测试脚本,发送测试报告,通知等

技术选型

单测框架:MSTest

单测报告框架:Trxer

覆盖度扫描工具:Opencover

覆盖度报告框架:ReportGenerator

覆盖度报告服务:Tomcat

自动通知:钉钉webhook & python

Jenkins 插件:

Git plugin:拉取代码

Version Number Plugin:生成部分版本号

window 批处理:执行bat脚本

SonarScanner for MSBuild:静态代码扫描

MSBuild Plugin:代码编译

MSTest plugin:执行测试

HTML Publisher plugin:单测在线 HtmlReport

Groovy Plugin:设置 HtmlReport 插件 css 生效

相关工具链接:

trxer:https://github.com/NivNavick/trxer

opencover:https://github.com/OpenCover/opencover

ReportGenerator:https://github.com/danielpalme/ReportGenerator

核心步骤

1)设置上传覆盖度结果上传到 SonarQube :

/d:propertyKey="TestResults\TestResults.trx" /d:sonar.cs.opencover.reportsPaths="TestResults\CodeCoverageResults.xml"

参考下图:

2)执行 MSBuild 编译,这里参考自己的项目设置:

3)执行单测及覆盖度扫描脚本如下:

::删除原文件 rmdir /s/q TestResults mkdir TestResults ::执行单元测试及覆盖度扫描 "C:\opencover.4.7.922\opencover.console.exe" -target:"C:\Program Files (x86)\Microsoft Visual Studio17\Enterprise\Common7\IDE\MSTest.exe" -targetargs:/testcontainer:"D:\Jenkins-workspace\Jenkins\workspace\bin\unitTest\UnitTestServer.dll" -filter:+[*]* -register:user -mergebyhash -output:TestResults\CodeCoverageResults.xml ::修改文件名 cd TestResults ren *.trx TestResults.trx ::生成单元测试报告 "D:\trxer\TrxerConsole\bin\Debug\TrxerConsole.exe" TestResults.trx ::生成单元测试覆盖度报告 "C:\ReportGenerator_4.1.4\net47\ReportGenerator.exe" -reports:"CodeCoverageResults.xml" -targetdir:"Coverage_%BUILD_NUMBER%" ::拷贝到服务器 xcopy Coverage_%BUILD_NUMBER% \xxx.xxx.xxx.xxx\webapps\v3c\coverage\%JOB_NAME%\Coverage_%BUILD_NUMBER% /I/F/E/Y

参考下图:

注意:

Tomcat 服务的主机需要开启共享文件(window)

配置 Groovy script,让 HtmlReport 插件 css 能用,同时不用担心 Jenkins 重启:

System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")

参考下图:

5)构建后操作,发布单测 HtmlReport:

注意:

HTML directory to archive:报告路径

Index page[s] :报告索引名称

Keep past HTML reports:保留报告

设置统计分析测试结果 :

7)post build task 执行钉钉通知:

持续交付之.Net项目单测自动化框架落地(入门篇)

Python脚本:

# coding=utf-8 ''' @author: zuozewei @file: notification.py @time: 2019/4/25 18:00 @description:dingTalk通知类 ''' import os, jenkins, configparser, requests, json, time from dingtalkchatbot.chatbot import DingtalkChatbot from jsonpath import jsonpath # 获取 Jenkins 变量 JOB_NAME = str(os.getenv("JOB_NAME")) BUILD_URL = str(os.getenv("BUILD_URL")) + "console" BUILD_VERSION = str(os.getenv("BUILD_VERSION")) JENKINS_HOME = os.getenv("JENKINS_HOME") BUILD_NUMBER = str(os.getenv("BUILD_NUMBER")) WORKSPACE = os.getenv("WORKSPACE") versionPath = JENKINS_HOME + "\workspace\Version.ini" config = configparser.ConfigParser() config.read(versionPath) xxx_Major = config.get("xxx", "xxx_Major") xxx_Minor = config.get("xxx", "xxx_Minor") xxx_Build = config.get("xxx", "xxx_Build") xxx_Revision = config.get("xxx", "xxx_Revision") VERSION = xxx_Major + "." + xxx_Minor + "." + xxx_Build + "." + xxx_Revision reportUrl = 'http://xxx.xxx.xxx.xxx:8080/view/xxx/job/' + JOB_NAME + '/' + BUILD_NUMBER + '/HTML_20Report/' # 连接jenkins server = jenkins.Jenkins(url="http://xxx.xxx.xxx.xxx:8080", username='xxx', password="xxx") testresult = '' packagePath = WORKSPACE + "\\package.ini" overageReportUrl = 'http://xxx.xxx.xxx.xxx/xxx/coverage/' + JOB_NAME + '/Coverage_' + BUILD_NUMBER def unitTestNotification(): title = 'xxx单测通知' last_build_number = server.get_job_info(JOB_NAME)['lastCompletedBuild']['number'] build_info = server.get_build_info(JOB_NAME, last_build_number) # dict字典转json数据 build_info_json = json.dumps(build_info) # 把json字符串转json对象 build_info_jsonobj = json.loads(build_info_json) failCount = jsonpath(build_info_jsonobj, '$.actions..failCount') skipCount = jsonpath(build_info_jsonobj, '$.actions..skipCount') totalCount = jsonpath(build_info_jsonobj, '$.actions..totalCount') successCount = totalCount[0] - skipCount[0] - failCount[0] successRate = round((successCount / totalCount[0]) * 100, 1) # 判断测试结果 if successRate == 100: testresult = 'SUCCESS' else: testresult = 'FAILURE' testFail = '#### ' + JOB_NAME + ' - UnitTest # ' + BUILD_NUMBER + ' \n' + \ '##### 测试结果: ' + testresult + ' \n' + \ '##### **版本类型**: ' + '开发版' + '\n' + \ '##### **当前版本**: ' + VERSION + '\n' + \ '##### **用例数**: ' + str(totalCount[0]) + '个 \n' + \ '##### **通过率**: ' + str(successRate) + '% \n' + \ '##### **成功**: ' + str(successCount) + '个 \n' + \ '##### **失败**: ' + str(failCount[0]) + '个 \n' + \ '##### **忽略**: ' + str(skipCount[0]) + '个 \n' + \ '##### **测试报告**: [查看详情](' + reportUrl + ') \n' + \ '##### **覆盖率报告**: [查看详情](' + overageReportUrl + ') \n' + \ '##### **关注人**: @18610902487 \n' + \ '> ###### xxx技术团队 \n ' testSuccess = '#### ' + JOB_NAME + ' - UnitTest # ' + BUILD_NUMBER + ' \n' + \ '##### **测试结果**: ' + testresult + '\n' + \ '##### **版本类型**: ' + '开发版' + '\n' + \ '##### **当前版本**: ' + VERSION + '\n' + \ '##### **用例数**: ' + str(totalCount[0]) + '个 \n' + \ '##### **通过率**: ' + str(successRate) + '% \n' + \ '##### **成功**: ' + str(successCount) + '个 \n' + \ '##### **失败**: ' + str(failCount[0]) + '个 \n' + \ '##### **忽略**: ' + str(skipCount[0]) + '个 \n' + \ '##### **测试报告**: [查看详情](' + reportUrl + ') \n' + \ '##### **覆盖率报告**: [查看详情](' + overageReportUrl + ') \n' + \ '> ###### xxx技术团队 \n ' if testresult == 'SUCCESS': dingText = testSuccess else: dingText = testFail sendding(title, dingText) def sendding(title, content): at_mobiles = ['186xxxx2487'] Dingtalk_access_token_v3c = 'https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxx' # 初始化机器人小丁 xiaoding1 = DingtalkChatbot(Dingtalk_access_token_v3c) # Markdown消息@指定用户 xiaoding1.send_markdown(title=title, text=content, at_mobiles=at_mobiles) if __name__ == "__main__": unitTestNotification()

功能展示

测试结果趋势:

在线 HtmlReport:

访问 Tomcat 报告 web 服务:

遇到的坑

单元测试中依赖的数据文件或者dll等非引用关系的资源导致测试失败(找不到依赖),开发case的时候需要加标识 DeploymentItem:

小结

本文带着大家结合 Jenkins 快速入门搭建一款属于自己Net项目单测自动化框架,希望你能有启发。

本文资源:

https://github.com/zuozewei/blog-example/tree/master/Jenkins-ci/jenkins-net-unitautotest

Jenkins 编译构建 CloudBuild

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:【直播资讯】华为云联合敢为软件,共同打造“自定义场景化”智慧园区
下一篇:【愚公系列】2021年12月 二十三种设计模式(二十三)-访问者模式
相关文章