首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在docker应用程序中从测试方法中分别运行docker映像

在docker应用程序中从测试方法中分别运行docker映像
EN

Stack Overflow用户
提问于 2021-12-22 04:16:37
回答 3查看 216关注 0票数 0

我有一个码头应用,里面有两个容器。一个是MySql,另一个是一些逻辑代码,我已经创建了一个使用Dockerfile的自定义映像。对于端到端测试,我希望将一些值存储在数据库中,然后运行逻辑代码映像()。这是我目前拥有的坞-撰写文件:

代码语言:javascript
复制
version: '3'
networks:
  docker-network:
    driver: bridge
services:
    database:
        image: mysql
        env_file:
          - ./src/logic/environment-variables.env
        ports:
          - 3306:3306
        healthcheck:
          test: "mysql -uroot -p$$MYSQL_ROOT_PASSWORD $$MYSQL_DATABASE -e 'select 1'"
          timeout: 20s
          retries: 10
        network:
          docker-network
    logic:
        container_name: main-logic
        build: ./src/logic/.
        depends_on:
          database:
            condition: service_healthy
        network:
          docker-network

我不能作为一个整体运行这个应用程序,因为当数据库运行时,它就会运行主程序。相反,我想启动db,在其中存储一些值,然后运行逻辑映像。我如何在测试方法中做到这一点?

考虑的方法是:从测试方法分别启动mysql映像,然后将值存储在it.Then中,启动逻辑映像并检查数据库的结果。是否有更好的方法或框架可用于此?

EN

回答 3

Stack Overflow用户

发布于 2021-12-22 04:24:22

这里需要的是数据库迁移。这项工作如下:

  • 在启动服务之前启动DB实例。
  • 将服务连接到DB。
  • 在DB上运行迁移。
  • 继续执行服务。

考虑一下:https://github.com/golang-migrate/migrate

票数 0
EN

Stack Overflow用户

发布于 2021-12-22 08:34:37

对于你的方法:

  1. 启动MySQL图像。
  2. 将数据上载到数据库。
  3. 启动逻辑图像。
  4. 检查数据库以获得结果。

您可以:

使用Makefile

其中包含一个sh脚本,它将逐个执行所有步骤。

Makefile:

代码语言:javascript
复制
start_test:
    docker-compose run -d database
    # put here your data uploading script
    docker-compose run -d logic
    #  put here your data database checking script

然后执行

代码语言:javascript
复制
$make start_test # execute all steps

使用测试容器-Go

测试容器GitHub

Testcontainers-Go是一个Go包,它使创建和清理基于容器的依赖关系变得简单,用于自动集成/冒烟测试。

它允许您执行go测试方法中的所有步骤。就你的情况而言,你会遇到这样的情况:

只是一个草案的代码,以赶上这一想法:

代码语言:javascript
复制
package main

import (
    "context"
    "database/sql"
    "fmt"
    "github.com/pkg/errors"
    "github.com/testcontainers/testcontainers-go"
    "github.com/testcontainers/testcontainers-go/wait"
    "log"
    "testing"
)

var db *sql.DB

func TestIntegration(t *testing.T) {
    if testing.Short() {
        t.Skip("skipping integration test")
    }
    
    err := setupMySql()
    if err != nil {
        t.Errorf("Test failed with error: %s", err)
    }
    
    err = setupData()
    if err != nil {
        t.Errorf("Test failed with error: %s", err)
    }
    err = setupLogic()
    if err != nil {
        t.Errorf("Test failed with error: %s", err)
    }
    err = checkResult()
    if err != nil {
        t.Errorf("Test failed with error: %s", err)
    }
}

func setupMySql() error {
    ctx := context.Background()
    req := testcontainers.ContainerRequest{
        Image:        "mysql:latest",
        ExposedPorts: []string{"3306/tcp", "33060/tcp"},
        Env: map[string]string{
            "MYSQL_ROOT_PASSWORD": "secret",
        },
        WaitingFor: wait.ForLog("port: 3306  MySQL Community Server - GPL"),
    }
    mysqlC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
        ContainerRequest: req,
        Started:          true,
    })
    defer func() {
        err := mysqlC.Terminate(ctx)
        if err != nil {
            log.Fatal(err)
        }
    }()
    
        if err != nil {
            return errors.Wrap(err, "Failed to run test container")
        }
    
    host, err := mysqlC.Host(ctx)
    p, err := mysqlC.MappedPort(ctx, "3306/tcp")
    port := p.Int()
    connectionString := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?tls=skip-verify",
        "root", "secret", host, port, "database")
    
    db, err = sql.Open("mysql", connectionString)
    defer func(db *sql.DB) {
        err := db.Close()
        if err != nil {
            log.Fatal(err)
        }
    }(db)
    
    if err != nil {
        return errors.Wrap(err, "Failed to connect to db")
    }
    
    return nil
}

func setupData() error {
    // db.Query(), your code with uploading data
    return nil
}

func setupLogic() error {
    // run your logic container
    return nil
}

func checkResult() error {
    // db.Query(), your code with checking result
    return nil
}

使用码头工人

Dockertest帮助您以最小的工作量启动用于Go测试的电子对接器图像。

和测试容器一样-去,

只是一个草案的代码,以赶上这一想法:

代码语言:javascript
复制
package main

import (
    "database/sql"
    "fmt"
    "github.com/ory/dockertest/v3"
    "github.com/pkg/errors"
    "testing"
)

var db *sql.DB

func TestIntegration(t *testing.T) {
    if testing.Short() {
        t.Skip("skipping integration test")
    }
    
    err := setupMySql()
    if err != nil {
        t.Errorf("Test failed with error: %s", err)
    }
    
    err = setupData()
    if err != nil {
        t.Errorf("Test failed with error: %s", err)
    }
    err = setupLogic()
    if err != nil {
        t.Errorf("Test failed with error: %s", err)
    }
    err = checkResult()
    if err != nil {
        t.Errorf("Test failed with error: %s", err)
    }
}

func setupMySql() error {
    // uses a sensible default on windows (tcp/http) and linux/osx (socket)
    pool, err := dockertest.NewPool("")
    if err != nil {
        return errors.Wrap(err, "Could not connect to docker")
    }
    
    // pulls an image, creates a container based on it and runs it
    resource, err := pool.Run("mysql", "5.7", []string{"MYSQL_ROOT_PASSWORD=secret"})
    if err != nil {
        return errors.Wrap(err, "Could not start resource")
    }
    
    // exponential backoff-retry, because the application in the container might not be ready to accept connections yet
    if err := pool.Retry(func() error {
        var err error
        db, err = sql.Open("mysql", fmt.Sprintf("root:secret@(localhost:%s)/mysql", resource.GetPort("3306/tcp")))
        if err != nil {
            return err
        }
        return db.Ping()
    }); err != nil {
        return errors.Wrap(err, "Could not connect to database")
    }
    
    if err := pool.Purge(resource); err != nil {
        return errors.Wrap(err, "Could not purge resource")
    }
    
    return nil
}

func setupData() error {
    // db.Query(), your code with uploading data
    return nil
}

func setupLogic() error {
    // run your logic container
    return nil
}

func checkResult() error {
    // db.Query(), your code with checking result
    return nil
}
票数 0
EN

Stack Overflow用户

发布于 2021-12-22 12:14:46

您可以完全按照问题中的话来做:启动数据库,手动加载种子数据,并启动应用程序的其余部分。因为您的数据库已经发布了ports:,所以您可以直接从主机连接到它,而不需要做任何特殊的事情。

代码语言:javascript
复制
docker-compose up -d database
mysql -h 127.0.0.1 < seed_data.sql
docker-compose up -d

@advayrajhansa的回答建议使用数据库迁移系统。如果这是内置在您的形象,您可以docker-compose run logic migrate ...作为中间步骤。这将在您在docker-compose.yml文件中定义的容器上运行一个备用命令。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70444149

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档