Git is the most popular version control software right now, and will be for a long time. The git workflow is branch based. What that means, is that you can experimenting with ideas, by open up a new branch and you can easily discard the changes, if you aren't satisfied with it. On the other hand, if your branch proves to be successful you can “merge” it into the “master”. This structure lets you control the versions of your program to a great extent. Combine this methodology with unit testing and you can make no mistake.
Let's dive in! If you haven't done the earlier tutorial I have “How to start a Django application”, you can clone my repository from github:
mkdir -p DjangoTutorial/{static,virtualenv,source,database,media}
virtualenv --python=python3 DjangoTutorial/virtualenv/
git clone <a href="https://github.com/fozodavid/DjangoTutorial.git">https://github.com/fozodavid/DjangoTutorial.git</a> --branch exercise1 --single-branch DjangoTutorial/source
cd DjangoTutorial/source
touch MyTutorial/local_settings.py
***MyTutorial/local_settings.py***
import os
from MyTutorial.settings import BASE_DIR
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'rf@7y-$2a41o+4&z$ki0&=z)(ao=@+$fseu1f3*f=25b6xtnx$'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR,'..','database','db.sqlite3'),
}
}
*** end of MyTutorial/local_settings.py ***
git branch -m exercise1 master
source ../virtualenv/bin/activate
pip install -r requirements.txt
If you come from earlier tutorial, just cd into the source directory and put into the terminal:
git checkout -b app
git branch
Should see this:
* app
master
That creates a new branch and you make changes without affecting the master. Activate virtualenv (if you haven't already) and let's create a new application then:
source ../virtualenv/bin/activate
python3 manage.py startapp main
ls
Should see:
main manage.py MyTutorial
Our apps have their own directory in Django. In order for django to recognize them, you need to put them into the INSTALLED_APPS in MyTutorial/settings.py
***MyTutorial/settings.py***
...
INSTALLED_APPS = ['main',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
...
Now, we initiate our testing capabilities. Remember testing and version control goes hand in hand. In a collaborative effort with other developers, they will only allow you to provide code with passing unit tests.
We only do some “smoketest” which will gives you the feedback if our unit test systems are working or not.
*** main/tests.py***
from django.test import TestCase
class SmokeTest(TestCase):
def test_wrong_results(self):
self.assertEqual(1 + 1, 3)
Try it out with the following command:
python3 manage.py test
It should fail as expected:
Creating test database for alias 'default'...
F
======================================================================
FAIL: test_wrong_results (MyTutorial.tests.SmokeTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/david/Tutorial/source/MyTutorial/tests.py", line 5, in test_wrong_results
self.assertEqual(1 + 1, 3)
AssertionError: 2 != 3
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
Destroying test database for alias 'default'...
Well, everything goes to plan, now it's a good time to do a git commit. Commit means that you want the changes you made to be saved.
First let's see what you have done so far with git status:
git status
Should see:
On branch app
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: MyTutorial/settings.py
Untracked files:
(use "git add <file>..." to include in what will be committed)
main/
no changes added to commit (use "git add" and/or "git commit -a")
Before you can save(commit), you need to review and select the files for change. We are happy with all developments, so we 'add' all files.
git add .
When you commit, you also need to provide a “commit message”. That way, you can review later what you have done. This provides you with a nice commented history of your work.
git commit -m “main application created, smoketest expected failure”
Once we committed our changes it's time to do some real unit test. Change the main/test.py file accordingly:
***main/tests.py***
from django.core.urlresolvers import resolve
from django.test import TestCase
from main.views import home
class HomePageTest(TestCase):
def test_root_resolves_to_home(self):
root = resolve('/')
self.assertEqual(root.func,home)
Now, it's time to run the test:
python3 manage.py test
But we have an error:
Creating test database for alias 'default'...
E
======================================================================
ERROR: main.tests (unittest.loader.ModuleImportFailure)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.4/unittest/case.py", line 58, in testPartExecutor
yield
File "/usr/lib/python3.4/unittest/case.py", line 577, in run
testMethod()
File "/usr/lib/python3.4/unittest/loader.py", line 32, in testFailure
raise exception
ImportError: Failed to import test module: main.tests
Traceback (most recent call last):
File "/usr/lib/python3.4/unittest/loader.py", line 312, in _find_tests
module = self._get_module_from_name(name)
File "/usr/lib/python3.4/unittest/loader.py", line 290, in _get_module_from_name
__import__(name)
File "/home/david/Tutorial/source/main/tests.py", line 3, in <module>
from main.views import home
ImportError: cannot import name 'home'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
Destroying test database for alias 'default'...
Error means, that we couldn't even run the test, because there is some bigger bug in the software. If you read carefully the output, you see that the cause of error was “ImportError”. Could not this function named “home”. Well, this f