Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Бодрящий микс из Selenium и TestNGРегрессионное тестирование руками          разработчиков           Ребров Андрей        ...
@andrebrov
Сколько тестировщиков в вашей           команде?
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 ...
Создание базовой web-      страницы
public abstract class AbstractPage extends LoadableComponent<LoginPage> {    public AbstractPage(WebDriver driver) {      ...
Описание web-страницы
public class LoginPage extends AbstractPage {     private static final Logger log = Logger.getLogger(LoginPage.class);    ...
Вынесение данных в                    DataProviderpublic class SearchDataProvider {     @DataProvider     public static Ob...
Refactoring• Вынесение текстовых констант из классов  страниц• Группировка DataProvider`ов в классы
Подключение базы данных<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-   method="close">   ...
Работа с базой внутри   DataProvider`ов
@Componentpublic class SearchByAlternateNameDataProvider {   private static DataProviderGenerator dataProviderGenerator;  ...
Хинт 1 – WebDriver как                    SpringBean@Configurationpublic class SeleniumConfiguration {   @Autowired   priv...
Хинт 2 – TestFactory для похожих              тестовpublic class SearchTestFactory {     @Factory(dataProvider = "searchTy...
Хинт 3 – Unit-тест как тест-кейсSearchPage searchPage = loadAndLogin();searchPage.setLegalNameSearchType(searchType);searc...
Хинт 4 – Подключаем javascriptpublic void waitForAjaxComplete() {   log.verbose("waiting for ajax completion");      wait....
Подключаем Jenkins• Используем возможность запуска через  maven• Подключаем отчеты от TestNG и видим  результаты регрессии...
Profit!
Куда двигаться дальше• Создание профилей тестирования (smokem  full, search)• Selenium Grid и многопоточность• 1 подход – ...
Андрей РебровArebrov@luxoft.com    @andrebrov
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разработчиков
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разработчиков
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разработчиков
Upcoming SlideShare
Loading in …5
×

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

6,290 views

Published on

Как-то так происходит, что “на 10 девчонок по статистике 9 ребят”, а точнее на группу из 5-7 разработчиков – 1 тестировщик. Или его нет совсем. Так что очень часто приходится и код писать, и тестировать, а дата релиза все ближе и ближе.
В тех случаях, когда мы пишем веб-приложение, помочь в нашей нелегкой судьбе может бодрящий микс из Selenium и TestNG... Как это сделали мы, какие потом получили выводы и результаты — все это я и хочу рассказать и показать

Published in: Technology
  • Be the first to comment

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

  1. 1. Бодрящий микс из Selenium и TestNGРегрессионное тестирование руками разработчиков Ребров Андрей Luxoft
  2. 2. @andrebrov
  3. 3. Сколько тестировщиков в вашей команде?
  4. 4. Build more overseer! ©
  5. 5. При этом...• «У нас agile» - значит, тестирование должно завершиться в том же спринте• «Люблю короткие релизы»- значит регрессионное тестирование надо делать постоянно• «Они опять изменили требования!» - значит опять надо менять тесты
  6. 6. Хватит это терпеть!
  7. 7. Задачи• Нужно иметь возможность проводить регрессию в короткий период времени• Тесты должны быть простыми, чтобы их можно было легко написать/дописать/переписать• Поддержка тестов не должна занимать много времени
  8. 8. Необходимые инструменты• Тестовый фреймворк• Фреймворк функционального тестирования• CI Server+ удобная IDE, понятный генератор отчетов,удобный язык программирования...
  9. 9. Что взяли мы• TestNG• Selenium 2 / WebDriver• Spring• IntelliJ IDEA• Jenkins• Набор самописных утилит
  10. 10. Почему TestNG• Удобная работа с данными - @DataProvider• Разбиение тестов по группам• Многопоточность «из коробки»• «Фабрика» тестов
  11. 11. Почему WebDriver• Java-фреймворк• Абстракция на уровне PageObject• Работа с IE & FF• Активно развивается
  12. 12. Зачем Spring?• Облегчение работы с базами данных• Необходима интеграция с различными сервисами в рамках тестов• IoC
  13. 13. Этапы создания тестовой платформы
  14. 14. Создание базового тестового класса
  15. 15. 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() {} }
  16. 16. Создание базовой web- страницы
  17. 17. 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) {}}
  18. 18. Описание web-страницы
  19. 19. 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() {}}
  20. 20. Вынесение данных в DataProviderpublic 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; }}
  21. 21. Refactoring• Вынесение текстовых констант из классов страниц• Группировка DataProvider`ов в классы
  22. 22. Подключение базы данных<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>
  23. 23. Работа с базой внутри DataProvider`ов
  24. 24. @Componentpublic 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); }}@Componentpublic class DataProviderGenerator { @Autowired private TestingJdbcTemplate testingJdbcTemplate; public Object[][] generatePairStringString(String sql) {}}
  25. 25. Хинт 1 – WebDriver как SpringBean@Configurationpublic class SeleniumConfiguration { @Autowired private WebDriver driver; public @Bean WebDriver driver() {} @PreDestroy public void cleanUp() { try { driver.quit(); } catch (Throwable e) { e.printStackTrace(); } }}
  26. 26. Хинт 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) {}}
  27. 27. Хинт 3 – Unit-тест как тест-кейсSearchPage searchPage = loadAndLogin();searchPage.setLegalNameSearchType(searchType);searchPage.setLegalNameSearchParam(legalName);SearchResultPage searchResultPage = searchPage.submit();assertIsSortedByLegalName(searchResultPage);
  28. 28. Хинт 4 – Подключаем javascriptpublic 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");}
  29. 29. Подключаем Jenkins• Используем возможность запуска через maven• Подключаем отчеты от TestNG и видим результаты регрессии• Запуск тестов по расписанию / установке новой версии / …
  30. 30. Profit!
  31. 31. Куда двигаться дальше• Создание профилей тестирования (smokem full, search)• Selenium Grid и многопоточность• 1 подход – разные типы приложений (WebService, ETL, ...)• End-to-end тестирование
  32. 32. Андрей РебровArebrov@luxoft.com @andrebrov

×