TeamCity run pytest in a docker-compose environment

Viewed 569

I have a question regarding a build configuration in teamcity

We are developing a python (flask) rest api where a sql database holds the data. Flask server and postgresql server each runs in a docker container. Our repository contains a docker-compose file which starts all necesary containers.

Now I want to set up a build configuration in TeamCity where the repository is pulled, containers are build and then the docker-compose file should be up and all test functions (pytest) in my flask-python application should be run. I want to get the test report and the docker-compose down command should be run.

My first approach using a command line build configuration step and issuing the commands works, but i don't get the test reports. I not even getting the correct exit code (test fails, but build configuration marked as success)

Can you give me a hint what would be the best strategie to do this task. Building, Testing, Deploying a application which is build out of multiple docker containers (i.e. a docker-compose file)

Thanks Jakob

1 Answers

I'm working with a similar configuration: a FastAPI application that uses Firebase Emulator suite to run pytest cases agains. Perhaps you will find these build steps suitable for your needs too. I get both test reports and coverage using all the built-in runners.

Reading the TeamCity On-Premise documentation, I found that running a build step command within a docker container will pick up TEAMCITY_DOCKER_NETWORK env var if previous steps ran docker-compose. This variable is then passed to your build step that runs in docker via --network flag, allowing you to communicate with services started in docker-compose.yml.

Three steps are required to get this working (please ignore numbering in the screenshots, I also have other steps configured):

  1. Using Docker runner, build your container where you will run pytest. Here I'm using the %build-counter% to give it a unique tag.

enter image description here

  1. Using Docker Compose runner, bring up other services that your tests rely on (postgresql service in your case). I am using teamcity-services.yml here because docker-compose.yml is already used by my team for local development.

enter image description here

  1. Using Python runner, run Pytest within your container that was build in step 1. I use suggested teamcity-messages and coverage.py, which get installed using pip install inside the container before executing pytest. My container already has pytest installed, if you look through "Show advanced options" there's a checkbox that will let you "Autoinstall the tool on command run" but I haven't tried it out.

enter image description here

Contents of my teamcity-services.yml, exposing endpoints that my app uses when running pytest.

version: "3"

services:
  firebase-emulator:
    image: my-firebase-emulator:0.1.13
    expose:
      - "9099" # auth
      - "8080" # firestore
      - "9000" # realtime database
    command: ./emulate.sh -o auth,firestore,database

A hypothetical app/tests/test_auth.py run by pytest, which connects to my auth endpoint on firebase-emulator:9099. Notice how I am using the service name defined in teamcity-service.yml and an exposed port.

def test_auth_connect(fb):
    auth = fb.auth.connect("firebase-emulator:9099")
    assert auth.connected

In my actual application, instead of hardcoding the hostname/port, I pass them as environment variables which can also be defined using TeamCity "Parameters" page in the build configuration.

Related