Django and Selenium Integration



    Hello.

    It's no secret that application testing is an important step in software development, and if you are developing web applications, then you just need to test the web interface. Fortunately, a tool like Selenium exists for this purpose . The well-known companies SKB Kontur and Yandex have already chosen it as a tool for functional testing of their applications and services (Yandex talked about this at the recent YaC).

    Now to the point.
    In one of the projects I'm working on, we used Selenium starting from the first branch. But time does not stand still, released Selenium 2.0, based on webdriver technology, more functional, convenient, and correctly imitating events in the browser ( more about the benefits ).

    In order not to update the old Selenium support code inside our application (what if it will have to be done more than once?), And also to try to do something useful for other developers, we decided to immediately integrate Selenium into a separate library.

    Next, I will describe what we did and how to use this library.

    Installation


    The library can be taken from https://github.com/dragoon/django-selenium or installed via pip:
    pip install django-selenium

    Opportunities


    First of all, the library allows you to integrate with the django testing subsystem . You can either simply specify in the settings to use TestRunner from the library:
    TEST_RUNNER = 'django_selenium.selenium_runner.SeleniumTestRunner'
    or inherit it and write your own class.
    Behind the scenes, SeleniumTestRunner does the following:
    • starts selenium-server.jar server
    • launches a test server instance with test fixtures
    Next, to start writing Selenium tests, you need to create the seltests.py file in the application , similar to the usual tests.py . Then you simply inherit the test class from django_selenium.testcases.SeleniumTestCase and write tests using Selenium commands to interact with the browser.

    Standard Driver Extension

    To facilitate the performance of standard operations, an extended driver class has been written that interacts with the browser - django_selenium.testcases.MyDriver . It contains operations such as opening a url, logging in to the site (the standard form of django), finding an element using the css selector, finding an element and clicking, check the presence of text on the page, receive alert text and others. For details, please refer to the source code of the MyDriver class for now .

    Replacing the test run command

    Finally, to replace the standard django test execution command with a command that supports selenium tests, you need to inherit the command class somewhere in your application as follows:
    from django_selenium.management.commands import test_selenium
    class Command(test_selenium.Command):
        def handle(self, *test_labels, **options):
            super(Command, self).handle(*test_labels, **options)
    The command supports two additional options:
    • --selenium - run all tests, including Selenium tests
    • --selenium-only - run only Selenium tests
    As in the case of the standard command, you can run Selenium tests for a specific application or only a specific test from the application.

    Test application


    To consolidate the above, I prepared a small django application containing one selenium test:
    
    # Скачиваем selenium-server.jar
    wget http://selenium.googlecode.com/files/selenium-server-standalone-2.7.0.jar
    git clone git://github.com/dragoon/django-selenium-testapp.git
    cd django-selenium-testapp
    # Установить правильный путь в переменную SELENIUM_PATH
    vi settings.py
    # Запускаем тесты
    ./manage.py test --selenium-only
    ...
    ----------------------------------------------------------------------
    Ran 1 test in 13.254s
    OK
    

    If everything went right, the following picture should be observed:


    As always, I will be glad to hear comments and suggestions for further refinement, opinions on how useful this library is, and of course I will be happy for any further refinement from other githubbers.

    Thanks for attention.

    Also popular now: