Pull to refresh

Ускоряем Selenium-тесты

Reading time 3 min
Views 26K
Все, кто использует Selenium тесты в своём билде, знают, что это достаточно дорогое удовольствие, потому что очень медленно. Из-за этого многие не запускают билд полностью перед коммитами или, вообще, запускают билд только по ночам. Итак, делаем наши тесты быстрее.

Отключаем native events


Примерная суть native events такова: когда тест натыкается на строку
driver.findElement(By.id(“someId”)).sendKeys(“hello”);
то операционке отправлятся некое событие типа “Введи в поле вооон с теми координатами слово ‘hello’”. Координаты расчитываются как-то сами собой и всё выглядит так, будто пользователь медленно вводит текст с клавиатуры. Проблема в том, что это затрачивает колоссальное количество времени, а нам это не надо.
Чтобы отключить эту фишку надо запускать Firefox с предварительно настроенным профайлом:

private WebDriver firefox() {
    final FirefoxProfile profile = new FirefoxProfile();
    profile.setEnableNativeEvents(false);
    return new FirefoxDriver(profile);
}

Вот так мы получили быстрый драйвер.
Если у Вас есть уже готовый профайл для запуска тестов, то можно создать в нём файл user.js:
user_pref("webdriver_enable_native_events", false);

Либо немного поменять метод создания драйвера

private WebDriver firefox(final String profileName) {
    final FirefoxProfile profile = new ProfilesIni().getProfile(profileName);
    profile.setEnableNativeEvents(false);
    return new FirefoxDriver(profile);
}

Отключаем анимацию


Анимация на сайте — это, конечно, вещь, но во время тестов — это зло. Приходится постоянно ждать, когда эта анимация закончится, вставлять какие-то костыли и т.д. И да, анимация сама по-себе съедает часть времени теста. Вообщем, отключаем анимацию на примере 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;");
            }
            // скорее всего переопределения одного метода не хватит
            // так что переопределяем тут всякие beforeClickOn, afterNavigateBack и т.д. 
        }
    );
    return driver;
}

Дальше работаем с инстансом класса EventFiringWebDriver. В примере я переопределил только метод afterNavigateTo(), который вызывается автоматически после каждого вызова driver.get(someUrl). В реальной жизни этого явно недостаточно. Например, тест жмёт на кнопку и происходит автоматичекий редирект на другую страницу. В этом случае вызова afterNavigateTo() не произойдёт, поэтому приходится переопределять дополнительно beforeClickOn(), чтобы отключить анимацию при первом клике на какой-нибудь элемент после загрузки новой страницы.

Запускаем тесты в параллельном режиме


Изначально, я посматривал в сторону Selenium Grid, но у меня даже дэмку не получилось запустить, да и вообще grid показался мне не очень удобным: нужно запускать хаб и сервер. Поэтому запускаем тесты в двух и более броузерах средствами Maven и TestNG.
Добавляем в 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>

Если Вы инжектируете в тесты потоконебезопасные инстансы со scope=«singleton», то необходимо поменять на scope=«prototype». В лучшем случае на данном этапе можно отделаться только конфигурацией конфигов (например Spring'a). Если каждый ваш тест использует уникальное имя пользователя для логина, то всё должно заработать с пол-пинка.

Итоги


Раньше в проекте, над которым я работаю, исполнение Selenium-тестов занимало примерно 5 минут, теперь же — 1,5 минуты.

Для справки

Все вышеописанные действия были проведены на свяке Java+Selenium 2.8.0+Maven+TestNG+Firefox 7.0.1+Spring
Tags:
Hubs:
+33
Comments 13
Comments Comments 13

Articles