All those who use Selenium tests in their build, know that it is quite expensive, because it is very slow. Because of this, many do not run the build completely before commits, or, in general, run the build only at night. So, we do our tests faster.
Disable native events
The approximate essence of native events is: when a test stumbles upon a string
driver.findElement(By.id(“someId”)).sendKeys(“hello”);
then some kind of an event like “Enter the word 'hello'” into the field with those coordinates. The coordinates are calculated somehow by themselves and it looks as if the user is slowly typing text from the keyboard. The problem is that it spends an enormous amount of time, and we do not need it.
To disable this feature, you need to launch Firefox with a pre-configured profile:
private WebDriver firefox() { final FirefoxProfile profile = new FirefoxProfile(); profile.setEnableNativeEvents(false); return new FirefoxDriver(profile); }
That's how we got a fast driver.
If you have a ready-made profile for running tests, you can create a user.js file in it:
user_pref("webdriver_enable_native_events", false);
Or slightly change the method of creating a driver
private WebDriver firefox(final String profileName) { final FirefoxProfile profile = new ProfilesIni().getProfile(profileName); profile.setEnableNativeEvents(false); return new FirefoxDriver(profile); }
Disable animation
The animation on the site is, of course, a thing, but during tests it is evil. You have to constantly wait for this animation to end, insert some crutches, etc. And yes, the animation itself eats up part of the test time. In general, disable the animation on the example of jQuery
private WebDriver initDriver() { final WebDriver wrappedDriver = firefox(); final EventFiringWebDriver driver = new EventFiringWebDriver(wrappedDriver); driver.register(new AbstractWebDriverEventListener() { @Override public void afterNavigateTo(final String url, final WebDriver driver) { ((JavascriptExecutor) driver).executeScript("jQuery.fx.off = true;"); }
We continue to work with an EventFiringWebDriver instance. In the example, I only redefined the afterNavigateTo () method, which is called automatically after each call to driver.get (someUrl). In real life, this is clearly not enough. For example, a test presses a button and an automatic redirect to another page takes place. In this case, the afterNavigateTo () call will not occur, so you have to redefine additionally beforeClickOn () to turn off the animation when you first click on any element after loading a new page.
We run tests in parallel mode
Initially, I looked towards the Selenium Grid, but I even didn’t manage to start the demk, and in general the grid didn’t seem very convenient to me: I had to start the hub and the server. Therefore, we run tests in two or more browsers using Maven and TestNG.
Add to pom.xml
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.8.1</version> <executions> <execution> <id>run-integration-tests</id> <phase>integration-test</phase> <goals> <goal>test</goal> </goals> <configuration> <groups>integration</groups> <parallel>classes</parallel> <threadCount>2</threadCount> </configuration> </execution> </executions> </plugin>
If you inject threading non-secure instances with scope = "singleton" into tests, then you need to change to scope = "prototype". At best, at this stage, you can only get rid of the configuration of configs (for example, Spring). If each of your tests uses a unique username for the login, then everything should work from a half-kick.
Results
Previously, in the project I was working on, the execution of Selenium tests took about 5 minutes, now it is 1.5 minutes.
')
For reference
All the above steps were performed on Java + Selenium 2.8.0 + Maven + TestNG + Firefox 7.0.1 + Spring