Golang持续集成与自动化测试和部署
概述
Golang是一门性能优异的静态类型语言,但因其奇快的编译速度,结合DevOps, 使得它也非常适合快速开发和迭代。
本文讲述如何使用Golang, 进行持续集成与自动化测试和部署。主要使用了以下相关技术:
- dep: 进行包的依赖管理
- gin: 搭建 api 服务
- gorm:ORM, 数据CRUD
- mysql: 存储数据
- testfixtures: 测试夹具,在自动化测试时,自动向数据库填充用于测试的数据
- httpexpect: HTTP 测试包,用于API测试
- GoDotEnv: 环境变量处理
- go test: 使用test命令进行单元测试, 基准测试和 HTTP 测试
- GitLabCI: DevOps 工具
- golint: Golang 静态检查工具
- migrate: 数据库迁移工具
- Docker: 使用 zacksleo/golang 镜像, 该镜像默认安装了 curl,git,build-base,dep 和 golint
- db2struct: 将数据库表结构一键生成为 struct(gorm的model)
- apig: 基于 gorm 和 gin 一键生成 CRUD API
开发流程
- 使用 apig 脚手架工具初始化项目结构和目录
- 使用 dep 安装相关依赖
- 使用 migrate 编写数据库迁移方法,并执行迁移创建数据表
- 使用 db2struct 生成 models
- 使用 apig 生成 crud 代码
- 使用 httpexpect 编写 api 测试代码,并通过 testfixtures 实现数据的自动填充
- 编写 GitLabCI 脚本进行持续集成
在上述过程中,如需连接数据库时,可通过 GoDotEnv 来实现环境变量的使用
相关CI脚本
# golang-devops-and-auto-deploy
image: zacksleo/golang
stages:- test- build- deployvariables:GOPATH: /rootbefore_script:- mkdir -p ~/src/github.com/zacksleo/projectname- cp -r . ~/src/github.com/zacksleo/projectname- cd ~/src/github.com/zacksleo/projectname
lint:stage: testscript:- golint -set_exit_status
unit-tests:stage: testservices:- mysql:5.6variables:MYSQL_ROOT_PASSWORD: rootMYSQL_DATABASE: webMYSQL_USER: webMYSQL_PASSWORD: webscript:- dep ensure- cp tests/.env .env- migrate -database "mysql://web:web@tcp(mysql:3306)/web" -path "./db/migrations/" up- go test -tags=unit_tests $(go list ./... | grep -v /vendor/ ./tests/api) -v -coverprofile .testCoverage.txtcoverage: '/^coverage:\s(\d+(?:\.\d+)?%)/'
integration-tests:stage: testservices:- mysql:5.6variables:MYSQL_ROOT_PASSWORD: rootMYSQL_DATABASE: webMYSQL_USER: webMYSQL_PASSWORD: webscript:- dep ensure- cp tests/.env .env- migrate -database "mysql://web:web@tcp(mysql:3306)/web" -path "./db/migrations/" up- go test -tags=integration $(go list ./tests/... | grep -v /vendor/) -v
build-bin:stage: testscript:- dep ensure- env GOOS=linux GOARCH=386 go build -o $CI_PROJECT_DIR/debugartifacts:expire_in: 60 minsuntracked: truename: "app"paths:- debugwhen: on_success
build-image:image: dockerstage: builddependencies:- build-binscript:- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG .- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG- docker rmi $CI_REGISTRY_IMAGE:$CI_COMMIT_TAGonly:- tagstags:- go
deploy:image: zacksleo/nodestage: deploybefore_script:- eval $(ssh-agent -s)- echo "$SSH_PRIVATE_KEY" > ~/deploy.key- chmod 0600 ~/deploy.key- ssh-add ~/deploy.key- mkdir -p ~/.ssh- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'script:- cd deploy/production- rsync -rtvhze ssh . root@$DEPLOY_SERVER:/data/gitlab/projectname --stats- ssh root@$DEPLOY_SERVER "docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY"- ssh root@$DEPLOY_SERVER "cd /data/gitlab/projectname && echo -e '\nTAG=$CI_COMMIT_TAG' >> .env && docker-compose pull app && docker-compose stop app && docker-compose rm -f app && docker-compose up -d app"only:- tags
集成测试
// +build integrationpackage apiimport ("log""os""testing""github.com/gin-gonic/gin""github.com/jinzhu/gorm""github.com/joho/godotenv""gitlab.com/moguyun/api/debug/db""gitlab.com/moguyun/api/debug/server"testfixtures "gopkg.in/testfixtures.v2"
)var (fixtures *testfixtures.Contexts *gin.Engine
)// PrepareTestDatabase for test
func PrepareTestDatabase(db *gorm.DB) {var fixtures *testfixtures.Contextvar err errortestfixtures.SkipDatabaseNameCheck(true)fixtures, err = testfixtures.NewFolder(db.DB(), &testfixtures.MySQL{}, "../fixtures")if err != nil {log.Fatal(err)}if err = fixtures.Load(); err != nil {log.Fatal(err)}
}// TestMain setup database
func TestMain(m *testing.M) {// Open connection with the test database.godotenv.Load("../.env")database := db.Connect()s = server.Setup(database)PrepareTestDatabase(database)os.Exit(m.Run())
}func TestToken(t *testing.T) {t.Run("CreateToken", TestCreateToken)
}func TestCustomer(t *testing.T) {t.Run("GetCustomers", TestGetCustomers)t.Run("GetCustomer", TestGetCustomer)t.Run("CreateCustomer", TestCreateCustomer)t.Run("UpdateCustomer", TestUpdateCustomer)t.Run("DeleteCustomer", TestDeleteCustomer)
}
注意事项
在测试中,如果需要区分单元测试和集成测试,可以使用 build tags 实现,如在文件头部中添加 // +build integration
, 运行测试使用 - go test -tags=integration $(go list ./tests/... | grep -v /vendor/) -v
可以只执行集成测试
参考文档
- Go Test
- How to write benchmarks in Go
- Go 性能调优之 —— 基准测试
- Go语言圣经(中文版)
- 使用tags区隔单元测试和集成测试
相关文章:

Golang持续集成与自动化测试和部署
概述 Golang是一门性能优异的静态类型语言,但因其奇快的编译速度,结合DevOps, 使得它也非常适合快速开发和迭代。 本文讲述如何使用Golang, 进行持续集成与自动化测试和部署。主要使用了以下相关技术: dep: 进行包的依赖管理gin…...
三套知识系统的实践比较:Notion、Confluence 与 Gitee Wiki
在过去几年中,我们团队先后使用过三套企业知识系统:Notion、Confluence 和 Gitee Wiki。每一套系统上线初期都带来一阵热情,但最终能真正融入研发流程、持续活跃的,只有最后一个。 我们不是要为某个平台背书,而是希望…...

mysql离线安装教程
1.下载地址: https://downloads.mysql.com/archives/community/ 2.上传安装包到系统目录,并解压 tar -xvf mysql-8.0.34-1.el7.x86_64.rpm-bundle.tar3.检查系统中是否存在mariadb的rpm包 rpm -qa|grep mariadb存在则删除 rpm -e xxx4.解压完后执行如下命令安装 sudo rpm -iv…...
OpenGL 3D 编程
OpenGL 是一个强大的跨平台图形 API,用于渲染 2D 和 3D 图形。以下是 OpenGL 3D 编程的入门基础。 一. 环境设置 安装必要的库 GLFW: 用于创建窗口和处理输入 GLEW 或 GLAD: 用于加载 OpenGL 函数 GLM: 数学库,用于 3D 变换 // 基本 OpenGL 程序结构示例 #include <GL/g…...

基于FPGA的VGA显示文字和动态数字基础例程,进而动态显示数据,类似温湿度等
基于FPGA的VGA显示文字和数字 前言一、VGA显示参数二、字模生成三、代码分析1.vga_char顶层2.vga_ctrl驱动文件3.vga_pic数据准备文件 总结 前言 结合正点原子以及野火的基础例程,理解了VGA本身基本协议,VGA本身显示像素为640*480,因此注意生…...

力扣刷题Day 68:搜索插入位置(35)
1.题目描述 2.思路 方法1:回溯的二分查找。 方法2:看到了一个佬很简洁的写法,代码贴在下面了。 3.代码(Python3) 方法1: class Solution:def searchInsert(self, nums: List[int], target: int) ->…...
NodeJS全栈WEB3面试题——P4Node.js后端集成 服务端设计
4.1 如何在 Node.js 中管理钱包与私钥的安全性? 私钥管理原则:不暴露,不硬编码,不明文存储。 常见做法: 加密存储: 使用 crypto 或 ethers.Wallet.encrypt() 加密私钥,存储到数据库或文件系统…...
SQL进阶之旅 Day 12:分组聚合与HAVING高效应用
【SQL进阶之旅 Day 12】分组聚合与HAVING高效应用 在SQL的世界里,分组聚合(Grouping and Aggregation)是处理大规模数据集时最常用的技术之一。它允许我们将数据按照某些列进行分类,并对每个分类进行统计计算。而 HAVING 子句则是…...
深入剖析C#构造函数执行:基类调用、初始化顺序与访问控制
导言 在面向对象编程中,理解对象构造过程至关重要。C#的构造函数执行遵循严格的顺序规则,尤其是涉及继承和成员初始化时。本文将深入解析构造函数的执行流程、初始化语句的妙用以及类访问修饰符的影响,助你写出更健壮、可维护的代码。 构造…...
Java 大数据处理:使用 Hadoop 和 Spark 进行大规模数据处理
Java 大数据处理:使用 Hadoop 和 Spark 进行大规模数据处理 在当今数字化时代,数据呈现出爆炸式增长,如何高效地处理大规模数据成为企业面临的重要挑战。Java 作为一门广泛使用的编程语言,在大数据处理领域同样发挥着关键作用。本文将深入探讨如何利用 Hadoop 和 Spark 这…...

使用Python绘制节日祝福——以端午节和儿童节为例
端午节 端午节总算是回家了,感觉时间过得真快,马上就毕业了,用Python弄了一个端午节元素的界面,虽然有点不像,祝大家端午安康。端午节粽子(python)_python画粽子-CSDN博客https://blog.csdn.net…...
探索大语言模型(LLM):参数量背后的“黄金公式”与Scaling Law的启示
引言 过去十年,人工智能领域最震撼的变革之一,是模型参数量从百万级飙升至万亿级。从GPT-3的1750亿参数到GPT-4的神秘规模,再到谷歌Gemini的“多模态巨兽”,参数量仿佛成了AI能力的代名词。但参数真的是越多越好吗?这…...
Excel to JSON 插件 2.4.0 版本更新
我们很高兴地宣布 Excel to JSON 插件已升级到 2.4.0 版本!本次更新带来了两项重要功能,旨在为您提供更大的灵活性和更强大的数据处理能力。 主要更新内容: 1. 用户可以选择从行或列中选择标题 在之前的版本中,插件通常默认从第…...
黑马点评后端笔记
1.基于Session实现登录流程 发送验证码: 先前端校验,后端再校验(防小人),合法生成验证码(RandomUtil生成),后端保存,在通过短信去发送给用户 短信验证码登录和注册: 拿到验证码和手机号后,后端通过session(spring mvc注入)拿到验证码,进行校验,如果用户…...

C#项目07-二维数组的随机创建
实现需求 创建二维数组,数组的列和宽为随机,数组内的数也是随机 知识点 1、Random类 Public Random rd new Random(); int Num_Int rd.Next(1, 100);2、数组上下限。 //定义数组 int[] G_Array new int[1,2,3,4];//一维数组 int[,] G_Array_T …...

光伏功率预测 | LSTM多变量单步光伏功率预测(Matlab完整源码和数据)
光伏功率预测 | MATLAB实现基于LSTM长短期记忆神经网络的光伏功率预测 目录 光伏功率预测 | MATLAB实现基于LSTM长短期记忆神经网络的光伏功率预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 光伏功率预测 | LSTM多变量单步光伏功率预测(Matlab完整源码和…...
解锁 AI 大语言模型的“知识宝藏”:知识库的奥秘与优化之道
1. 知识库在 AI 大语言模型中的作用 1.1 提供准确信息 知识库是 AI 大语言模型的重要组成部分,能够为模型提供准确的信息。在处理用户问题时,模型可以参考知识库中的数据,从而给出更准确的答案。例如,在医疗领域,知识…...

一步一步配置 Ubuntu Server 的 NodeJS 服务器详细实录——3. 服务器软件更新,以及常用软件安装
前言 前面,我们已经 安装好了 Ubuntu 服务器系统,并且 配置好了 ssh 免密登录服务器 ,现在,我们要来进一步的设置服务器。 那么,本文,就是进行服务器的系统更新,以及常用软件的安装 调整 Ubu…...
第四十天打卡
知识点回顾: 彩色和灰度图片测试和训练的规范写法:封装在函数中展平操作:除第一个维度batchsize外全部展平dropout操作:训练阶段随机丢弃神经元,测试阶段eval模式关闭dropout 作业:仔细学习下测试和训练代码…...
【请关注】ELK集群部署真实案例分享
ELK集群部署 1,准备es配置 es.yml: -------------------------------------------------------------- #集群名称 cluster.name: elasticsearch-cluster #节点名称 node.name: es-node1 #设置绑定的ip地址,可以使ipv4或者ipv6 #绑定这台机器的任何一个ip network.bind_hos…...
odoo17 windows server布署错误分析
odoo17 windows server布署错误分析 错误代码: File "C:\od172406\odoo\sql_db.py", line 681, in borrow result psycopg2.connect( ^^^^^^^^^^^^^^^^^ File "C:\od172406\venv\Lib\site-packages\psycopg2\__init__.py"…...

PyTorch 入门学习笔记
一、简介 PyTorch 是由 Meta(原 Facebook) 开源的深度学习框架。其前身 Torch 是一个基于 LuaJIT 的科学计算框架,核心功能是提供高效的张量(Tensor)操作和神经网络支持。由于 Lua 语言的生态限制,Torch 逐…...
【 Samba】Windows 用户访问Docker服务器上当前A用户的 ~/aaa目录
要让 Windows 用户访问 ~/aaa目录,需要在 Linux 系统上配置 Samba 共享服务,并设置合适的权限。以下是具体步骤: 1. 安装 Samba bash sudo apt update sudo apt install samba 2. 创建 Samba 用户(可选) 如果你希望 …...

pycharm生成图片
文章目录 图片例子生成图片并储存,设置中文字体支持两条线绘制散点图和直方图绘制条形图(bar)绘制条形图(横着的)(plt.barh)分组的条形图 颜色和线条风格1. **颜色字符 (color)**其他颜色指定方…...

Android 云手机横屏模式下真机键盘遮挡输入框问题处理
一、背景 打开横屏应用,点击云机EditText输入框,输入框被键盘遮挡,如下图: 未打开键盘状态: 点击第二个输入框,键盘遮挡了输入框: 二、解决方案(推荐第三中方案,博主采用的也是第三种方案) 博主这里整理了三种方案:…...
Redis 中的 5 种数据类型和示例场景
Redis 作为一款高性能的键值对数据库,凭借其丰富的数据类型,在缓存、消息队列、排行榜等众多场景中发挥着重要作用。本文将详细介绍 Redis 的 5 种核心数据类型,并结合示例场景和代码,让你快速掌握它们的使用方法。 一、String&am…...

Axure设计案例——科技感对比柱状图
想让数据对比展示摆脱平淡无奇,瞬间抓住观众的眼球吗?那就来看看这个Axure设计的科技感对比柱状图案例!科技感设计风格运用独特元素打破传统对比柱状图的常规,营造出一种极具冲击力的视觉氛围。每一组柱状体都仿佛是科技战场上的士…...
SpringBoot项目搭建指南
SpringBoot项目搭建指南 文章目录 SpringBoot项目搭建指南一、SpringBoot项目搭建1.1 SpringBoot 版本选择1.2 SpringBoot 框架引入方式1.2.1 继承 Starter Parent POM1.2.2 不使用 Parent POM 来使用 Spring Boot 1.3 SpringBoot 打包插件 二、日志框架引入2.1 引入SpringBoot…...
分布式锁剖析
一、分布式锁 1. 为什么需要分布式锁? 在单体应用中,通过synchronized或ReentrantLock等进程内锁即可解决多线程资源竞争问题。但在分布式系统中,多个服务实例运行在不同进程中,传统进程内锁失效,此时需要一种跨进程…...
C语言中函数指针和指针函数的定义及用法
在C/C中,函数指针和指针函数是两个容易混淆但完全不同的概念。以下是它们的详细对比和学习指南,结合代码示例帮助你彻底掌握。 1. 函数指针(Function Pointer) 本质:一个指向函数的指针变量,用于动态调用…...