SlideShare a Scribd company logo
Бодрящий микс из Selenium и TestNG
Регрессионное тестирование руками
          разработчиков


           Ребров Андрей
               Luxoft
@andrebrov
Сколько тестировщиков в вашей
           команде?
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разработчиков
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разработчиков
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разработчиков
Build more overseer! ©
При этом...
• «У нас agile» - значит, тестирование
  должно завершиться в том же спринте
• «Люблю короткие релизы»- значит
  регрессионное тестирование надо делать
  постоянно
• «Они опять изменили требования!» -
  значит опять надо менять тесты
Хватит это терпеть!
Задачи
• Нужно иметь возможность проводить
  регрессию в короткий период времени
• Тесты должны быть простыми, чтобы их
  можно было легко
  написать/дописать/переписать
• Поддержка тестов не должна занимать
  много времени
Необходимые инструменты
• Тестовый фреймворк
• Фреймворк функционального тестирования
• CI Server
+ удобная IDE, понятный генератор отчетов,
удобный язык программирования...
Что взяли мы
•   TestNG
•   Selenium 2 / WebDriver
•   Spring
•   IntelliJ IDEA
•   Jenkins
•   Набор самописных утилит
Почему TestNG
•   Удобная работа с данными - @DataProvider
•   Разбиение тестов по группам
•   Многопоточность «из коробки»
•   «Фабрика» тестов
Почему WebDriver
•   Java-фреймворк
•   Абстракция на уровне PageObject
•   Работа с IE & FF
•   Активно развивается
Зачем Spring?
• Облегчение работы с базами данных
• Необходима интеграция с различными
  сервисами в рамках тестов
• IoC
Этапы создания тестовой
      платформы
Создание базового тестового
          класса
public abstract class AbstractSeleniumTestClass extends AbstractTestNGSpringContextTests {

       @Autowired
       private WebDriver driver;

       @BeforeMethod(alwaysRun = true)
       public void printTestName(Method method) {}

       @AfterMethod(alwaysRun = true)
       public void clearCookies(Method method) throws Exception {}

       protected WebDriver getWebDriver() {}

       public SearchPage loadLemAndLogin() {}
   }
Создание базовой web-
      страницы
public abstract class AbstractPage extends LoadableComponent<LoginPage> {

    public AbstractPage(WebDriver driver) {
      this.driver = driver;
      this.wait = new WebDriverWait(driver, DEFAULT_TIMEOUT);
      PageFactory.initElements(driver, this);
    }

    protected abstract By getPageLoadedCheckElementLocator();

    // Primitive actions
    protected void clickOn(WebElement webElement) {}
    protected void type(WebElement webElement, String text) {}

    // Keys
    protected void pressEnter(WebElement webElement) {}
    protected void pressRight(WebElement webElement) {}
    // Autocomplete
    public void fillAutocomplete(WebElement webElement, String text) {}

    // Waits
    public WebElement waitUntilFound(final By by) {}
}
Описание web-страницы
public class LoginPage extends AbstractPage {

     private static final Logger log = Logger.getLogger(LoginPage.class);

     @FindBy(xpath = "//input[@name='USER']")
     private WebElement usernameInput;
     @FindBy(xpath = "//input[@name='PASSWORD']")
     private WebElement passwordInput;
     @FindBy(xpath = "//input[@class='Button']")
     private WebElement loginButton;


     @Override
     protected By getPageLoadedCheckElementLocator() {}

     public LoginPage(WebDriver driver) {
       super(driver);
     }

     @Override
     protected void isLoaded() throws Error {}

     public SearchPage login() {}

}
Вынесение данных в
                    DataProvider
public class SearchDataProvider {

     @DataProvider
     public static Object[][] searchTypes() {
       Object[][] result = new Object[4][1];
       result[0][0] = "BEGINS_WITH";
       result[1][0] = "CONTAINS";
       result[2][0] = "CONTAINS_SUBSTRING";
       result[3][0] = "SOUNDS_LIKE";
       return result;
     }

}
Refactoring
• Вынесение текстовых констант из классов
  страниц
• Группировка DataProvider`ов в классы
Подключение базы данных
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-
   method="close">
     <property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
     <property name="url" value=""/>
     <property name="username" value=""/>
     <property name="password" value=""/>
     <property name="maxActive" value="10"/>
</bean>

<bean id="simpleJdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemp
   late">
   <constructor-arg ref="dataSource"/>
</bean>
Работа с базой внутри
   DataProvider`ов
@Component
public class SearchByAlternateNameDataProvider {
   private static DataProviderGenerator dataProviderGenerator;

    @Autowired
    public void setDataProviderGenerator(DataProviderGenerator dataProviderGenerator) {
    SearchByAlternateNameDataProvider.dataProviderGenerator = dataProviderGenerator;
    }

    @DataProvider
    public static Object[][] alternateNameAndNonSuitableCOI() {
     return dataProviderGenerator.generatePairStringString("select …" + Config.DATA_COUNT);
    }
}

@Component
public class DataProviderGenerator {
   @Autowired
   private TestingJdbcTemplate testingJdbcTemplate;

    public Object[][] generatePairStringString(String sql) {}

}
Хинт 1 – WebDriver как
                    SpringBean
@Configuration
public class SeleniumConfiguration {
   @Autowired
   private WebDriver driver;

    public @Bean WebDriver driver() {}

    @PreDestroy
    public void cleanUp() {
      try {
         driver.quit();
      } catch (Throwable e) {
        e.printStackTrace();
      }
    }
}
Хинт 2 – TestFactory для похожих
              тестов
public class SearchTestFactory {

     @Factory(dataProvider = "searchTypes", dataProviderClass = SearchDataProvider.class)
     public Object[] createTest(String searchType) {
       return new Object[]{new GenericSearchTest(searchType)};
     }
}

public class GenericSearchTest extends AbstractSeleniumTest {
   private String searchType;

    public GenericSearchByLegalNameCOITest(String searchType) {
      this.searchType = searchType;
    }
    @Test(dataProvider = "legalNamesAndCountries", dataProviderClass =
    SearchTestFactory.class)
    @JiraIssue(number = “SRC-19")
    public void test(String param1, String param2) {}

}
Хинт 3 – Unit-тест как тест-кейс
SearchPage searchPage = loadAndLogin();
searchPage.setLegalNameSearchType(searchType);
searchPage.setLegalNameSearchParam(legalName);
SearchResultPage searchResultPage = searchPage.submit();
assertIsSortedByLegalName(searchResultPage);
Хинт 4 – Подключаем javascript
public void waitForAjaxComplete() {
   log.verbose("waiting for ajax completion");
      wait.until(new ExpectedCondition<Boolean>() {
         public Boolean apply(WebDriver driver) {
           return (Boolean) js.executeScript("return $.active == 0");
         }
      });
   log.verbose("All ajax calls are complete");
}
Подключаем Jenkins
• Используем возможность запуска через
  maven
• Подключаем отчеты от TestNG и видим
  результаты регрессии
• Запуск тестов по расписанию / установке
  новой версии / …
Profit!
Куда двигаться дальше
• Создание профилей тестирования (smokem
  full, search)
• Selenium Grid и многопоточность
• 1 подход – разные типы приложений
  (WebService, ETL, ...)
• End-to-end тестирование
Андрей Ребров
Arebrov@luxoft.com
    @andrebrov

More Related Content

PPTX
Автоматизация тестирования многопоточности
PPTX
Основы и нюансы параллельного тестрования
PPTX
Maven 3 : уличная магия
PPT
Maven как средство сборки проекта
PPT
Инструментация среды исполнения в арсенале тестировщика
KEY
Testing RIA with Selenium
PPTX
Cистемы автоматической сборки проектов (Полина Фоминых)
PPTX
Konstantin slisenko - Spring Framework
Автоматизация тестирования многопоточности
Основы и нюансы параллельного тестрования
Maven 3 : уличная магия
Maven как средство сборки проекта
Инструментация среды исполнения в арсенале тестировщика
Testing RIA with Selenium
Cистемы автоматической сборки проектов (Полина Фоминых)
Konstantin slisenko - Spring Framework

What's hot (20)

PDF
BDD girls Battle: Cucumber VS. JBehave
PPTX
системы сборок проектов
PDF
Разработка Enterprise-приложения на основе Spring Framework
PDF
Иван Крутов - Автоматизация сборки Java-проекта
PDF
Selenium grid on-demand
PPT
Сервлеты
PPTX
Нагрузочное тестирование JMeter Кожухов
PPTX
Kubernetes
PDF
Опыт разработки и тестирования RESTful JSON сервиса
PPTX
Automation testing desktop applications
PPT
Spring in java
PPTX
Система обработки бизнес-логики server-side приложения на Groovy
PDF
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
PDF
Микросервисы для автоматизации тестирования - опыт "Одноклассников"
PDF
Автоматизация UI тестирования под Windows и Windows Phone
PPTX
Silverlight 4, есть ли жизнь на десктопе
PDF
Автоматизация функционального тестирования REST API
PPTX
Тестирование отклика Web-интерфейса с JMeter и Selenium
ODP
Java 9 - Back to the Future
PPTX
Курс Java-2016. Занятие 02. Пакеты, сборка проекта с Maven
BDD girls Battle: Cucumber VS. JBehave
системы сборок проектов
Разработка Enterprise-приложения на основе Spring Framework
Иван Крутов - Автоматизация сборки Java-проекта
Selenium grid on-demand
Сервлеты
Нагрузочное тестирование JMeter Кожухов
Kubernetes
Опыт разработки и тестирования RESTful JSON сервиса
Automation testing desktop applications
Spring in java
Система обработки бизнес-логики server-side приложения на Groovy
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
Микросервисы для автоматизации тестирования - опыт "Одноклассников"
Автоматизация UI тестирования под Windows и Windows Phone
Silverlight 4, есть ли жизнь на десктопе
Автоматизация функционального тестирования REST API
Тестирование отклика Web-интерфейса с JMeter и Selenium
Java 9 - Back to the Future
Курс Java-2016. Занятие 02. Пакеты, сборка проекта с Maven
Ad

Similar to Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разработчиков (20)

PPTX
вебинар - функциональное тестирование с использованием Selenium 2 и TestNG
ODP
Unit test быстрый старт
PDF
Mobile automation uamobile
PPTX
iOS and Android Mobile Test Automation
PDF
The Old New ASP.NET
PPTX
Automation Functional Testing in Agile Projects
PPTX
Типичные ошибки начинающих писать тесты на WebDriver
PPT
Приемочные тесты на огурце
PPT
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
PDF
Jsfwdays 2013-2
PPTX
Тестирование Web API
PDF
Database (Lecture 14 – database)
PPTX
Java осень 2012 лекция 8
PPTX
SECON'2016. Иовлев Роман, JDI is UI Automation Future
PDF
Плюсы и минусы автоматизации, пример из жизни
PPTX
Java осень 2012 лекция 5
PDF
QA Fest 2017. Яна Кокряшкина. Интеграция автоматизированных тестов с инструме...
PDF
Виталий Каторгин, Wamba
PPT
Alexander manuhin selenium_php_v2.0
PPTX
Java весна 2013 лекция 8
вебинар - функциональное тестирование с использованием Selenium 2 и TestNG
Unit test быстрый старт
Mobile automation uamobile
iOS and Android Mobile Test Automation
The Old New ASP.NET
Automation Functional Testing in Agile Projects
Типичные ошибки начинающих писать тесты на WebDriver
Приемочные тесты на огурце
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Jsfwdays 2013-2
Тестирование Web API
Database (Lecture 14 – database)
Java осень 2012 лекция 8
SECON'2016. Иовлев Роман, JDI is UI Automation Future
Плюсы и минусы автоматизации, пример из жизни
Java осень 2012 лекция 5
QA Fest 2017. Яна Кокряшкина. Интеграция автоматизированных тестов с инструме...
Виталий Каторгин, Wamba
Alexander manuhin selenium_php_v2.0
Java весна 2013 лекция 8
Ad

More from Andrey Rebrov (20)

PPTX
Agile Testing in Enterprise: Way to transform - SQA Days 2014
PPTX
Spec By Example or How to teach people talk to each other
PPTX
Test Automation Canvas
PPT
How engineering practices help business
PPT
Don’t turn your logs into cuneiform
PPT
DevOps tools cargo tools
PPTX
Agile Games
PDF
Agile тестирование в enterpise проектов: путь трансформации
PDF
Building deployment pipeline - DevOps way
PDF
Test Automation Canvas - не наступайте на глабли автоматизации
PDF
Не превращайте ваши логи в клинопись
PDF
Карго культ инструментов в DevOps
PDF
как инженерные практики помогают экономить бизнесу
PDF
грабли автоматизации тестирования мобильного веба с помощью Selenium 2
PDF
DevOps от и до - что, зачем и почему
PDF
Agile Testing: вопросы и ответы
PDF
DevOps модное слово или следующая ступень эволюции
PPTX
Как научить людей общаться с помощью Spec By Example
PDF
Rebrov selenium camp2013
PDF
Курс молодого бойца-автоматизатора - как остаться в живых и стать ветераном
Agile Testing in Enterprise: Way to transform - SQA Days 2014
Spec By Example or How to teach people talk to each other
Test Automation Canvas
How engineering practices help business
Don’t turn your logs into cuneiform
DevOps tools cargo tools
Agile Games
Agile тестирование в enterpise проектов: путь трансформации
Building deployment pipeline - DevOps way
Test Automation Canvas - не наступайте на глабли автоматизации
Не превращайте ваши логи в клинопись
Карго культ инструментов в DevOps
как инженерные практики помогают экономить бизнесу
грабли автоматизации тестирования мобильного веба с помощью Selenium 2
DevOps от и до - что, зачем и почему
Agile Testing: вопросы и ответы
DevOps модное слово или следующая ступень эволюции
Как научить людей общаться с помощью Spec By Example
Rebrov selenium camp2013
Курс молодого бойца-автоматизатора - как остаться в живых и стать ветераном

Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разработчиков

  • 1. Бодрящий микс из Selenium и TestNG Регрессионное тестирование руками разработчиков Ребров Андрей Luxoft
  • 3. Сколько тестировщиков в вашей команде?
  • 8. При этом... • «У нас agile» - значит, тестирование должно завершиться в том же спринте • «Люблю короткие релизы»- значит регрессионное тестирование надо делать постоянно • «Они опять изменили требования!» - значит опять надо менять тесты
  • 10. Задачи • Нужно иметь возможность проводить регрессию в короткий период времени • Тесты должны быть простыми, чтобы их можно было легко написать/дописать/переписать • Поддержка тестов не должна занимать много времени
  • 11. Необходимые инструменты • Тестовый фреймворк • Фреймворк функционального тестирования • CI Server + удобная IDE, понятный генератор отчетов, удобный язык программирования...
  • 12. Что взяли мы • TestNG • Selenium 2 / WebDriver • Spring • IntelliJ IDEA • Jenkins • Набор самописных утилит
  • 13. Почему TestNG • Удобная работа с данными - @DataProvider • Разбиение тестов по группам • Многопоточность «из коробки» • «Фабрика» тестов
  • 14. Почему WebDriver • Java-фреймворк • Абстракция на уровне PageObject • Работа с IE & FF • Активно развивается
  • 15. Зачем Spring? • Облегчение работы с базами данных • Необходима интеграция с различными сервисами в рамках тестов • IoC
  • 18. public abstract class AbstractSeleniumTestClass extends AbstractTestNGSpringContextTests { @Autowired private WebDriver driver; @BeforeMethod(alwaysRun = true) public void printTestName(Method method) {} @AfterMethod(alwaysRun = true) public void clearCookies(Method method) throws Exception {} protected WebDriver getWebDriver() {} public SearchPage loadLemAndLogin() {} }
  • 20. public abstract class AbstractPage extends LoadableComponent<LoginPage> { public AbstractPage(WebDriver driver) { this.driver = driver; this.wait = new WebDriverWait(driver, DEFAULT_TIMEOUT); PageFactory.initElements(driver, this); } protected abstract By getPageLoadedCheckElementLocator(); // Primitive actions protected void clickOn(WebElement webElement) {} protected void type(WebElement webElement, String text) {} // Keys protected void pressEnter(WebElement webElement) {} protected void pressRight(WebElement webElement) {} // Autocomplete public void fillAutocomplete(WebElement webElement, String text) {} // Waits public WebElement waitUntilFound(final By by) {} }
  • 22. public class LoginPage extends AbstractPage { private static final Logger log = Logger.getLogger(LoginPage.class); @FindBy(xpath = "//input[@name='USER']") private WebElement usernameInput; @FindBy(xpath = "//input[@name='PASSWORD']") private WebElement passwordInput; @FindBy(xpath = "//input[@class='Button']") private WebElement loginButton; @Override protected By getPageLoadedCheckElementLocator() {} public LoginPage(WebDriver driver) { super(driver); } @Override protected void isLoaded() throws Error {} public SearchPage login() {} }
  • 23. Вынесение данных в DataProvider public class SearchDataProvider { @DataProvider public static Object[][] searchTypes() { Object[][] result = new Object[4][1]; result[0][0] = "BEGINS_WITH"; result[1][0] = "CONTAINS"; result[2][0] = "CONTAINS_SUBSTRING"; result[3][0] = "SOUNDS_LIKE"; return result; } }
  • 24. Refactoring • Вынесение текстовых констант из классов страниц • Группировка DataProvider`ов в классы
  • 25. Подключение базы данных <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy- method="close"> <property name="driverClassName" value="oracle.jdbc.OracleDriver"/> <property name="url" value=""/> <property name="username" value=""/> <property name="password" value=""/> <property name="maxActive" value="10"/> </bean> <bean id="simpleJdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemp late"> <constructor-arg ref="dataSource"/> </bean>
  • 26. Работа с базой внутри DataProvider`ов
  • 27. @Component public class SearchByAlternateNameDataProvider { private static DataProviderGenerator dataProviderGenerator; @Autowired public void setDataProviderGenerator(DataProviderGenerator dataProviderGenerator) { SearchByAlternateNameDataProvider.dataProviderGenerator = dataProviderGenerator; } @DataProvider public static Object[][] alternateNameAndNonSuitableCOI() { return dataProviderGenerator.generatePairStringString("select …" + Config.DATA_COUNT); } } @Component public class DataProviderGenerator { @Autowired private TestingJdbcTemplate testingJdbcTemplate; public Object[][] generatePairStringString(String sql) {} }
  • 28. Хинт 1 – WebDriver как SpringBean @Configuration public class SeleniumConfiguration { @Autowired private WebDriver driver; public @Bean WebDriver driver() {} @PreDestroy public void cleanUp() { try { driver.quit(); } catch (Throwable e) { e.printStackTrace(); } } }
  • 29. Хинт 2 – TestFactory для похожих тестов public class SearchTestFactory { @Factory(dataProvider = "searchTypes", dataProviderClass = SearchDataProvider.class) public Object[] createTest(String searchType) { return new Object[]{new GenericSearchTest(searchType)}; } } public class GenericSearchTest extends AbstractSeleniumTest { private String searchType; public GenericSearchByLegalNameCOITest(String searchType) { this.searchType = searchType; } @Test(dataProvider = "legalNamesAndCountries", dataProviderClass = SearchTestFactory.class) @JiraIssue(number = “SRC-19") public void test(String param1, String param2) {} }
  • 30. Хинт 3 – Unit-тест как тест-кейс SearchPage searchPage = loadAndLogin(); searchPage.setLegalNameSearchType(searchType); searchPage.setLegalNameSearchParam(legalName); SearchResultPage searchResultPage = searchPage.submit(); assertIsSortedByLegalName(searchResultPage);
  • 31. Хинт 4 – Подключаем javascript public void waitForAjaxComplete() { log.verbose("waiting for ajax completion"); wait.until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driver) { return (Boolean) js.executeScript("return $.active == 0"); } }); log.verbose("All ajax calls are complete"); }
  • 32. Подключаем Jenkins • Используем возможность запуска через maven • Подключаем отчеты от TestNG и видим результаты регрессии • Запуск тестов по расписанию / установке новой версии / …
  • 34. Куда двигаться дальше • Создание профилей тестирования (smokem full, search) • Selenium Grid и многопоточность • 1 подход – разные типы приложений (WebService, ETL, ...) • End-to-end тестирование