Your SlideShare is downloading. ×
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разработчиков
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

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

4,612
views

Published on

Как-то так происходит, что “на 10 девчонок по статистике 9 ребят”, а точнее на группу из 5-7 разработчиков – 1 тестировщик. Или его нет совсем. Так что очень часто приходится и код писать, и …

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

Published in: Technology

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,612
On Slideshare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
30
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Бодрящий микс из Selenium и TestNGРегрессионное тестирование руками разработчиков Ребров Андрей Luxoft
  • 2. @andrebrov
  • 3. Сколько тестировщиков в вашей команде?
  • 4. Build more overseer! ©
  • 5. При этом...• «У нас agile» - значит, тестирование должно завершиться в том же спринте• «Люблю короткие релизы»- значит регрессионное тестирование надо делать постоянно• «Они опять изменили требования!» - значит опять надо менять тесты
  • 6. Хватит это терпеть!
  • 7. Задачи• Нужно иметь возможность проводить регрессию в короткий период времени• Тесты должны быть простыми, чтобы их можно было легко написать/дописать/переписать• Поддержка тестов не должна занимать много времени
  • 8. Необходимые инструменты• Тестовый фреймворк• Фреймворк функционального тестирования• CI Server+ удобная IDE, понятный генератор отчетов,удобный язык программирования...
  • 9. Что взяли мы• TestNG• Selenium 2 / WebDriver• Spring• IntelliJ IDEA• Jenkins• Набор самописных утилит
  • 10. Почему TestNG• Удобная работа с данными - @DataProvider• Разбиение тестов по группам• Многопоточность «из коробки»• «Фабрика» тестов
  • 11. Почему WebDriver• Java-фреймворк• Абстракция на уровне PageObject• Работа с IE & FF• Активно развивается
  • 12. Зачем Spring?• Облегчение работы с базами данных• Необходима интеграция с различными сервисами в рамках тестов• IoC
  • 13. Этапы создания тестовой платформы
  • 14. Создание базового тестового класса
  • 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. Создание базовой web- страницы
  • 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. Описание web-страницы
  • 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. Вынесение данных в 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. Refactoring• Вынесение текстовых констант из классов страниц• Группировка DataProvider`ов в классы
  • 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. Работа с базой внутри DataProvider`ов
  • 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. Хинт 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. Хинт 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. Хинт 3 – Unit-тест как тест-кейсSearchPage searchPage = loadAndLogin();searchPage.setLegalNameSearchType(searchType);searchPage.setLegalNameSearchParam(legalName);SearchResultPage searchResultPage = searchPage.submit();assertIsSortedByLegalName(searchResultPage);
  • 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. Подключаем Jenkins• Используем возможность запуска через maven• Подключаем отчеты от TestNG и видим результаты регрессии• Запуск тестов по расписанию / установке новой версии / …
  • 30. Profit!
  • 31. Куда двигаться дальше• Создание профилей тестирования (smokem full, search)• Selenium Grid и многопоточность• 1 подход – разные типы приложений (WebService, ETL, ...)• End-to-end тестирование
  • 32. Андрей РебровArebrov@luxoft.com @andrebrov