Tag Archives: testing

Setup multiple scenarios for e2e testing on django with django-remote-scenario

When we are testing an application (blackbox), either manually or on an automated fashion, often have the need to create different sets of data, for the different scenarios of each feature we want to test (Checkout this link: http://dannorth.net/introducing-bdd/). That is where django-remote-scenario comes to the rescue!.

I wrote this tool, because I needed to do e2e testing for an Angular application with a Django backend. I needed to create different sets of data, so a third party application could retrieve each one of them, via REST services at will. The idea is simple, create a "scenario file" for each scenario you want to test,and django remote scenario will translate it into an URL that can be remotely call to load the data into the database, and be ready to be consume.

Quickstart

Install django-remote-scenario::

pip install django-remote-scenario

Then add it to an exsiting django project::

INSTALLED_APPS = [
...
django_rs

You need add django_rs urls to your project url file like this::

urlpatterns = patterns('',
...
url(r'^drs/', include('django_rs.urls')),
..
)

To create custom scenarios, just create a directory inside your app named "scenarios" , then add as many files as scenarios you want to implement and create a init.py file to import them. Inside each of those files, you need to implement a main() function setting up the models you want to create for the scenario, you could create them by hand or use something like django_dynamic_fixtures.

Note: Your scenario is not limited to creating new models, you may also mock specific parts of the enviroment as well

Once everything is ready, start the server this way, this will enable the dynamic call of scenarios::

python manage.py rune2eserver initial_data.json

Note: You need to pass a initial fixture file with the barebones of your data.

It is also possible to pass a specific settings file, for testing purposes, in case you want to do the tests using a different database for example::

python manage.py rune2eserver initial_data.json --settings=demoproject.test_settings

To start using it, just go to the following url:

http://127.0.0.1:8000/drs/[APPLICATION]/[SCENARIO]

after doing that the database will be populated with the data you provided in your scenario. Take into account that, everytime you call an scenario, all the other data in the database is erased, except for the one in your initial_data fixture files, wich are loaded again, and also the one you pass as a parameter when you call the command.

Inside this repository you will find a demo Django project preconfigured with a simple scenario that sets up four objects. Use it like this:

First run the server:

$ python manage.py rune2eserver initial_data.json --settings=demoproject.test_settings

Then go to your browser and setup a scenario:

http://127.0.0.1:8000/drs/demoapp/scenario_1

You may also pass a parameter to avoid flushing the database on a specific call:

http://127.0.0.1:8000/drs/demoapp/scenario_1/?flush=0

Later you could see the results on the following url::

http://127.0.0.1:8000/demoapp/

E2E tests with django-casper

We often need to test our "javascript rich" Django application and the infamous TestClient provided with Django is not enough on this cases. Here is when django-casper comes to the rescue

First a brief introduction. Javascript has a great package named PhantomJs. PhantomJs is a headless webkit browser (yeap no need to open FF/Chrome for testing ala selenium!). CasperJS is a library on top of that to ease the testing from CasperJS website:

CasperJS is an open source navigation scripting &testing utility written in >Javascript for the PhantomJS WebKit headless browser and SlimerJS (Gecko).It >eases the process of defining a full navigationscenario and provides useful >high-level functions,methods & syntactic sugar for doing common tasks such as:

  • defining & ordering browsing navigation steps
  • filling & submitting forms
  • clicking & following links
  • capturing screenshots of a page (or part of it)
  • testing remote DOM
  • logging events
  • downloading resources, including binary ones
  • writing functional test suites, saving results as JUnit XML
  • scraping Web contents

django-casper is a sort of wrapper for casperjs, allowing us to run javacript/casper tests from Django's built-in test command, this is great, not only to facilitate the development process, but to take advantage of Django's own test runner to create mocks, stubs, fixtures, etc. for our front end testing.

Installation:

We will need a running python and node instance with django and casperjs installed respectively. If you don't have it already on your box here is a quick howto for GNU/Linux

Node

Install nvm

$ curl https://raw.github.com/creationix/nvm/v0.4.0/install.sh | sh

From nvm, install latest node version

$ nvm install latest

then open a new terminal or source ~/.zshrc or ~/.bashrc or whatever rc file for the shell you are using

Create virtualenv

Create a new virtualenv instance if you don't have virtualenv installed please refer to the official documentation http://virtualenv.readthedocs.org/en/latest/virtualenv.html Note: You can skip this step and install Django globally, but is not recommended

$ virtualenv django-casper && source django-casper/bin/activate

Now we are ready to install casperjs and django

Installing django

$ pip install django

Installing casperjs

$ npm install -g casperjs

Installing django-casper

It is possible to install django-casper from pip (pip install django-casper), but we are going to use the following method, in order to get the example code for tests.

$ git clone git@github.com:dobarkod/django-casper.git $ cd django-casper $ python setup.py install

Using it

Django-casper comes with a testproject that implements some test tests.

$ cd testproject $ python manage.py test testapp

This should run all the test included in the application.

Where are my tests?!!

Tests are divided in two parts, the django part where the backend stuff is prepared (fixture, backend mocks, etc) and the casper part where the actual tests are written. Lets see an example:

$ vim testapp/tests.py

from casper.tests import CasperTestCase
import os.path

from django.contrib.auth.models import User


class CasperTestTestCase(CasperTestCase):

    def test_that_casper_integration_works(self):
        self.assertTrue(self.casper(
            os.path.join(os.path.dirname(__file__),
            'casper-tests/test.js')))

On this file we have one test that in turn calls the casper library passing the test casper should run on this case casper-tests/test.js. Inside this django test, we could add new data to the database, and test the result on the casper-tests/test.js test.

Lets see the content of the casper-tests/test.js test file

 casper.test.comment('Casper+Django integration example');
 var helper = require('../../../casper/jslib/djangocasper.js');

 helper.scenario('/',
function() {
   this.test.assertSelectorHasText('em', 'django-casper',
 "There's a mention of django-casper on the page");
},
function() {
  this.click('a');
   this.test.assertSelectorHasText('#messages p', 'Good times!',
 "When the link is clicked, a message is added to the page");
}
 );

helper.run();

We can observe, that the test is opening the root "/" page (helper.scenario('/'.... ), and then asserting the content of the page on the first function. The second function, clicks on a link on the page, and asserts that a message is added to the page.

These are basic tests, I encourage you to give it a try. Also take a look a Django dynamic fixture, a library to create dynamic test data for your django tests.

Happy Testing!

Useful links

django-casper: https://github.com/dobarkod/django-casper

django-dynamic-fixture: https://github.com/paulocheque/django-dynamic-fixture

casperjs: http://casperjs.org/

virtualenv: http://www.virtualenv.org/en/latest/

nvm: https://github.com/creationix/nvm