Testing Django Applications with Selenium
Selenium
Selenium is a very convenient (IMHO) tool for testing web applications.
Tests are created using the add-on for Firefox, which can generate test code in various languages, including Python. These tests are then performed by a dedicated server, Selenium RC.
Selenium itself is not tied to either languages or frameworks, so to integrate it into a testing system for Django applications, you need to make very little effort.
To solve the integration problem, I will use the Django: Sane Testing library. This is a library that extends the capabilities of the standard Django testing system, including support for Selenium tests.
We put Django: Sane Testing
Installing this library would be standard if it didn't drag Django along with it. What is not right if you use a trunk, like me.
Download the current release , unpack it (you can in / tmp), open setup.py, find either delete or comment on the part about Django. After that, put: sudo python setup.py install
install_requires = ['Django>=1.0_final','nose>=0.10'], <br/>
We put Selenium
You need to install the server and plugin for Firefox. Both are on the download page .
To install the plugin, just open the Selenium IDE link, enable the plugin installation, install it and restart Firefox. In addition, the respected bazzzman wrote an extension for this plugin (!) , For the convenience of work.
To install the server, you need to download the archive using the Selenium RC link, unpack it somewhere. In the resulting directory after unpacking there will be several subdirectories. Among them will be selenium-server-xyz, this is the directory with the server. The server itself is the selenium-server.jar file. Here we copy it somewhere, to a convenient place, for example, in / usr / local / lib, after which you can rub the entire unpacked directory, it is no longer needed.
For easy start creating the script,
sudo nano / usr / local / bin directory / selenium-server
with the following content:
# / bin directory / the bash!
/ Usr / bin directory / java -jar the env /usr/local/lib/selenium-server.jar
Asking him the right to execute:
sudo chmod 755 / usr / local / bin / selenium-server
Check: after the / usr / local / bin / selenium-server command is executed, something like this should appear: if it is, then the server is working OK.
23:58:17.788 INFO - Java: Sun Microsystems Inc. 14.2-b01
23:58:17.798 INFO - OS: Linux 2.6.31-14-generic i386
23:58:17.863 INFO - v1.0.1 [2696], with Core v@VERSION@ [@REVISION@]
23:58:18.111 INFO - Version Jetty/5.1.x
23:58:18.113 INFO - Started HttpContext[/selenium-server/driver,/selenium-server/driver]
23:58:18.114 INFO - Started HttpContext[/selenium-server,/selenium-server]
23:58:18.114 INFO - Started HttpContext[/,/]
23:58:18.166 INFO - Started SocketListener on 0.0.0.0:4444
23:58:18.166 INFO - Started org.mortbay.jetty.Server@fc9944
Test project
We create a test project:
django-admin.py startproject justtotest
There will be one application in the project, let's call it habrahabr:
./manage.py startapp habrahabr
Our test hub will consist of one model:
class Greeting (models.Model):
text = models.CharField (max_length = 200 ) of
one form for entering a greeting:
class GreetingForm (forms.ModelForm):
text = forms.CharField (widget = forms.TextInput (attrs = { 'size' : '40' }),
error_messages = { 'required' : 'And enter the welcome text?' })
Class Meta :
model = Greeting
and one view:
def Greetings (request):
template_name = 'habrahabr / index.html'
title = 'Selenium'
if request.method == 'GET' :
form = GreetingForm ()
else :
form = GreetingForm ( request.POST)
if form.is_valid ():
text = form.cleaned_data [ 'text' ]
new_greeting = Greeting (text = text)
new_greeting.save ()
return HttpResponseRedirect ( '/' )
greetings = Greeting.objects.all (). order_by ( '-id' )
context = {
'title' : title,
'greetings' : greetings,
'form' : form,
}
return render_to_response (template_name, context,
context_instance = RequestContext ( request))
which displays a list of greetings added previously and a form for adding a new greeting.
Creating a Selenium Test
Run the project and create a test in the browser using the plugin, watch the video (I advise you to watch it in HQ):
As you can see, we have a python code. From this generated code, we take the class file and modify it a bit to get this in our tests.py:
coding: utf-8
from djangosanetesting.selenium.driver import selenium
import unittest, time, re
class Untitled ( unittest .TestCase):
test_type = "selenium"
start_live_server = True
def setUp (self):
self .start_live_server = True
self .verificationErrors = []
self .selenium = selenium ( "localhost" , 4444 ,"* chrome" , " 127.0.0.1 : 8000 /" )
self .selenium.start ()
def test_required_text_exists (self):
sel = self .selenium
sel. open ( "/" )
sel. type ( "id_text" , "Testing with Selenium" )
sel.click (u "// input [@ value = 'Add']" )
sel.wait_for_page_to_load ( "30000" )
try : self .failUnless (sel.is_text_present ( " Testing with Selenium " ))
exceptAssertionError, e: self .verificationErrors.append ( str (e))
def tearDown (self):
self .selenium.stop ()
self .assertEqual ([], self .verificationErrors)
if __name__ == "__main__" :
unittest .main ()
We added two attributes to the class.
test_type
- indicates the type of test and start_live_server
- it indicates that it will be necessary to start the test server. In addition, there are other imports, after installing sane we already have everything in the installed package.
Scripts for running tests
There are two settings for running tests. The first option is to add a variable to settings.py
TEST_RUNNER
, but in this case it will not work to select individual types of tests, for example, only unit tests, or only selenium tests, and after all, you do not always need to run everything. Therefore, I chose the second option - I wrote scripts to run the tests. The first script, nose-selenium:
#! / Bin / bash
DJANGO_SETTINGS_MODULE = "settings" PYTHONPATH = ".: .." nosetests --with-django --with-djangoliveserver --with-sanetestselection - select -seleniumtests;
this script will run selenium tests with a test server.
Second script, nose-unittests:
#! / Bin / bash
DJANGO_SETTINGS_MODULE ="Settings" PYTHONPATH = ".: .." nosetests --with-django --with-sanetestselection - select -unittests;
this script will run unit tests, without a test server.
You can make the necessary scripts for all occasions, all types of tests are listed in the documentation . Do not forget to set the permissions to perform scripts
chmod 755
.Running tests
Now you are ready to run the tests. You need to start the Selenium server, / usr / local / bin / selenium-server, after which you can run the tests using scripts.
I did not do a screencast, but be sure that everything works OK - the browser starts, contacts the server, fills out a form, checks for text, the results are displayed as usual.
I posted the code for the article on Yandex , if the file disappears from there, write in a personal.
Summary
In my opinion, selenium is a good addition to the test system, because allows you to test javascript-rich interfaces, which the standard test system can not do. In addition, Django: Sane Testing itself offers additional features, which I advise you to read in the documentation .
I hope my article will be useful for a wide range of Django developers, both beginners and experienced. From experienced developers waiting for comments on the topic :-)
PS
Windmill did not try. If it is easier \ better \ more reliable than Selenium, please describe in the comments or as an article. I will put the link to the article at the beginning of this.