techgeek.biz being a geek is fun

[ Home ] [ Tech Tips ] [ Getting Started ] [ Contact ] [ About ]  
Django testing and docker

Django unit tests & functional tests in docker! No luck with Jenkins for me

 

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

 

1. Want to start creating files in your parent directory of your django folder

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

 

2 .You will need to make a folder called mkdir ./tests

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

 

3. A new ./docker-compose.yml file

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:[email protected]: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

4. Write a test!   

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')

 

5. unit test ==

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)

 

 

6. docker-compose up!

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

7. Watch on vnc viewer, if you like....         

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

 

8. Re run test on demand

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.. 

 

 

 

 

 

Luke Keam

Luke Keam

Thank you for reading.

Any questions, comments or suggestions
Email [email protected]

Have a great day from

Luke Keam 
techgeek.biz 
 

AD


                   

        

FOLLOW US

youtubemail

AD