Перейти к содержимому

Фотография

По поводу PageObject


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 31

#1 armag

armag

    Новый участник

  • Members
  • Pip
  • 53 сообщений

Отправлено 20 ноября 2013 - 07:24

Итак, решил попробовать переписать тесты с использованием PageObject и тут же встрял.
Тест писал аналогично https://code.google....iki/PageFactory

Начинаю я с обычного класса TestOne, в котором инициализирую страничку LoginPage, открываю url, которая забирается из класса config, и вызываю метод doLogin:
LoginPage page = PageFactory.initElements(driver, LoginPage.class);
page.open(config.getUrl());
page.doLogin("test", "asd");

Класс LoginPage:
@FindBy(id = "1")
	private WebElement loginTextBox;

...

public void doLogin(String login, String pass) {
		
		loginTextBox.sendKeys(login);
		...
	}

Возникает ошибка, что не найден элемент (Unable to find element with name == 1 (WARNING: The server did not provide any stacktrace information)).

Сообщение отредактировал armag: 20 ноября 2013 - 08:11

  • 0

#2 armag

armag

    Новый участник

  • Members
  • Pip
  • 53 сообщений

Отправлено 20 ноября 2013 - 07:44

Проблема в том, что при открытии страницы LoginPage - сначала открывается пустая страница, которая открывает новое окно со страницей логина. Исправилось таким кодом:

LoginPage page = PageFactory.initElements(driver, LoginPage.class);
page.open(cd.getUrl());
UtilPopups.SwitchToPopUpCloseParent(driver);
PageFactory.initElements(driver, LoginPage.class);

  • 0

#3 armag

armag

    Новый участник

  • Members
  • Pip
  • 53 сообщений

Отправлено 20 ноября 2013 - 08:09

Коллеги, но я так и не понял - как мне подгружать в аннотации типа:

@FindBy(id = "1")
private WebElement passTextBox;

вместо параметра "1" эту строчку из текстового файла? Я так понимаю в аннотацию нельзя подгрузить id из внешнего файла?
  • 0

#4 user12

user12

    Специалист

  • Members
  • PipPipPipPipPip
  • 894 сообщений
  • ФИО:Виктор
  • Город:Минск


Отправлено 20 ноября 2013 - 08:35

Я так понимаю в аннотацию нельзя подгрузить id из внешнего файла?


правильно понимаешь
  • 0

#5 armag

armag

    Новый участник

  • Members
  • Pip
  • 53 сообщений

Отправлено 20 ноября 2013 - 08:39


Я так понимаю в аннотацию нельзя подгрузить id из внешнего файла?


правильно понимаешь


Никакого решения данной проблемы не существует? То есть подгружать конфигурацию веб-страничек из внешних файлов нельзя?
Если это так, то в пень этот pagefactory :)
  • 0

#6 user12

user12

    Специалист

  • Members
  • PipPipPipPipPip
  • 894 сообщений
  • ФИО:Виктор
  • Город:Минск


Отправлено 20 ноября 2013 - 08:55

Никакого решения данной проблемы не существует?


Скажу за себя, я не знаю решения данной проблемы. Хотя оно м.б. и есть
  • 0

#7 aksas

aksas

    Активный участник

  • Members
  • PipPip
  • 130 сообщений
  • Город:Харьков

Отправлено 20 ноября 2013 - 10:13

Никакого решения данной проблемы не существует?

Попробуйте покопать в сторону FieldDecorator и PageFactory.initElements(FieldDecorator decorator, Object page) или initElements(ElementLocatorFactory factory, java.lang.Object page)
  • 0

#8 appmen

appmen

    Опытный участник

  • Members
  • PipPipPipPip
  • 408 сообщений
  • ФИО:Victor

Отправлено 20 ноября 2013 - 10:52

если можно сделать так
String fieldID = "1";
@FindBy(id = fieldID)
то можно очень просто сделать через проперти файлы
  • 0

#9 armag

armag

    Новый участник

  • Members
  • Pip
  • 53 сообщений

Отправлено 20 ноября 2013 - 11:09

если можно сделать так

String fieldID = "1";
@FindBy(id = fieldID)
то можно очень просто сделать через проперти файлы


А можно подробнее? Файл с пропертями читается уже в процессе выполнения программы, а PageFactory работает с переменными, которые инициализируются при создании экземпляра класса (насколько я понимаю). Что именно вы предлагаете сделать через проперти файлы?
  • 0

#10 armag

armag

    Новый участник

  • Members
  • Pip
  • 53 сообщений

Отправлено 20 ноября 2013 - 11:18

Никакого решения данной проблемы не существует?

Попробуйте покопать в сторону FieldDecorator и PageFactory.initElements(FieldDecorator decorator, Object page) или initElements(ElementLocatorFactory factory, java.lang.Object page)


Можно подробнее? Погуглив минут 30, я только лишь понял, что "decorators provide all the same methods as original WebElement, but adds several new methods to deal with forms, selects, checkboxes etc." Насколько я понимаю это лишь расширяет привычные веб-элементы, добавляя дополнительные методы :) Ну то есть чтобы не писать код типа:

Select SomeList = 
	new Select(driver.findElement(By.id(LoginPage.getSomeListId())));
SomeList.selectByIndex(0);

можно было писать

driver.findElement(By.id(LoginPage.getSomeListId())).selectByIndex(0);

Если я не прав и не туда полез копать - поправьте ;)
  • 0

#11 barancev

barancev

    Администратор

  • Admin
  • PipPipPipPipPipPip
  • 6 871 сообщений
  • ФИО:Алексей Баранцев
  • Город:Россия, Москва


Отправлено 20 ноября 2013 - 11:36

Голосуйте за https://code.google..../detail?id=3567
  • 0
Алексей Баранцев
Тренинги для тестировщиков (тестирование производительности, защищенности, тест-дизайн, автоматизация):
Линейка тренингов по Selenium

#12 armag

armag

    Новый участник

  • Members
  • Pip
  • 53 сообщений

Отправлено 20 ноября 2013 - 11:43

Голосуйте за https://code.google..../detail?id=3567


Как голосовать? ) Коммент оставить?
Алексей, то есть в случае хранения id-шников во внешнем хранилище - пока следует отказаться от PageFactory?
  • 0

#13 user12

user12

    Специалист

  • Members
  • PipPipPipPipPip
  • 894 сообщений
  • ФИО:Виктор
  • Город:Минск


Отправлено 20 ноября 2013 - 11:48

если можно сделать так

String fieldID = "1";
@FindBy(id = fieldID)
то можно очень просто сделать через проперти файлы

надо final String fieldID = "1"

И как я помню, там не получиться взять данные из проперти, будет кидать ошибку, типо "must be constant expression" - когда будет время, надо глянуть
  • 0

#14 aksas

aksas

    Активный участник

  • Members
  • PipPip
  • 130 сообщений
  • Город:Харьков

Отправлено 20 ноября 2013 - 13:08

Можно подробнее?

цепочка такая:
1. Расширяем org.openqa.selenium.support.pagefactory.Annotations пререопределяя buildByFromLongFindBy и buildByFromShortFindBy методы
2. Создаем свой ElementLocatorFactory и ElementLocator (по аналогии с DefaultElementLocator и DefaultElementLocatorFactory)
3. Используем initElements(ElementLocatorFactory factory, Object page) с нашей ElementLocatorFactory
4. Profit :)
  • 0

#15 armag

armag

    Новый участник

  • Members
  • Pip
  • 53 сообщений

Отправлено 20 ноября 2013 - 13:30

цепочка такая:
1. Расширяем org.openqa.selenium.support.pagefactory.Annotations пререопределяя buildByFromLongFindBy и buildByFromShortFindBy методы
2. Создаем свой ElementLocatorFactory и ElementLocator (по аналогии с DefaultElementLocator и DefaultElementLocatorFactory)
3. Используем initElements(ElementLocatorFactory factory, Object page) с нашей ElementLocatorFactory
4. Profit :)


Ничего не понял :( Если честно у меня когнитивный диссонанс возникает, когда я представляю, что полю класса буду присваивать значение на этапе инициализации с помощью вызова метода.
Мне нужно переписать класс, который реализует аннотации? Но ведь они определяются на этапе инициализации класса, так как являются его полями. Как мне нужно переопределить эти 2 метода? Вместо using передавать что-то или что? :)
  • 0

#16 aksas

aksas

    Активный участник

  • Members
  • PipPip
  • 130 сообщений
  • Город:Харьков

Отправлено 20 ноября 2013 - 14:14

Я не гарантирую работоспособность, это просто идея.
Договоримся, что селектор начинающийся с "ext" ищется гдето снаружи.
Тогда вместо Annotations
Скрытый текст


соответственно вместо ElementLocator
Скрытый текст


фабрика элементов
Скрытый текст


и фабрика страниц
Скрытый текст


и теперь можно попробовать
LoginPage page = ExternalPageFactory.initElements(driver, LoginPage.class);
для
@FindBy(id = "extLoginButton")
private WebElement loginTextBox;

Если заработает, отпишиетсь. Аж самому интересно, а поробовать возможности нет :)

Сообщение отредактировал aksas: 20 ноября 2013 - 14:17

  • 0

#17 aksas

aksas

    Активный участник

  • Members
  • PipPip
  • 130 сообщений
  • Город:Харьков

Отправлено 20 ноября 2013 - 15:40

Аж самому интересно, а поробовать возможности нет :)


Добрался до дома и попробовал - в таком виде не работает, но направление верное :)

Значит так: фабрику страниц делать не надо, просто нужно по другому инициализровать PageObject
LoginPage page = new LoginPage();
PageFactory.initElements(new ExternalElementLocatorFactory(driver), page);
page.login();

и в таком виде все отлично работает :crazy:
  • 0

#18 armag

armag

    Новый участник

  • Members
  • Pip
  • 53 сообщений

Отправлено 21 ноября 2013 - 06:36

все отлично работает


Добрый день. Я так понимаю весь смысл в этом блоке:
protected String getSelector(String sel){
        if(sel.startsWith("ext")){
                String key = sel.substring(3);
                //find our selector by key
                sel = ...;
        }
        return sel;
  }

В общем я сейчас полтора часа просидел и придумал как бы это все сделать:
1) Создаем объект LoginPage (сделано)
2) В него подгружаем элементы loginTextBox и passTextBox из файла (сделано)
3) Теперь в моем классе LoginPage есть эти поля и геттеры (сделано)
4) Копируем код класса ExternalAnnotations (сделано)

Дальше у меня проблема. Я написал метод, который в зависимости от значения key вызывает соответствующий геттер класса LoginPage :))) Однако, из ExternalAnnotations не могу обратиться к методам LoginPage. Единственное, что разрешает эклипс, это:
sel = LoginPage.this.getElement(key);

Ругается на "No enclosing instance of the type LoginPage is accessible."
Судя по гуглению stock overflow - нужно передавать экземпляр класса в ExternalAnnotations, но если у меня страниц в проекте будет 100? :))))
Что я делаю не так, подскажите ;)
  • 0

#19 aksas

aksas

    Активный участник

  • Members
  • PipPip
  • 130 сообщений
  • Город:Харьков

Отправлено 21 ноября 2013 - 10:23

Я так понимаю весь смысл в этом блоке:

Все верно.

Дальше у меня проблема. Я написал метод, который в зависимости от значения key вызывает соответствующий геттер класса LoginPage :))) Однако, из ExternalAnnotations не могу обратиться к методам LoginPage. Единственное, что разрешает эклипс, это:
sel = LoginPage.this.getElement(key);


А вот тут уже я не понял :) Я не сильно понимаю как вы храните селекторы, но подразумевалось что у вас общее хранилище для них, например проперти файл. А если для каждого PageObject свое хранилище, то тогда мое решение не сильно подходит. Поизвращаться конечно можно...

Давайте вы выложите сюда код PageObject?
  • 0

#20 armag

armag

    Новый участник

  • Members
  • Pip
  • 53 сообщений

Отправлено 21 ноября 2013 - 10:36


Дальше у меня проблема. Я написал метод, который в зависимости от значения key вызывает соответствующий геттер класса LoginPage :))) Однако, из ExternalAnnotations не могу обратиться к методам LoginPage. Единственное, что разрешает эклипс, это:
sel = LoginPage.this.getElement(key);


А вот тут уже я не понял :) Я не сильно понимаю как вы храните селекторы, но подразумевалось что у вас общее хранилище для них, например проперти файл. А если для каждого PageObject свое хранилище, то тогда мое решение не сильно подходит. Поизвращаться конечно можно...

Давайте вы выложите сюда код PageObject?


Я так понимаю вы предлагаете вообще ВСЕ айди локаторов хранить в одном большом файле? Но ведь какие-то страницы в каких-то кейсах не участвуют и зачем мне подгружать весь массив данных? Я думал подгружать локаторы из файла перед вызовом метода return new (PageObject).

Вот код LoginPage:
public class LoginPage {
		
	@FindBy(id = "extLoginTextBox")
	private WebElement loginTextBox;
	
	@FindBy(id = "extPassTextBox")
	private WebElement passTextBox;
	
	protected WebDriver driver;
	
	private String loginTextBoxInner = ""; // Обозвал поля иначе, чтобы не пересекались строки с вебэлементами
	private String passTextBoxInner = ""; // Обозвал поля иначе, чтобы не пересекались строки с вебэлементами
	
	public enum LoginPageElements { loginTextBox, passTextBox }
	
	public LoginPage (WebDriver driver) throws IOException {
		
		this.driver = driver;
		
	}
	
	public void open (String url) {
		
		driver.get(url);
		
	}
	
	public void doLogin(String login, String pass) {
		
		loginTextBox.sendKeys(login);
		passTextBox.sendKeys(pass);
                // Дальше здесь я хотел создавать экземпляр класса MainWindow 
                // (которое после логина открывается) с инициализацией его локаторов
                // И дальше здесь я хотел инициализировать PageFactory
                // И возвращать новый объект-страницу MainWindow
		
	}

	// Это быдло-код, который читает массив вида param;value и присваивает полям класса содержимое value для соответствующего param
	public LoginPage(String[][] aParams) {
		for (int i = 0; i < aParams.length; i++) {
			if (!(aParams[i][0]==null))
			if (aParams[i][0].equals("loginTextBox")) this.loginTextBoxInner = aParams[i][1];
			else if (aParams[i][0].equals("passTextBox")) this.passTextBoxInner = aParams[i][1];
		}
	}
	
	public String getLoginTextBoxId() {
		return this.loginTextBoxInner;
	}
	
	public String getPassTextBoxId() {
		return this.passTextBoxInner;
	}
	
        // Метод, который в зависимости от key, полученного из Annotations, будет вызывать соответствующий геттер
	public String getElement (String key) {
		String output = "";
		if (key == "LoginTextBox") output = getLoginTextBoxId();
		else if (key == "PassTextBox") output = getPassTextBoxId();
		return output;
	}
	
	
}

  • 0


Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных