使用Docker容器的Pytest测试实用程序。

lovely-pytest-docker的Python项目详细描述


https://img.shields.io/pypi/v/lovely-pytest-docker.svghttps://img.shields.io/pypi/pyversions/lovely-pytest-docker.svghttps://travis-ci.com/lovelysystems/lovely-pytest-docker.svg?branch=master

创建简单的Pytestfixture,用于基于docker编写集成测试 容器。框架提供了一个服务类来启动和停止容器 基于Docker的合成。每个容器可以单独启动。

这个包裹的某些部分是从 https://github.com/AndreLouisCaron/pytest-docker

与pytest一起使用

docker compose文件应该包含所有需要的容器和端口 应该暴露出来。在下面的示例中,我们希望启动应用程序进行测试 以及一个sql数据库(crate)。假设应用程序有一个Dockerfile。 在与Docker相同的文件夹中编写文件:

version: "3"
services:
  app:
    build: .
    ports:
      - "8080"
    depends_on:
      - "crate"

  crate:
    image: crate:latest
    ports:
      - "4200"

conftest.py文件中,我们可以为每个服务声明docker fixture 我们希望能够在测试中开始:

import pytest

@pytest.fixture(scope='session')
def docker_app(docker_services):
    docker_services.start('app')
    public_port = docker_services.wait_for_service("app", 8080)
    url = "http://{docker_services.docker_ip}:{public_port}".format(**locals())
    return url

@pytest.fixture(scope='session')
def docker_crate(docker_services):
    docker_services.start('crate')
    public_port = docker_services.wait_for_service("crate", 4200)
    dsn = "{docker_services.docker_ip}:{public_port}".format(**locals())
    return dsn

默认情况下,fixture将在 tests位于pytest.ini所在路径的子文件夹(或项目的 如果没有给定ini文件,则为根目录(如测试示例中所示)。在许多 您将要覆盖Docker撰写文件的位置的案例。只是 覆盖conftest.py文件中的docker_compose_files设备:

@pytest.fixture(scope='session')
def docker_compose_files(pytestconfig):
    """Get the docker-compose.yml absolute path.
    Override this fixture in your tests if you need a custom location.
    """
    return [
        project_path('docker', 'docker-compose.yml'),
    ]

在测试文件中声明要使用的设备:

def test_something(docker_app, docker_crate):
    # e.g. initialize database
    ...
    # test something (e.g. request to docker_app)
    ...

工作配置和测试示例可以在tests文件夹中找到 这个包裹的。

在Docker容器中执行

可以在其中一个Docker容器中执行命令。使用 docker_servicesfixture的exec方法:

def test_exec(docker_services):
    # the first argument is the service name of the compose file,
    # the following arguments build the command to run
    res = docker_services.exec('crate', 'ls', '-a')

等待服务

服务模块的wait_for_service方法检查 Docker服务真的启动了。默认情况下,它向 服务器的/终结点。服务将重试检查,直到超时 30秒过去了。

自定义服务检查器

有些服务可能工作方式不同,需要自定义检查程序。

创建一个自定义服务检查器函数,该函数接收IP地址和 端口作为参数:

def custom_service_checker(ip_address, port):
    # if service is ready
    return True
    # otherwise return False

在fixture中提供自定义服务检查器函数check_servicewait_for_service方法的参数:

@pytest.fixture(scope='session')
def docker_custom_service(docker_services):
    docker_services.start('custom_service')
    public_port = docker_services.wait_for_service(
        "app",
        8080,
        check_service=custom_service_checker
    )
    url = "http://{docker_services.docker_ip}:{public_port}".format(**locals())
    return url

运行测试

测试保存在tests目录中。运行测试通过 pytest包,带有:

./gradlew pytest

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java log4j找不到log4jtest。房产?   我在java线程“awteventque1”中获得异常。lang.NullPointerException   java为什么在使用完整路径从文件系统读取文件时出错?   java如何迭代所有注册表项?   java中的安卓 Opencv SVM未正确训练   多线程Java ThreadPoolExecutor关闭特定线程?   如何使用Java NIO CreateDirectory方法设置目录所有者组?   java NatTable混合了固定宽度的列和可调整大小的填充剩余空间   java如何删除特定网络,即使该网络是由安卓上的其他设备创建的?   java Guava toJavaUtil()不存在   java对许多常量使用枚举是有效的memorywise?   java是否可以使用坐标定位JButton?   从WSDL生成java代码导致异常   java如何在安卓中导出javadoc   爬行JAX中的java NoClassDefFoundError错误   java为片段中的文本视图设置区域设置   发送最后一条消息后发生Java RMI RemoteException