Блог вебразработчика
  • ГЛАВНАЯ
  • ПОДПИСКА

Selenium PageFactory и FieldDecorator (часть 1)

Сен04
2012
Написал Tatyana

Интерфейс FieldDecorator используется фабрикой для декорирования объектов в классе страницы. Он предоставляет метод decorate, который вызывается для каждого поля в классе. По умолчанию фабрика использует класс DefaultFieldDecorator. Он определяет все WebElement и List<WebElement> объекты в классе и декорирует их с помощью прокси.
Зачем может понадобиться кастомный декоратор?
Интерфейс WebElement не всегда удобно использовать. Его невозможно расширить и добавить свои методы для работы с элементом. Использовать свои методы можно только создавая классы-обвертки(CheckBox, Button и т.п.), которые просто делегируют вызов методов настоящему WebElement. Но эти классы приходится вызывать в коде явно, передавая им объект WebElement.
Использование кастомного декоратора позволяет инициализировать такие классы неявно. Такой подход значительно уменьшает количество кода и повышает его читаемость. Однако есть и своеобразный минус — для каждого найденного веб-элемента будет создаваться лишний объект в памяти, представляющий Вашу обвертку.

Класс-обвертка должен выглядеть примерно следующим образом, обязательным условием является наличие конструктора принимающего WebElement:

import org.openqa.selenium.WebElement;

public class Element {
	protected WebElement webElement;
	    
	public Element(WebElement webElement) {
		this.webElement = webElement;
	}
		
	// универсальные методы для всех элементов	
}

Наследуясь от этого класса можно создавать уже более узконаправленные классы, отличающиеся по функциональности (кнопки, текстовые поля, списки):

import org.openqa.selenium.WebElement;

public class CheckBox extends Element {
	    
	public CheckBox(WebElement webElement) {
	        super(webElement);
	}

	public void setChecked(boolean value) {
	        if (value != isChecked()) {
	            webElement.click();
	        }
	}
	    
	public boolean isChecked() {
	        return webElement.isSelected();
	}
}

Кастомный декоратор можно полностью написать самим, реализовав интерфейс FieldDecorator. А можно унаследоваться от класса DefaultFieldDecorator и использовать найденные им веб-элементы для создания своих классов. Обратите внимание, что приведенный ниже декоратор работает только с классами-обвертками и больше не обрабатывает WebElement.

import java.lang.reflect.Field;

import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.pagefactory.
						DefaultElementLocatorFactory;
import org.openqa.selenium.support.pagefactory.DefaultFieldDecorator;
import org.openqa.selenium.support.pagefactory.ElementLocator;
public class CustomFieldDecorator extends DefaultFieldDecorator {

	public CustomFieldDecorator(SearchContext searchContext) {
		super(new DefaultElementLocatorFactory(searchContext));
	}

	/**
	 * Метод вызывается фабрикой для каждого поля в классе
	 */
	@Override
	public Object decorate(ClassLoader loader, Field field) {
		Class<?> decoratableClass = decoratableClass(field);
		// если класс поля декорируемый
		if (decoratableClass != null) {
			 ElementLocator locator = factory.createLocator(field);
			 if (locator == null) {
			      return null;
			 }

			 // элемент   
			 return createElement(loader, locator, decoratableClass);	
		}
	    return null;
	}

	/**
	 * Возвращает декорируемый класс поля, 
	 * либо null если класс не подходит для декоратора
	 */
	private Class<?> decoratableClass(Field field) {
		
		Class<?> clazz = field.getType();
		
		// у элемента должен быть конструктор, принимающий WebElement
		try {
			clazz.getConstructor(WebElement.class);
		} catch (Exception e) {
			return null;
		} 
		
	    return clazz;
	}
	
	/**
	 * Создание элемента.
	 * Находит WebElement и передает его в кастомный класс 
	 */
	protected <T> T createElement(ClassLoader loader, 
								ElementLocator locator, Class<T> clazz) {
		WebElement proxy = proxyForLocator(loader, locator);
		return createInstance(clazz, proxy);
	}

	/**
	 * Создает экземпляр класса, 
	 * вызывая конструктор с аргументом WebElement
	 */
	private <T> T createInstance(Class<T> clazz, WebElement element) {
		try {
			return (T) clazz.getConstructor(WebElement.class)
									.newInstance(element);
		} catch (Exception e) {
			throw new AssertionError(
					"WebElement can't be represented as " + clazz
					);
		} 
	}
}

Если нужно использовать одновременно и свои классы и WebElement, замените в методе decorate последнюю строку на:

return super.decorate(loader, field);

В приведенном примере декоратор работает только с отдельными элементами. О том как реализовать обработку списка кастомных элементов речь пойдет в следующей статье Selenium PageFactory и FieldDecorator (часть 2).

Справедливости ради стоит заметить, что вместе с этим декоратором можно использовать готовый класс org.openqa.selenium.support.ui.Select, предоставляемый библиотекой Selenium. Но его методы ограничены лишь работой со списком, поэтому лучше все же написать свой.

Page Object класс страницы с использованием декоратора (здесь используется org.openqa.selenium.support.ui.Select):

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.Select;

public class SelectExamplePage {

	private WebDriver driver;
	
	@FindBy(tagName = "select")
	private Select select;
	
	public SelectExamplePage(WebDriver driver) {
		PageFactory.initElements(new CustomFieldDecorator(driver), this);
		this.driver = driver;
	}
	
	public void printInfoAboutSelectElements() {
		System.out.println("Select option: " 
						+ select.getFirstSelectedOption().getText());
		System.out.println("Is multiply: " 
						+ select.isMultiple() + "\n");
	}
}
  • Нравится
  • Tweet

Опубликовано в Selenium - Помечено Page Object, PageFactory, Select, Selenium WebDriver
Рассказать всем Twitter Facebook Delicious StumbleUpon E-Mail
← Selenium и Page Object паттерн
Selenium PageFactory и FieldDecorator (часть 2) →

7 комментариев

  1. Владимир's Gravatar Владимир
    30.01.2013 at 06:28 | Permalink

    Как быть с конструктором если целевая страница с переопределяемыми веб-элементами у нас наследуется от базовой?

    • Tatyana's Gravatar Tatyana
      30.01.2013 at 07:29 | Permalink

      Если вызов фабрики выполняется в конструкторе базового класса, то:

      public class ChildPage extends CommonPage {
          public ChildPage(WebDriver driver) {
              super(driver);
          }
      }
      • Владимир's Gravatar Владимир
        30.01.2013 at 11:33 | Permalink

        Но порядок другой:
        public BasePage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(new CustomFieldDecorator(driver), this);
        }

        Иначе волшебство не срабатывало.
        В любом случае большое спасибо, за блог!
        Очень вдохновляет.

        • Tatyana's Gravatar Tatyana
          30.01.2013 at 11:47 | Permalink

          Видимо потому, что в new CustomFieldDecorator(driver) у Вас передавался this.driver, а не параметр метода. Тут путаница получилась из-за имен, если бы у параметра было другое имя, то такая ситуация бы не возникла)))

  2. Александр's Gravatar Александр
    31.07.2013 at 08:38 | Permalink

    а паттерн Декоратор не пробовали использовать? Почти как обертка, но при этом реализует интерфейс WebElement, что позволяет использовать кастомные элементы со стандартным DefaultFieldDecorator?

    По задумке 🙂 Т.к. у меня пока не заработало, но не в слое Selenium (там все нормально определяется по интерфейсу WebElement), а глубже, на уровне Field.set() вылетает эксепшн sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException.

    Интересно узнать пробовали ли вы и получилось ли?

  3. Евгений's Gravatar Евгений
    16.07.2014 at 19:16 | Permalink

    Подскажите пожалуйста, а как решить проблему с обёртками в фукнциях ожидания? Они же используют читый WebElement

    public WebElement waitElemByXpath(int sec, final String SELECTOR) {
    LOGGER.info("Trying to find element by xpath: " + SELECTOR);
    WebElement tempElement = (WebElement) (new WebDriverWait(this.driver, sec)).until(new ExpectedCondition() {
    @Override
    public WebElement apply(WebDriver driver) {
    return driver.findElement(By.xpath(SELECTOR));
    }
    });
    return tempElement;

    • Tatyana's Gravatar Tatyana
      17.07.2014 at 07:29 | Permalink

      Используйте конструктор обвертки, который принимает как раз WebElement

Свежие записи

  • WebDriver и SSL Untrusted certificate
  • Видеозапись выполнения тестов Selenium
  • Selenium WebDriver: basic авторизация
  • BrowserMob Proxy + Selenium: автоматизация сбора данных о производительности
  • Hibernate 4: UserType пользовательский тип данных (часть 2)

Поиск

Рубрики

  • Hibernate ORM
  • SEO
  • Разное
  • Тестирование
    • JUnit
    • Selenium
    • Thucydides

Метки

Actions AJAX Alert AutoIt ChromeDriver Exceptions ExpectedConditions FindElement FirefoxDriver Hibernate InternetExplorerDriver Java Javascript Jenkins JUnit4 Maven PageFactory Page Object RemoteWebDriver Select Selenium IDE Selenium Server Selenium WebDriver switchTo Thucydides WebDriverWait XPath Автоматизированное тестирование база данных заработок в сети сеть Интернет скорость продвижения сайта статейное продвижение услуги продвижения

Реклама


Donec in mi a arcu cursus commodo non ut metus. Nunc id eros ut augue consequat tempus ut non ligula. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer pretium, erat sit amet scelerisque euismod, purus lectus convallis dui, eget imperdiet sapien est ut magna. Nullam elementum, tortor vitae pulvinar mattis, orci neque porta tortor, a feugiat nisi lacus quis diam. Ut gravida augue id est rutrum elementum. Mauris eget felis dolor. Phasellus ante ante, porttitor sit amet lobortis ut, suscipit id neque. Fusce hendrerit dolor nec odio eleifend in auctor enim cursus. Nullam fermentum pretium risus, in hendrerit nulla cursus sit amet. Fusce eu tempus elit. Ut tortor velit, aliquam in ornare vel, feugiat sed nibh. Donec fringilla est id odio lacinia vulputate. Donec nulla urna, congue sit amet pretium non, dictum at orci. Fusce neque sem, fermentum eu tempus nec, mattis venenatis sem. Proin scelerisque velit tristique urna mattis adipiscing. Proin mattis faucibus facilisis. Integer non lacus ac ligula accumsan convallis quis molestie erat. Curabitur imperdiet vestibulum vulputate. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris lacus ligula, hendrerit eget suscipit in, sollicitudin nec dui. Suspendisse euismod, lorem pretium gravida rhoncus, enim quam facilisis orci, nec volutpat nisi dolor id lacus. Proin dolor arcu, rutrum eget hendrerit vel, pharetra id elit. Nullam porta euismod suscipit. Pellentesque malesuada consequat sem, et auctor magna aliquam gravida. Nullam blandit dignissim iaculis. Suspendisse non diam nec augue scelerisque iaculis. Nam id dui sed lorem vulputate rhoncus eget eu tellus. In sit amet nisi nunc. Fusce sed aliquet sem. Aliquam sit amet metus metus.
Donec in mi a arcu cursus commodo non ut metus. Nunc id eros ut augue consequat tempus ut non ligula. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer pretium, erat sit amet scelerisque euismod, purus lectus convallis dui, eget imperdiet sapien est ut magna. Nullam elementum, tortor vitae pulvinar mattis, orci neque porta tortor, a feugiat nisi lacus quis diam. Ut gravida augue id est rutrum elementum. Mauris eget felis dolor. Phasellus ante ante, porttitor sit amet lobortis ut, suscipit id neque. Fusce hendrerit dolor nec odio eleifend in auctor enim cursus. Nullam fermentum pretium risus, in hendrerit nulla cursus sit amet. Fusce eu tempus elit. Ut tortor velit, aliquam in ornare vel, feugiat sed nibh. Donec fringilla est id odio lacinia vulputate. Donec nulla urna, congue sit amet pretium non, dictum at orci. Fusce neque sem, fermentum eu tempus nec, mattis venenatis sem. Proin scelerisque velit tristique urna mattis adipiscing. Proin mattis faucibus facilisis. Integer non lacus ac ligula accumsan convallis quis molestie erat. Curabitur imperdiet vestibulum vulputate. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris lacus ligula, hendrerit eget suscipit in, sollicitudin nec dui. Suspendisse euismod, lorem pretium gravida rhoncus, enim quam facilisis orci, nec volutpat nisi dolor id lacus. Proin dolor arcu, rutrum eget hendrerit vel, pharetra id elit. Nullam porta euismod suscipit. Pellentesque malesuada consequat sem, et auctor magna aliquam gravida. Nullam blandit dignissim iaculis. Suspendisse non diam nec augue scelerisque iaculis. Nam id dui sed lorem vulputate rhoncus eget eu tellus. In sit amet nisi nunc. Fusce sed aliquet sem. Aliquam sit amet metus metus.
Donec in mi a arcu cursus commodo non ut metus. Nunc id eros ut augue consequat tempus ut non ligula. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer pretium, erat sit amet scelerisque euismod, purus lectus convallis dui, eget imperdiet sapien est ut magna. Nullam elementum, tortor vitae pulvinar mattis, orci neque porta tortor, a feugiat nisi lacus quis diam. Ut gravida augue id est rutrum elementum. Mauris eget felis dolor. Phasellus ante ante, porttitor sit amet lobortis ut, suscipit id neque. Fusce hendrerit dolor nec odio eleifend in auctor enim cursus. Nullam fermentum pretium risus, in hendrerit nulla cursus sit amet. Fusce eu tempus elit. Ut tortor velit, aliquam in ornare vel, feugiat sed nibh. Donec fringilla est id odio lacinia vulputate. Donec nulla urna, congue sit amet pretium non, dictum at orci. Fusce neque sem, fermentum eu tempus nec, mattis venenatis sem. Proin scelerisque velit tristique urna mattis adipiscing. Proin mattis faucibus facilisis. Integer non lacus ac ligula accumsan convallis quis molestie erat. Curabitur imperdiet vestibulum vulputate. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris lacus ligula, hendrerit eget suscipit in, sollicitudin nec dui. Suspendisse euismod, lorem pretium gravida rhoncus, enim quam facilisis orci, nec volutpat nisi dolor id lacus. Proin dolor arcu, rutrum eget hendrerit vel, pharetra id elit. Nullam porta euismod suscipit. Pellentesque malesuada consequat sem, et auctor magna aliquam gravida. Nullam blandit dignissim iaculis. Suspendisse non diam nec augue scelerisque iaculis. Nam id dui sed lorem vulputate rhoncus eget eu tellus. In sit amet nisi nunc. Fusce sed aliquet sem. Aliquam sit amet metus metus.
Donec in mi a arcu cursus commodo non ut metus. Nunc id eros ut augue consequat tempus ut non ligula. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer pretium, erat sit amet scelerisque euismod, purus lectus convallis dui, eget imperdiet sapien est ut magna. Nullam elementum, tortor vitae pulvinar mattis, orci neque porta tortor, a feugiat nisi lacus quis diam. Ut gravida augue id est rutrum elementum. Mauris eget felis dolor. Phasellus ante ante, porttitor sit amet lobortis ut, suscipit id neque. Fusce hendrerit dolor nec odio eleifend in auctor enim cursus. Nullam fermentum pretium risus, in hendrerit nulla cursus sit amet. Fusce eu tempus elit. Ut tortor velit, aliquam in ornare vel, feugiat sed nibh. Donec fringilla est id odio lacinia vulputate. Donec nulla urna, congue sit amet pretium non, dictum at orci. Fusce neque sem, fermentum eu tempus nec, mattis venenatis sem. Proin scelerisque velit tristique urna mattis adipiscing. Proin mattis faucibus facilisis. Integer non lacus ac ligula accumsan convallis quis molestie erat. Curabitur imperdiet vestibulum vulputate. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris lacus ligula, hendrerit eget suscipit in, sollicitudin nec dui. Suspendisse euismod, lorem pretium gravida rhoncus, enim quam facilisis orci, nec volutpat nisi dolor id lacus. Proin dolor arcu, rutrum eget hendrerit vel, pharetra id elit. Nullam porta euismod suscipit. Pellentesque malesuada consequat sem, et auctor magna aliquam gravida. Nullam blandit dignissim iaculis. Suspendisse non diam nec augue scelerisque iaculis. Nam id dui sed lorem vulputate rhoncus eget eu tellus. In sit amet nisi nunc. Fusce sed aliquet sem. Aliquam sit amet metus metus.

Блог вебразработчика
Функциональное тестирование и продвижение сайтов

Яндекс.Метрика