Немного про Selenium 2.0

Selenium 2.0 (он же Selenium WebDriver) — это инструмент автоматизации функционального тестирования. Selenium WebDriver представляет собой набор библиотек для управления браузерами. В Selenium 2.0 можно использовать все прелести как Selenium WebDriver, так и Selenium RC (в режиме совместимости с WebDriver, подразумевается, что это временное решение для перехода всех пользователей с Selenium RC на WebDriver). Разработчики инструмента рекомендуют использовать Selenium WebDriver, так как Selenium RC через некоторое время поддерживаться не будет.

Главное отличие, которое разделяет WebDriver и Selenium RC, заключается в способе взаимодействия с браузером. Selenium RC посылает команды браузеру с помощью специального JavaScript ядра Selenium Core. Данный подход позволяет обеспечивать кроссбраузерность (Selenium 1.0 может с относительной легкостью работать с разными браузерами). В этой заметке я описывал инструменты тестирования семейства Selenium. WebDriver, в отличие от Selenium RC “общается” с браузером через нативный интерфейс. Для каждого браузера свой нативный интерфейс, это и накладывает определенные сложности с поддержкой разных браузеров в WebDriver. Зато, предоставляет ряд преимуществ. Например, действия пользователя эмулируется максимально точно (например, тесты на WebDriver не видят скрытые элементы интерфейса).

Архитектуру Selenium RC можно представить следующим образом: Авто тесты -> Selenium RC Server -> Браузер -> Тестируемое приложение.

Selenium-1

В архитектуре Selenium WebDriver отсутствует «прослойка» Selenium RC Server. Зато добавляется слой Driver, который и отвечает за взаимодействие с браузером.

Selenium-2

Главное достоинство Selenium WebDriver заключается в том, что он использует драйверы, адаптированные под конкретный браузер, то есть Selenium WebDriver работает с каждым браузером по «индивидуальной программе». Это повышает стабильность работы тестов (так как они затачиваются под конкретный браузер), тесты становится проще писать и поддерживать, увеличивается скорость их работы. Selenium WebDriver использует нативные команды (старается полностью эмитировать действия пользователя), что является важным преимуществом перед Selenium RC.

На данный момент существуют следующие драйверы:

  • FirefoxDriver;
  • InternetExplorerDriver;
  • ChromeDriver;
  • OperaDriver — в данный момент еще не доступен для использования;
  • SafariDriver — в данный момент еще не доступен для использования;;
  • HtmlUnitDriver — кроссплатформенный драйвер на java, не требует установки кого-либо браузера;
  • AndriodDriver — мобильный браузер. Возможность тестирования веб-приложений под телефоны — еще одна фишка в Selenium 2.0;
  • IphoneDriver — мобильный браузер.

Список поддерживаемых языков в Selenium WebDriver: C#, Java, Ruby, Phyton.

Про основные команды в Selenium WebDriver я постараюсь написать в следующих заметках, стоит лишь отметить, что некоторые принципы работы по сравнению c Selenium 1.0 все же изменились в лучшую сторону. Так, WebDriver предлагает достаточно гибкую работу с ожиданиями событий на странице. Это объясняется тем, что WebDriver направлен в первую очередь на работу со сложным, перегруженными AJAX запросами веб-интерфейсами. Разработчики предлагают два механизма ожидания (Explicit Waits, Implicit Waits), тут можно посмотреть описание и примеры. Explicit Waits (эксплицитное ожидание), с использованием класса WebDriverWait, представляет сабой фактически циклическое ожидание события. Implicit Waits (имплицитное ожидание) – все команды поиска элементов автоматически становятся ожидающими. Естественно, можно использовать свои методы ожидания, ну или (что очень не желательно :-)) Thread.sleep(). Кстати, Selenium WebDriver умеет работать с HTML 5! Также, очень порадовал измененный механизм работы с локаторами — работать стало гораздо удобнее. В Selenium WebDriver добавились новые типы локаторов: partionalLinkText, tagName, name. В этой заметке я расписывал типы локаторов в Selenium 1.0. Полный список локаторов в Selenium 2.0:

  • By.id – в качестве локатора используется атрибут id (уникальный идентификатор) элемента страницы;
  • By.name – в качестве локатора используется атрибут name элемента страницы;
  • By.xpath – используется для поиска элемента по XPath выражению;
  • By.tagName – поиск по имени HTML тэга;
  • By.className – поиск по CSS классу элемента;
  • By.cssSelector – данный тип локаторов основан на описаниях таблиц стилей (CSS);
  • By.linkText – поиск ссылки с указанным текстом;
  • By.partionalLinkText – поиск по части ссылки с указанным текстом.

Для того, чтобы начать разрабатывать авто тесты на Selenium 2.0 под .Net нужно скачать отсюда набор библиотек для .Net. В скачанном архиве должны находится следующие библиотеки: Castle.Core.dll, Ionic.Zip.Reduced.dll, Newtonsoft.Json.Net35.dll, Selenium.WebDriverBackedSelenium.dll, ThoughtWorks.Selenium.Core.dll, WebDriver.dll, WebDriver.Support.dll. Данные библиотеки нужно подключить в проект. Если вы хотите писать тесты на другом языке программирования, то начальную инструкцию, можно изучить на официальным сайте разработчиков Selenium. Для запуска тестов, нам понадобиться установить NUnit. NUnit — это вспомогательный framework для создания тестов. Скачать NUnit можно перейдя по этой ссылке. Библиотеки NUnit: nmock.dll, nunit.core.dll, nunit. framework.dll также нужно подключить в проект.

Итак, открываем Visual Studio и создаем новый проект типа Class Library, добавляем упомянутые выше библиотеки. После этого можно приступать к написанию первого теста. Шаги нашего простейшего теста будут следующими:

  • Открыть главную страницу данного блога, проверить title страницы;
  • В поле «Поиск» внести значение «Выпуск Selenium 2.0»;
  • Нажать на кнопку «Search Submit» (лупа);
  • Проверить результаты поиска.

Пример теста на Selenium WebDriver с использованием C#:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System;
using System.Text;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
 
namespace SeleniumTests
{
    [TestFixture]
    public class Untitled
    {
        private IWebDriver driver;
        private StringBuilder verificationErrors;
        private string baseURL;
 
        [SetUp]
        public void SetupTest()
        {
            // You may use any WebDriver implementation. Firefox is used here as an example
            driver = new FirefoxDriver();
            baseURL = "http://bugscatcher.net";
            verificationErrors = new StringBuilder();
        }
 
        [TearDown]
        public void TeardownTest()
        {
            try
            {
                driver.Quit();
            }
            catch (Exception)
            {
                // Ignore errors if unable to close the browser
            }
            Assert.AreEqual("", verificationErrors.ToString());
        }
 
        [Test]
        public void TheUntitledTest()
        {
            // open | /qa | 
            driver.Navigate().GoToUrl(baseURL);
 
            // assertTitle | Bugs Catcher | 
            Assert.AreEqual("Bugs Catcher", driver.Title);
 
            // type | name=s | Selenium WebDriver
            driver.FindElement(By.Name("s")).SendKeys("Выпуск Selenium 2.0");
 
            // click | id=searchsubmit | 
            driver.FindElement(By.Id("searchsubmit")).Click();
 
            // assertTitle | Search Results Selenium WebDriver -Bugs Catcher | 
            Assert.AreEqual("Search Results Selenium WebDriver -Bugs Catcher", driver.Title);
 
            //assertText present
            Assert.IsTrue(driver.PageSource.Contains("Результаты поиска"));
 
            //assertLink present
            Assert.IsTrue(driver.FindElement(By.LinkText("Выпуск Selenium 2.0")).Displayed);
        }
    }
}
using System;
using System.Text;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;

namespace SeleniumTests
{
    [TestFixture]
    public class Untitled
    {
        private IWebDriver driver;
        private StringBuilder verificationErrors;
        private string baseURL;

        [SetUp]
        public void SetupTest()
        {
            // You may use any WebDriver implementation. Firefox is used here as an example
            driver = new FirefoxDriver();
            baseURL = "http://bugscatcher.net";
            verificationErrors = new StringBuilder();
        }

        [TearDown]
        public void TeardownTest()
        {
            try
            {
                driver.Quit();
            }
            catch (Exception)
            {
                // Ignore errors if unable to close the browser
            }
            Assert.AreEqual("", verificationErrors.ToString());
        }

        [Test]
        public void TheUntitledTest()
        {
            // open | /qa | 
            driver.Navigate().GoToUrl(baseURL);

            // assertTitle | Bugs Catcher | 
            Assert.AreEqual("Bugs Catcher", driver.Title);

            // type | name=s | Selenium WebDriver
            driver.FindElement(By.Name("s")).SendKeys("Выпуск Selenium 2.0");

            // click | id=searchsubmit | 
            driver.FindElement(By.Id("searchsubmit")).Click();

            // assertTitle | Search Results Selenium WebDriver -Bugs Catcher | 
            Assert.AreEqual("Search Results Selenium WebDriver -Bugs Catcher", driver.Title);

            //assertText present
            Assert.IsTrue(driver.PageSource.Contains("Результаты поиска"));

            //assertLink present
            Assert.IsTrue(driver.FindElement(By.LinkText("Выпуск Selenium 2.0")).Displayed);
        }
    }
}

Теперь попробуем запустить разработанный тест. Перед этим сбилдите проект в Visual Studio (F6) и проверьте, что нет ошибок. Если все хорошо, идем дальше, если нет — пишите в комменты или на email.

  • Запускаем ранее установленный NUnit;
  • В NUnit выбираем «File -> Open Project…»;
  • И в диалоговом окне указываем путь к .dll нашего теста (…binDebugSeleniumTest.dll);
  • Загружаем проект и нажимает кнопку «Run» (ее будет трудно не заметить).

В результате данных не итрых действий должен запуститься написанный нами ранее авто-тест на Selenium. Примерно так должно выглядеть окно NUnit-а с загруженным тестом:

NUnit

В данном примере использовались следующие команды Selenium WebDriver:

  • void GoToUrl(string url) — перейти по указанному в «baseURL» адресу;
  • string Title { get; } — возвращает Title активной страницы;
  • FindElement(OpenQA.Selenium.By by) — поиск элемента страницы по указанному типу локатора. Например, driver.FindElement(By.Name("s")) или driver.FindElement(By.LinkText("Выпуск Selenium 2.0")). Список поддерживаемых типов локаторов предоставлен выше;
  • void SendKeys(string text) — ввести значение в текстовое поле;
  • void Click() — нажатие на элемент страницы;
  • public bool Contains(string value) — возвращает значение, указывающие, является ли введённое значение частью объекта.

Также разработчиками Selenium 2.0 создан план по переходу от Selenium 1.0 к Selenium 2.0 в режиме WebDriver. План примерно таков:

  • Используем эмулятор интерфейса Selenium 1.0 для Java и .Net. Для этого нужно использовать в инициализации WebDriverBackedSelenium вместо DefaultSelenium. Судя по комментариям на данном этапе могут возникать трудности (и скорее всего возникнут). Проблемы могут возникнуть в связи с тем, что команды в Selenium 2.0 немного отличаются (фиксы старых проблем, плюс теоретически новые проблемы) от Selenium 1.0. Поэтому после данной стадии скорее всего последует этап стабилизации. Должно получится примерно так:
    1
    2
    
    WebDriver driver = new FirefoxDriver();
    Selenium selenium = new WebDriverBackedSelenium(driver, "http://www.yoursite.com");
    WebDriver driver = new FirefoxDriver();
    Selenium selenium = new WebDriverBackedSelenium(driver, "http://www.yoursite.com");
  • Создание новых тестов и переписывание старых под Selenium 2.0 в режиме WebDriver. После того, как все тесты будут готовы работать в режиме WebDriver в классе инициализации Selenium вместо эмулятора WebDriverBackedSelenium нужно прописать команду запуска чистого WebDriver API:
    1
    
    WebDriver driver = ((WrapsDriver) selenium).getWrappedDriver();
    WebDriver driver = ((WrapsDriver) selenium).getWrappedDriver();

В качестве примера возьмем ранее рассмотренный тест и и преобразуем его таким образом, чтобы можно было использовать команды как Selenium 1.0, так и Selenium 2.0. После этого запустим полученный тест в смешанном «режиме» (на всякий случай напомню, что Selenium Server запускать не нужно). Вот так вот будет выглядеть преобразованный тест с использованием команд Selenium 1.0 и Selenium 2.0 (Web Driver) (найдите 10 отличий от предыдущего примера :-)) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using System;
using System.Text;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using Selenium;
 
namespace SeleniumTests
{
    [TestFixture]
    public class Untitled
    {
        private IWebDriver driver;
        private StringBuilder verificationErrors;
        private string baseURL;
        private ISelenium selenium;
 
        [SetUp]
        public void SetupTest()
        {
            // You may use any WebDriver implementation. Firefox is used here as an example
            driver = new FirefoxDriver();
            
            // A "base url", used by selenium to resolve relative URLs
            baseURL = "http://bugscatcher.net";
            
            // Create the Selenium implementation
            selenium = new WebDriverBackedSelenium(driver, baseURL);
            
            selenium.Start();
            verificationErrors = new StringBuilder();
        }
 
        [TearDown]
        public void TeardownTest()
        {
            try
            {
                selenium.Stop();
            }
            catch (Exception)
            {
                // Ignore errors if unable to close the browser
            }
            Assert.AreEqual("", verificationErrors.ToString());
        }
 
        [Test]
        public void TheUntitledTest()
        {
            // open | /qa | 
            driver.Navigate().GoToUrl(baseURL);
 
            // assertTitle | Bugs Catcher | 
            Assert.AreEqual("Bugs Catcher", selenium.GetTitle());
 
            // type | name=s | Selenium WebDriver
            driver.FindElement(By.Name("s")).SendKeys("Выпуск Selenium 2.0");
 
            // click | id=searchsubmit | 
            selenium.Click("searchsubmit");
            
            selenium.WaitForPageToLoad("3000");
 
            // assertTitle | Search Results Selenium WebDriver -Bugs Catcher | 
            Assert.AreEqual("Search Results Selenium WebDriver -Bugs Catcher", driver.Title);
 
            //assertText present
            Assert.IsTrue(selenium.IsTextPresent("Результаты поиска"));
 
            //assertLink present
            Assert.IsTrue(driver.FindElement(By.LinkText("Выпуск Selenium 2.0")).Displayed);
        }
    }
}
using System;
using System.Text;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using Selenium;

namespace SeleniumTests
{
    [TestFixture]
    public class Untitled
    {
        private IWebDriver driver;
        private StringBuilder verificationErrors;
        private string baseURL;
        private ISelenium selenium;

        [SetUp]
        public void SetupTest()
        {
            // You may use any WebDriver implementation. Firefox is used here as an example
            driver = new FirefoxDriver();
            
            // A "base url", used by selenium to resolve relative URLs
            baseURL = "http://bugscatcher.net";
            
            // Create the Selenium implementation
            selenium = new WebDriverBackedSelenium(driver, baseURL);
            
            selenium.Start();
            verificationErrors = new StringBuilder();
        }

        [TearDown]
        public void TeardownTest()
        {
            try
            {
                selenium.Stop();
            }
            catch (Exception)
            {
                // Ignore errors if unable to close the browser
            }
            Assert.AreEqual("", verificationErrors.ToString());
        }

        [Test]
        public void TheUntitledTest()
        {
            // open | /qa | 
            driver.Navigate().GoToUrl(baseURL);

            // assertTitle | Bugs Catcher | 
            Assert.AreEqual("Bugs Catcher", selenium.GetTitle());

            // type | name=s | Selenium WebDriver
            driver.FindElement(By.Name("s")).SendKeys("Выпуск Selenium 2.0");

            // click | id=searchsubmit | 
            selenium.Click("searchsubmit");
            
            selenium.WaitForPageToLoad("3000");

            // assertTitle | Search Results Selenium WebDriver -Bugs Catcher | 
            Assert.AreEqual("Search Results Selenium WebDriver -Bugs Catcher", driver.Title);

            //assertText present
            Assert.IsTrue(selenium.IsTextPresent("Результаты поиска"));

            //assertLink present
            Assert.IsTrue(driver.FindElement(By.LinkText("Выпуск Selenium 2.0")).Displayed);
        }
    }
}

Вот еще пример работы на совместимостью WebDriver и Selenium RC взятый из официальной документации к Selenium 2.0:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// You may use any WebDriver implementation. Firefox is used here as an example
WebDriver driver = new FirefoxDriver();
 
// A "base url", used by selenium to resolve relative URLs
 String baseUrl = "http://www.google.com";
 
// Create the Selenium implementation
Selenium selenium = new WebDriverBackedSelenium(driver, baseUrl);
 
// Perform actions with selenium
selenium.open("http://www.google.com");
selenium.type("name=q", "cheese");
selenium.click("name=btnG");
 
// Get the underlying WebDriver implementation back. This will refer to the
// same WebDriver instance as the "driver" variable above.
WebDriver driverInstance = ((WebDriverBackedSelenium) selenium).getUnderlyingWebDriver();
 
    //Finally, close the browser. Call stop on the WebDriverBackedSelenium instance
    //instead of calling driver.quit(). Otherwise, the JVM will continue running after
    //the browser has been closed.
    selenium.stop();
// You may use any WebDriver implementation. Firefox is used here as an example
WebDriver driver = new FirefoxDriver();

// A "base url", used by selenium to resolve relative URLs
 String baseUrl = "http://www.google.com";

// Create the Selenium implementation
Selenium selenium = new WebDriverBackedSelenium(driver, baseUrl);

// Perform actions with selenium
selenium.open("http://www.google.com");
selenium.type("name=q", "cheese");
selenium.click("name=btnG");

// Get the underlying WebDriver implementation back. This will refer to the
// same WebDriver instance as the "driver" variable above.
WebDriver driverInstance = ((WebDriverBackedSelenium) selenium).getUnderlyingWebDriver();

    //Finally, close the browser. Call stop on the WebDriverBackedSelenium instance
    //instead of calling driver.quit(). Otherwise, the JVM will continue running after
    //the browser has been closed.
    selenium.stop();

Удачной автоматизации!