Golang持续集成与自动化测试和部署

[复制链接]
发表于 2025-7-7 15:49:46 | 显示全部楼层 |阅读模式
概述


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脚本

  1. # golang-devops-and-auto-deploy
  2. image: zacksleo/golang
  3. stages:
  4.     - test
  5.     - build
  6.     - deploy
  7. variables:
  8.     GOPATH: /root
  9. before_script:
  10.     - mkdir -p ~/src/github.com/zacksleo/projectname
  11.     - cp -r . ~/src/github.com/zacksleo/projectname
  12.     - cd ~/src/github.com/zacksleo/projectname
  13. lint:
  14.     stage: test
  15.     script:
  16.         - golint -set_exit_status
  17. unit-tests:
  18.     stage: test
  19.     services:
  20.         - mysql:5.6
  21.     variables:
  22.         MYSQL_ROOT_PASSWORD: root
  23.         MYSQL_DATABASE: web
  24.         MYSQL_USER: web
  25.         MYSQL_PASSWORD: web
  26.     script:
  27.         - dep ensure
  28.         - cp tests/.env .env
  29.         - migrate -database "mysql://web:web@tcp(mysql:3306)/web" -path "./db/migrations/" up
  30.         - go test -tags=unit_tests $(go list ./... | grep -v /vendor/ ./tests/api) -v -coverprofile .testCoverage.txt
  31.     coverage: '/^coverage:\s(\d+(?:\.\d+)?%)/'
  32. integration-tests:
  33.     stage: test
  34.     services:
  35.         - mysql:5.6
  36.     variables:
  37.         MYSQL_ROOT_PASSWORD: root
  38.         MYSQL_DATABASE: web
  39.         MYSQL_USER: web
  40.         MYSQL_PASSWORD: web
  41.     script:
  42.         - dep ensure
  43.         - cp tests/.env .env
  44.         - migrate -database "mysql://web:web@tcp(mysql:3306)/web" -path "./db/migrations/" up
  45.         - go test -tags=integration $(go list ./tests/... | grep -v /vendor/) -v
  46. build-bin:
  47.     stage: test
  48.     script:
  49.         - dep ensure
  50.         - env GOOS=linux GOARCH=386 go build -o $CI_PROJECT_DIR/debug
  51.     artifacts:
  52.       expire_in: 60 mins
  53.       untracked: true
  54.       name: "app"
  55.       paths:
  56.         - debug
  57.       when: on_success
  58. build-image:
  59.     image: docker
  60.     stage: build
  61.     dependencies:
  62.         - build-bin
  63.     script:
  64.         - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
  65.         - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG .
  66.         - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
  67.         - docker rmi $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
  68.     only:
  69.         - tags
  70.     tags:
  71.         - go
  72. deploy:
  73.     image: zacksleo/node
  74.     stage: deploy
  75.     before_script:
  76.         - eval $(ssh-agent -s)
  77.         - echo "$SSH_PRIVATE_KEY" > ~/deploy.key
  78.         - chmod 0600 ~/deploy.key
  79.         - ssh-add ~/deploy.key
  80.         - mkdir -p ~/.ssh
  81.         - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
  82.     script:
  83.         - cd deploy/production
  84.         - rsync -rtvhze ssh . root@$DEPLOY_SERVER:/data/gitlab/projectname --stats
  85.         - ssh root@$DEPLOY_SERVER "docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY"
  86.         - 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"
  87.     only:
  88.         - tags
复制代码
集成测试

  1. // +build integration
  2. package api
  3. import (
  4.         "log"
  5.         "os"
  6.         "testing"
  7.         "github.com/gin-gonic/gin"
  8.         "github.com/jinzhu/gorm"
  9.         "github.com/joho/godotenv"
  10.         "gitlab.com/moguyun/api/debug/db"
  11.         "gitlab.com/moguyun/api/debug/server"
  12.         testfixtures "gopkg.in/testfixtures.v2"
  13. )
  14. var (
  15.         fixtures *testfixtures.Context
  16.         s        *gin.Engine
  17. )
  18. // PrepareTestDatabase for test
  19. func PrepareTestDatabase(db *gorm.DB) {
  20.         var fixtures *testfixtures.Context
  21.         var err error
  22.         testfixtures.SkipDatabaseNameCheck(true)
  23.         fixtures, err = testfixtures.NewFolder(db.DB(), &testfixtures.MySQL{}, "../fixtures")
  24.         if err != nil {
  25.                 log.Fatal(err)
  26.         }
  27.         if err = fixtures.Load(); err != nil {
  28.                 log.Fatal(err)
  29.         }
  30. }
  31. // TestMain setup database
  32. func TestMain(m *testing.M) {
  33.         // Open connection with the test database.
  34.         godotenv.Load("../.env")
  35.         database := db.Connect()
  36.         s = server.Setup(database)
  37.         PrepareTestDatabase(database)
  38.         os.Exit(m.Run())
  39. }
  40. func TestToken(t *testing.T) {
  41.         t.Run("CreateToken", TestCreateToken)
  42. }
  43. func TestCustomer(t *testing.T) {
  44.         t.Run("GetCustomers", TestGetCustomers)
  45.         t.Run("GetCustomer", TestGetCustomer)
  46.         t.Run("CreateCustomer", TestCreateCustomer)
  47.         t.Run("UpdateCustomer", TestUpdateCustomer)
  48.         t.Run("DeleteCustomer", TestDeleteCustomer)
  49. }
复制代码
留意事项

在测试中,假如需要区分单元测试和集成测试,可以使用 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区隔单元测试和集成测试

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

快速回复 返回顶部 返回列表