Package: docker-services
Uses docker to spawn containers for services required during testsInstallThis project is available on pypi, so you can usepipto install it:pip install docker-servicesOr include it as a dependency onsetup.pyor arequirements.txtfile, whatever you prefer.Use it1. Configure your project servicesYou need to start listing all services that your project depends on and leverage ondocker-servicesto maintain the lifecycle of those services during test runs.This must happen using either thedocker_servicesconfig option on any pytest.cfg/.inifile or on a.services.yamlfile, the value for that option requires a yaml structure where top level members are the service names and their values can be either an empty value, image name or a or an object.Due to limitations of ini files, full support for yaml is not available on .cfg/.ini files, if you need complex config then usage of the.services.yamlfile is encouraged.This is a basic example for a project that depends on apostgresservice:[pytest]
docker_services=postgres:This is the same:[pytest]
docker_services=
    postgres:And this:[pytest]
docker_services=
    postgres: postgresAnd this too (on .services.yaml):postgres:image:postgresAnd guess what?... this too!database:name:postgresimage:postgresIf the projects depends different services, list all of them:[pytest]
docker_services=
    postgres:
    redis:When image name is not specified (and I bet you already noticed this) it falls back to use the service name as image name, but it is possible to specify the image name and version to use:[pytest]
docker_services=
    postgres: postgres:10Also this way:postgres:image:postgres:10Now the service name ispostgresand image name ispostgres:10.Another option is to use a different name for the service, something like:[pytest]
docker_services=
    db: postgres:10db:image:postgres:10Now service name isdband image name ispostgres:10.If you don't want (or need) to set a specific image version, just ignore the version part like this:[pytest]
docker_services=
    db: postgresAlso you are able to use images from a private registry:[pytest]
docker_services=
    db: my.registry.com/custom/postgres1.1. Configure environment variables for your servicesYou may want to customize the behaviour of your services by setting environment variables, it is also possible by adding to the config (valid only when using the.services.yamlfile).db:image:postgres:10environment:POSTGRES_USERNAME:myuserPOSTGRES_PASSWORD:$3cr3tPOSTGRES_DB:mydbUsing that config above thedbservice is now initialized withPOSTGRES_USERNAME,POSTGRES_PASSWORDandPOSTGRES_DBenvironment variables.Those variables are also exposed to the actual session, so you can consume those values from within your app or tests too.1.2. Configure dynamic variables tooAre you planning to configure aDATABASE_URLenvironment variable based on service's port number?... then don't wait and configure a variable template ;).Talking about theDATABASE_URLfor postgres one usually expects something likepostgres://user:password@host:port/dbname, and that can be achieved by replacingpostgres:image:postgres:10environment:POSTGRES_USERNAME:myuserPOSTGRES_PASSWORD:$3cr3tPOSTGRES_DB:mydb_templates:POSTGRES_PORT:"{env[POSTGRES_PORT_5432_TCP_PORT]}"DATABASE_URL:"postgres://myuser:$s3cr3t@localhost:{env[POSTGRES_PORT_5432_TCP_PORT]}/mydb"It is also possible to use environment variables defined for the service, so you don't repeat the same:DATABASE_URL: "postgres://{env[POSTGRES_USERNAME]}:{env[POSTGRES_PASSWORD]}@localhost:{env[POSTGRES_PORT_5432_TCP_PORT]}/{env[POSTGRES_DB]}"The parameters on the template are replaced using python's.format()method and at the moment onlyenvparameter is passed and it references actually to the content ofos.environ, so all environment variables are available.2. Run tests with docker-services enableddocker-servicesadds the--use-docker-servicescommand line option forpy.test, when setting this option it enables service's spawning using docker, run it like this:py.test --docker-services3. Communicate with the servicesWe spawn our services because we need to communicate with them during test sessions, either to consume data from or publish data to. For thatdocker_servicesrely on service's exposed ports to create unique environment variables for each port and protocol exposed on each of the services.The variable names follows the same conventions as in environment variables created fromlinks, but for now we only create the*_PORTenvironment variables, assuming docker is running on local machine and ports exposed to localhost.So, if we have apostgresservice we expect to communicate using port 5432, now looking at theDockerfilewe can confirm that itexposes port 5432.Please note thatdocker_servicescreates environment variables for exposed ports only, if service's image doesn't expose any port then no*_PORTvariable would be reated.For thepostgresservice use case, variable name for port5432would be:POSTGRES_PORT_5432_TCP_PORT, this variable name is built using this template:{service_name}_PORT_{port}_{protocol}_PORT.Also remember that environment variables configured for a service are also available within the context of the pytest session, this applies to both static and dynamic variables!