I spent 2 days trying to get Jenkins working with my django project and just was running into problem after problem and decided. Why cant we do this in docker? and what do we really need?
This is a basic docoker-compose / Dockerfile that sets up an environment to
Unit test
Coverage
Functional tests
I might put this up on github, it is running on local dev environment for myself
Create a ./Dockerfile
FROM python:3
# Install Python and Package Libraries
RUN apt-get update
RUN apt-get install -y \
virtualenv \
python3-pip \
python3-venv
with a file called ./tests/dockerfile_requirements.txt with below in, the top two are from your own pip freeze
# copy requirements from project Django pytz # testing requirements selenium asgiref >= 3.2.10 argon2-cffi >= 16.1.0 bcrypt docutils geoip2 jinja2 >= 2.9.2 numpy Pillow >= 6.2.0 # pylibmc/libmemcached can't be built on Windows. # pylibmc; sys.platform != 'win32' python-memcached >= 1.59 pywatchman; sys.platform != 'win32' PyYAML tblib >= 1.5.0 coverage
In you parent directory, you will need to edit for your curret setup. fyi this is another site of mine https://quick-time-management.com
Eg. I have this setup for my local folders
Also i left commented code in there for some mysql
version: "3"
services:
django:
container_name: django_tests
build:
context: .
dockerfile: Dockerfile
volumes:
- ./:/var/www # takes your local volumes ./ and adds it to container at /var/www
- /var/testing_venv:/var/testing_venv
command: >
bash -c "
python3 -m venv /var/testing_venv &&
source /var/testing_venv/bin/activate &&
python3 -m pip install --upgrade pip &&
pip3 install -r /var/www/tests/dockerfile_requirements.txt &&
cd /var/www/quick-time-management.com/django_project &&
coverage run manage.py test &> /var/www/tests/unit_tests.txt &&
coverage report > /var/www/tests/coverage.txt &&
source /var/testing_venv/bin/activate &&
nohup python3 /var/www/quick-time-management.com/django_project/functional_tests.py &> /var/www/tests/functional_tests.txt & sleep 20 &&
echo 'done' &&
source /var/testing_venv/bin/activate &&
cd /var/www/quick-time-management.com/django_project &&
python3 manage.py runserver 0.0.0.0:9000
"
# python3 manage.py test > /var/www/tests/unit_test.txt &&
# coverage html > /var/www/tests/coverage.html
depends_on:
- selenium_hub
ports:
- 9000:9000
#links:
# - db
#environment:
# - DATABASE_URL=mysql://root:itsasecret@db:3306/docker_tutorial_django_db
#db:
#container_name: mysql_database
#image: mysql/mysql-server
#ports:
# - "3306:3306"
#environment:
# - MYSQL_ROOT_PASSWORD=itsasecret
#volumes:
# - /Users/work/Development/data/mysql:/var/lib/mysql
selenium_hub:
container_name: selenium_hub
image: selenium/hub
ports:
- "4444:4444"
selenium_chrome:
container_name: selenium_chrome
image: selenium/node-chrome-debug
environment:
- HUB_PORT_4444_TCP_ADDR=selenium_hub
- HUB_PORT_4444_TCP_PORT=4444
ports:
- "5900:5900"
depends_on:
- selenium_hub
selenium_firefox:
container_name: selenium_firefox
image: selenium/node-firefox-debug
environment:
- HUB_PORT_4444_TCP_ADDR=selenium_hub
- HUB_PORT_4444_TCP_PORT=4444
ports:
- "5901:5900"
depends_on:
- selenium_hub
volumes:
.:
driver: local
Make a test in the same location as you put in your docker-compose
"nohup python3 /var/www/quick-time-management.com/django_project/functional_tests.py &> /var/www/tests/functional_tests.txt & sleep 20 &&"
import unittest from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities class SeleniumTest(unittest.TestCase): def setUp(self): self.chrome = webdriver.Remote( command_executor='http://selenium_hub:4444/wd/hub', desired_capabilities=DesiredCapabilities.CHROME ) self.chrome.implicitly_wait(5) def tearDown(self): self.chrome.quit() # self.firefox.quit() def test_login(self): self.chrome.get('http://django:9000/login') self.assertIn(self.chrome.title, 'Quick-Time-Management') self.chrome.close() def test_about(self): self.chrome.get('http://django:9000/about') self.assertIn(self.chrome.title, 'Quick-Time-Management')
same as the previous one, you should have a unit test describe in your docker compose file
"cd /var/www/quick-time-management.com/django_project &&
coverage run manage.py test &> /var/www/tests/unit_tests.txt &&"
Heres a basic unit test
from django.test import TestCase, Client from django.urls import resolve from .views import *
class LoginTest(TestCase): def test_page_login(self): response = self.client.get('/login/') self.assertEqual(response.status_code, 200)
Lets fire it up and see if it works! Hope fully it does and its all sharp and shiny.
It will take some time the first run as it needs to "build" the image and download it
Fire up vnc viewer and go to localhost:5900 for chrome and localhost:5901 for firefox and the super secret password is..... 'secret'
I know what your going to say... that is super dooper secret
By this stage you should have everything working just sweet as sugar and even getting some output into ./tests
using docker-compose up and docker-compose down
I can hear it in my head already. "But Luke this is all well and good but I dont want to docker-compose up and down everytime to run one blooming test!" and I would agree...
While docker-compose is up
docker exec -it django_tests /bin/bash -c "source /var/testing_venv/bin/activate ; python3 /var/www/quick-time-management.com/django_project/functional_tests.py &> /var/www/tests/functional_tests.txt" docker exec -it django_tests /bin/bash -c "source /var/testing_venv/bin/activate ; cd /var/www/quick-time-management.com/django_project ; coverage run manage.py test &> /var/www/tests/unit_tests.txt"
Sweet as sugar... no?
Hit me up via email for comments, ideas suggestions..