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