27
Функциональное тестирование с помощью Selenium Ребров Андрей Luxoft

вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Embed Size (px)

Citation preview

Page 1: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Функциональное тестирование с помощью Selenium

Ребров АндрейLuxoft

Page 2: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

@andrebrov

Page 3: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Задачи

• Нужно иметь возможность проводить регрессию в короткий период времени

• Тесты должны быть простыми, чтобы их можно было легко написать/дописать/переписать

• Поддержка тестов не должна занимать много времени

Page 4: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Необходимые инструменты

• Тестовый фреймворк• Фреймворк функционального тестирования• CI Server•+ удобная IDE, понятный генератор отчетов, удобный язык программирования...

Page 5: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Что взяли мы

• TestNG• Selenium 2 / WebDriver• Spring• IntelliJ IDEA• Jenkins• Набор самописных утилит

Page 6: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Почему TestNG

• Удобная работа с данными - @DataProvider• Разбиение тестов по группам• Многопоточность «из коробки»• «Фабрика» тестов

Page 7: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Почему WebDriver

• Java-фреймворк• Абстракция на уровне PageObject• Работа с IE & FF• Активно развивается

Page 8: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Зачем Spring?

• Облегчение работы с базами данных• Необходима интеграция с различными

сервисами в рамках тестов• IoC

Page 9: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Этапы создания тестовой платформы

Page 10: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Создание базового тестового класса

Page 11: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

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 12: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Создание базовой web-страницы

Page 13: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

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 14: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Описание web-страницы

Page 15: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

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 16: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Вынесение данных в 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 17: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Refactoring

• Вынесение текстовых констант из классов страниц

• Группировка DataProvider`ов в классы

Page 18: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Подключение базы данных<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 19: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Работа с базой внутри DataProvider`ов

Page 20: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

@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 21: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Хинт 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 22: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Хинт 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 23: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Хинт 3 – Unit-тест как тест-кейс        SearchPage searchPage = loadAndLogin();        searchPage.setLegalNameSearchType(searchType);        searchPage.setLegalNameSearchParam(legalName);        SearchResultPage searchResultPage = searchPage.submit();        assertIsSortedByLegalName(searchResultPage);

Page 24: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Хинт 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 25: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Подключаем Jenkins

• Используем возможность запуска через maven

• Подключаем отчеты от TestNG и видим результаты регрессии

• Запуск тестов по расписанию / установке новой версии / …

Page 26: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

Куда двигаться дальше

• Создание профилей тестирования (smokem full, search)

• Selenium Grid и многопоточность• 1 подход – разные типы приложений

(WebService, ETL, ...)• End-to-end тестирование

Page 27: вебинар - функциональное тестирование с использованием Selenium 2 и TestNG

• Андрей Ребров• [email protected]

• @andrebrov