What is the best practice for combining Docker with Python unit tests?

Viewed 380

My Python project is deployed as a container, and also has unit tests. For Docker best-practice, the final image is supposed to exclude any dependencies that are only used for testing (like pytest for example). How should I exclude test dependencies while still running the tests?

One issue is that if I build my test environment independently from my deployment image, then those two environments may end up containing different versions of sub-dependencies. (Hypothetically if my project uses rasterio, and rasterio and pytest both use attrs, then installing pytest could alter which version of attrs is installed by the package manager. This suggests a bug could appear in the deployment image, without being present in the test environment.) If test dependencies are included in the final image, then the CI can be set up with successive steps like docker-compose build, docker-compose up -d and docker-compose exec myimage pytest. If testing dependencies are not present in the final container environment, how should the CI workflow be arranged? (E.g., if I used a multi-stage docker build and ran unit tests before the second stage, would I need to manually maintain a list of sub-dependencies to carry into the final stage?)

1 Answers

How to configure docker
gist
How to use configuration

# no dev-packages
docker build -t release .
# dev-packages + test config
docker build -t test-image --target=test .
# dev-packages + release config
docker build -t dev-image --build-args APP_ENV=dev .

How to get requirements.txt and requirements-dev.txt
Use pipenv or poetry to manage general and develop packages. Example with pipenv:

pipenv install django 
pipenv install --dev pytest
pipenv lock -r > requirements.txt
pipenv lock -r --dev > requirements-dev.txt

Details in pipenv and poetry docs
Source of knowledge: link

Related