Introduction
At the moment, the most popular solution for client testing is selenium. It is worth noting that it is well deserved - those opportunities provided by selenium in conjunction with the webdriver, really cover almost the entire spectrum of user interaction with web applications.
For small projects, the option with plug-ins for browsers, the functionality of which can be expanded by adding third-party components (for example,
UI-element ), is great. But when the project becomes large enough, and many of its parts change many times and even completely sawn through, after each change in the structure of the page or the way the data is presented, you have to replace entire blocks of tests at once, looking almost at every test. After such a selenium, plug-ins no longer seem so convenient. And here come the selenium libraries, implemented for many languages ​​associated with web development (
documentation on the official site)
I suggest you look at the client testing capabilities (in particular, django projects) that python-selenium provides in conjunction with the lettuce library.
')
Lettuce + Selenium
Let's take a look at the capabilities that these components provide separately:
Python-Selenium- as mentioned above, selenium has a rich arsenal of interaction with web applications through a browser
- Unlike plugins, it is possible to use extensive python functionality.
- integration with the project itself
Lettuce- separation of tests into loosely coupled parts
- control over each stage of testing
- beautiful output in the terminal :)
And immediately into battle
Using the example of simple registration and authorization tests, I will try to demonstrate the main aspects of working with lettuce + selenium.
Formulation of the problemYou need to create 2 tests that will perform the following actions:
Check in:
- Enter the registration page
- Fill in the fields in the registration form
- Click on the registration button
- See the message about successful registration
Authorization:
- Enter the login page
- Fill in the fields in the authorization form
- Click on the authorization button
- See successful login message
Already from the formulation of the problem it is clear that these 2 tests perform similar actions, but in a different context. We proceed to the task.
Task performanceBy adding lettuce to our django project, as described in the
official documentation , and installing all the necessary dependencies (in our case, these are the firefox system packages and the Python-based modules lettuce and selenium), you can start writing tests.
PS: to run in headless mode, you will need xvfb and pyvirtualdisplay
To work with lettuce you need to create the following files:
- terrain.py in the root of the project contains instructions that are executed at this stage of testing.
- * .feature files in myapp / features folder contains a step-by-step description of each test.
- * .py files in myapp / features folder contain descriptions of steps used in * .feature files
From myself I can advise you to include in the project a file containing the structure of the pages of your application (by analogy with the PageObject used in selenium). Let's call this file
mapping.py and put it in the root of the project. This separation of the structure of the pages from the tests reduces the need for rewriting the tests themselves when changing the layout: it is enough to fix the corresponding page in mapping.py. It also significantly increases the readability of tests (further it will be clearly shown).
mapping.py
host_url = 'http://example.com' site_mapping = { "registration": { "url": host_url + "/registration/", "username": "//input[@id='username']", "email": "//input[@id='email']", "password": "//input[@name='password1']", "verify password": "//input[@name='password2']", "signup button": "//button[@name='signup']", "status message": "//div[@id='status']", }, "authorization": { "url": host_url + "/login/", "username": "//input[@id='username']", "password": "//input[@name='password']", "login button": "//button[@name='login']", "status message": "//div[@id='status']", }, }
PS: I use xpath, because I think this is the best way to find items
terrain.py
from lettuce import before, after, world from selenium import webdriver from mapping import site_mapping @before.harvest def setup(server):
myapp / features / auth.feature
Feature: Authorization Scenario: Registration Open "registration" page Fill "username" with "myusername" Fill "email" with "user@example.com" Fill "password" with "1234" Fill "verify password" with "1234" Click "signup button" See "Welcome aboard" in "status message" Scenario: Authorization Open "authorization" page Fill "username" with "myusername" Fill "password" with "1234" Click "login button" See "Hello! Again..." in "status message"
As you can see, the lack of information about the location of elements played a role in the readability of the scripts. Thanks mapping.py for this
myapp / features / steps.py
from lettuce import step, world @step(r'Open "(.*)" page') def open_page(step, page): world.current_page = world.mapping[page]
That's all. It remains only to run the tests and see how they successfully (or not) pass.
It seems that there are too many gestures for writing some two tests - that is. But if you want to cover the project with a large number of tests, then as you write scripts and steps to them, you will have less and less need to write new steps, because almost all possible user interaction with your site will already be described in the existing steps - all that remains is to write new scenarios, which is no more difficult than writing the “problem statement” item a little higher.
Total
What we have in the rest:
- A tool that can be used by both developers and testers.
- High resistance to changes in the layout and structure of the site as a whole thanks to mapping.py
- You can run tests in almost anything. Firefox, chrome, phantomjs (maybe there are other options, but this is what I tried).
- Run tests anywhere: on your computer, on a virtual machine, on a remote server
- For each test run, you can create a test database, include a separate instance of your application, load test data, and at the end, safely remove all of this (as does the test framework in django itself).
- You can attach saving logs. And if asynchronous tasks are timed for this, then it is possible to receive information about the status of the entire project every N hours.
- With a large base of steps (steps.py), it will suffice to describe only the scenarios, which are quite simple to write “translating” TK into them.
- Deploying such tests on one project will not be difficult to transfer them to another project. When transferring to a new project, writing scripts will take the most time, which doesn’t seem so difficult (compared to, for example, creating the next hundred tests in the selenium plugins)
Useful links on the topic:
PS: I hope that someone will be interested in this topic and it will be reasonable to write about the pitfalls that I encountered using lettuce + selenium. I will be glad to answer your questions.
PPS: I apologize in advance for the writing style, punctuation and in general. The first article and all that ...