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

Фотография

WaitForElementPresent


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

#1 Biasha

Biasha

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

  • Members
  • PipPip
  • 130 сообщений
  • Город:СПб

Отправлено 09 октября 2008 - 09:17

Коллеги, кто может посоветовать:
В Selenium IDE есть функция waitForElementPresent, ее очень удобно использовать, чтобы тест не валился из-за того, что не успевает найти какую-нибудь линку или кнопку на форме.
В RC такой функции не нашла, есть только isElementPresent, возвращает булевское значение есть ли элемент. И чтобы дождаться появления элемента на форме, приходится писать такую конструкцию:

while (!browser.isElementPresent("AnyButton"))
browser.setTimeout("10000");

Есть ли возможность делать проще?
  • 0
Молодой пожарный не боится пламя!

#2 popo_kid

popo_kid

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

  • Members
  • PipPip
  • 79 сообщений

Отправлено 09 октября 2008 - 09:57

while (!browser.isElementPresent("AnyButton"))
browser.setTimeout("10000");

Есть ли возможность делать проще?

сдается мне, что данная конструкция работает не так как вы ожидаете =) setTimeout ни как не влияет на функцию isElementPresent.
кстати, если элемент так и не появится, то у вас будет бесконечный цикл

PS: 1) лучше напишите свой класс унаследованный от DefaultSelenium, и дополните его своими функциям
2) для клиентских либ есть документация
  • 0

#3 Biasha

Biasha

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

  • Members
  • PipPip
  • 130 сообщений
  • Город:СПб

Отправлено 09 октября 2008 - 10:53

То, что setTimeout не влияет на появление элемента понятно и так) просто таким образом вставляется некая временная задержка, необходимая для появления элемента на форме. Вопрос в том, есть ли встроенная функция для этих целей?
  • 0
Молодой пожарный не боится пламя!

#4 NLord

NLord

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

  • Members
  • PipPip
  • 108 сообщений

Отправлено 09 октября 2008 - 10:59

То, что setTimeout не влияет на появление элемента понятно и так) просто таким образом вставляется некая временная задержка, необходимая для появления элемента на форме. Вопрос в том, есть ли встроенная функция для этих целей?


public boolean waitForElementPresent(String elementToWaitForLocator) {
		boolean resultFlag = false;
		for (int second = 0; second <= Integer.parseInt(Constants.WaitFor_DELAY); second++) {
			if (selenium.isElementPresent(elementToWaitForLocator)) {
				resultFlag = true;
				break;
			} else {
				resultFlag = false;
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		return resultFlag;
	}

Сообщение отредактировал NLord: 13 октября 2008 - 09:54

  • 0
"Меня терзают смутные сомненья..." что это работает.

#5 popo_kid

popo_kid

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

  • Members
  • PipPip
  • 79 сообщений

Отправлено 09 октября 2008 - 11:03

То, что setTimeout не влияет на появление элемента понятно и так) просто таким образом вставляется некая временная задержка, необходимая для появления элемента на форме. Вопрос в том, есть ли встроенная функция для этих целей?

setTimeout - не вставляет задержку на N-ое количество миллисекунд, у вас постояно долбиться browser.isElementPresent("AnyButton") без какой-либо задержки, до самого появления элемента

встроенной функции нет, по крайней мере в либе для c#, с другими языками не работал. Мб они и содержат какие-нить дополнительные функции
  • 0

#6 popo_kid

popo_kid

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

  • Members
  • PipPip
  • 79 сообщений

Отправлено 09 октября 2008 - 11:06

public boolean waitForElementPresent(String elementToWaitFor)

ну таким макаром человек точно не научится документацию читать :acute:
  • 0

#7 Biasha

Biasha

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

  • Members
  • PipPip
  • 130 сообщений
  • Город:СПб

Отправлено 13 октября 2008 - 08:44

Спасибо за ответ. Указанный код работает, что неудивительно.

Что интересно - в доках говорят о классе Wait (http://release.openq...0.9.2/doc/java/).
Пока что-то не разобралась, но видимо это еще один вариант решения.
  • 0
Молодой пожарный не боится пламя!

#8 vitorg

vitorg

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

  • Members
  • PipPipPipPip
  • 408 сообщений

Отправлено 13 октября 2008 - 18:39

Спасибо за ответ. Указанный код работает, что неудивительно.

Что интересно - в доках говорят о классе Wait (http://release.openq...0.9.2/doc/java/).
Пока что-то не разобралась, но видимо это еще один вариант решения.


Очень не рекомендую использовать в данном случае класс Wait... да и вообще мало где его можно применить в тестах на Selenium.
Тебе необходимо расширить DefaultSelenium и добавить следующий код:

/**
	 * Waiting for element to appear/disappear on page for specified time (means not element visibility but really
	 * present/not present like in {@link com.thoughtworks.selenium.Selenium#isElementPresent(String)} method).
	 *
	 * @param locator an element locator.
	 * @param timeout time to wait in milliseconds after which {@link TimeoutException} will be thrown.
	 * @param present true - wait until element appear, false - wait until element disappear.
	 * @since Selenium RC 0.9.2.
	 */
	public void waitForElement(String locator, String timeout, boolean present) {
		String logMessage = "Waiting for element '" + locator + "' to " + (present ? "" : "dis") + "appear for " + timeout + " milliseconds... Element ";
		try {
			waitForCondition("var element;" +
					"try{" +
					" element = selenium.browserbot.findElement('" + locator.replaceAll("'", "\\\\'") + "');" +
					"} catch(e){" +
					" element = null;" +
					"}" +
					"element" + (present ? "!=" : "==") + "null;", timeout);
			logMessage += (present ? "" : "dis") + "appear.";
		} catch (SeleniumException e) {
			logMessage += "didn't " + (present ? "" : "dis") + "appear as expected!";
			throw new RunTimeException(logMessage, e);
		} finally {
			LOG.trace(logMessage);
		}
	}

	/**
	 * Waiting for element to appear on page for specified time. It's the same as {@link #waitForElement(String, String,
	 * boolean)} when the third parameter is true.
	 *
	 * @param locator an element locator.
	 * @param timeout time to wait in milliseconds after which {@link TimeoutException} will be thrown.
	 * @since SeleniumRC 0.9.2.
	 */
	public void waitForElementAppear(String locator, String timeout) {
		waitForElement(locator, timeout, true);
	}

	/**
	 * Waiting for element to disappear on page for specified time. It's the same as {@link #waitForElement(String,
	 * String, boolean)} when the third parameter is false.
	 *
	 * @param locator an element locator.
	 * @param timeout time to wait in milliseconds after which {@link TimeoutException} will be thrown.
	 * @since SeleniumRC 0.9.2.
	 */
	public void waitForElementDisappear(String locator, String timeout) {
		waitForElement(locator, timeout, false);
	}

Теперь должно быть понятно почему использование класса Wait плохо.

PS: приведённый в 4-м посте код страдает теми же проблемами, что и решение с Wait.
  • 1

#9 NLord

NLord

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

  • Members
  • PipPip
  • 108 сообщений

Отправлено 14 октября 2008 - 06:22

Спасибо за ответ. Указанный код работает, что неудивительно.

Что интересно - в доках говорят о классе Wait (http://release.openq...0.9.2/doc/java/).
Пока что-то не разобралась, но видимо это еще один вариант решения.


Очень не рекомендую использовать в данном случае класс Wait... да и вообще мало где его можно применить в тестах на Selenium.
...

Теперь должно быть понятно почему использование класса Wait плохо.

PS: приведённый в 4-м посте код страдает теми же проблемами, что и решение с Wait.


Не понятно :). Объясните, по возможности, в чём принципиальная порочность подхода? Ибо вездесущие "не рекомендуется" убеждают слабо, а работающий код чуть сильнее. Хотя, с Вашего разрешения, возьму Ваш код на вооружение :).
  • 0

#10 vitorg

vitorg

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

  • Members
  • PipPipPipPip
  • 408 сообщений

Отправлено 14 октября 2008 - 09:53

Не понятно :). Объясните, по возможности, в чём принципиальная порочность подхода? Ибо вездесущие "не рекомендуется" убеждают слабо, а работающий код чуть сильнее. Хотя, с Вашего разрешения, возьму Ваш код на вооружение :).

При использовании класса Wait и т.п. мы файтически в цикле вызываем метод
DefaultSelenium#isElementPresent(String)

Этот вызов приводит к обращению драйвера к SeleniumRC по HTTP-протоколу, вызову команды JS через SeleniumCore самим RC и возврату результата обратно в драйвер. Само собой дело это не быстрое, а когда у нас цикл, то таких цепочек у нас может быть достаточно много, соответственно временное разрешение у нас очень маленькое (количество проверок в единицу времени). Кроме того что это расточительно, у нас может быть достаточно динамичное приложение и элемент мог не только появиться, но и уже исчезнуть, причём несколько раз.

При использовании метода
DefaultSelenium#waitForCondition(String, String)
Происходит единственный запрос от драйвера к SeleniumRC и дальше цикл проверки на появление/исчезновение элемента выполняется только на стороне браузера JavaScript'ом. В этом случае мы имеем временное разрешение примерно того же порядка, что и скорость работы самого тестируемого Web-приложения.

Немного сумбурно, но думаю понятно :)
  • 1

#11 NLord

NLord

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

  • Members
  • PipPip
  • 108 сообщений

Отправлено 14 октября 2008 - 11:21

...

При использовании метода

DefaultSelenium#waitForCondition(String, String)
Происходит единственный запрос от драйвера к SeleniumRC и дальше цикл проверки на появление/исчезновение элемента выполняется только на стороне браузера JavaScript'ом. В этом случае мы имеем временное разрешение примерно того же порядка, что и скорость работы самого тестируемого Web-приложения.

Немного сумбурно, но думаю понятно :)


Спасибо, Вы первый, кто мне смог это внятно объяснить :).
  • 0

#12 Biasha

Biasha

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

  • Members
  • PipPip
  • 130 сообщений
  • Город:СПб

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

Скажите пожалуйста, что за объект LOG в этом примере?

LOG.trace(logMessage);
  • 0
Молодой пожарный не боится пламя!

#13 NLord

NLord

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

  • Members
  • PipPip
  • 108 сообщений

Отправлено 12 ноября 2008 - 10:34

Скажите пожалуйста, что за объект LOG в этом примере?

LOG.trace(logMessage);


Скорее всего используется log4j.
  • 0
"Меня терзают смутные сомненья..." что это работает.

#14 vitorg

vitorg

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

  • Members
  • PipPipPipPip
  • 408 сообщений

Отправлено 12 ноября 2008 - 16:29

Да, это обычный логгер, я использую log4j, но обычно рекомендуют commons-logging (если не требуется Level.OFF). В общем, это необязательный объект, можно все строчки с ним удалить.
  • 0

#15 MoleX

MoleX

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

  • Members
  • Pip
  • 18 сообщений
  • ФИО:Олег
  • Город:Новосибирск, Россия

Отправлено 17 ноября 2008 - 06:03

так ить в IDE есть конвертор в java rc, он как то попроще переделывает :)

for (int second = 0;; second++) {
if (second >= 60) fail("timeout");
try { if (selenium.isElementPresent("Anybutton")) break; } catch (Exception e) {}
Thread.sleep(1000);
}
  • 0

#16 vitorg

vitorg

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

  • Members
  • PipPipPipPip
  • 408 сообщений

Отправлено 17 ноября 2008 - 12:25

так ить в IDE есть конвертор в java rc, он как то попроще переделывает :)

Попроще, но очень часто этот вариант оказывается неприменим, почему - я уже писал, см. здесь
  • 0

#17 ezha

ezha

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

  • Members
  • Pip
  • 13 сообщений
  • ФИО:Зоя

Отправлено 18 ноября 2008 - 15:47

waitForCondition умеет работать и с командами самого селениума. То есть можно написать просто:
selenium.waitForCondition("selenium.isElementPresent(\"" + locator + "\")", "10000");

или ждем, что элемент исчезнет:
selenium.waitForCondition("!selenium.isElementPresent(\"" + locator + "\")", "10000");

При этом "selenium." в условии - эт ключевое слово, дальше должно быть название команды из DefaultSelenium. То есть если вы этот класс расширили, нифига wait for condition новое не возьмет, только стандартные. Нужно конеш еще в код заглянуть, и убедиться что все работает именно так :)
  • 0
Завтра. Будет.

#18 vitorg

vitorg

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

  • Members
  • PipPipPipPip
  • 408 сообщений

Отправлено 19 ноября 2008 - 09:31

Интересно, не знал что в контексте управляющего фрейма доступен этот объект напрямую.
По поводу того, что команда должна быть из DefaultSelenium, видимо, не совсем так, команда должна быть одной из допустимых в SeleniumCore, так?
  • 0

#19 Biasha

Biasha

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

  • Members
  • PipPip
  • 130 сообщений
  • Город:СПб

Отправлено 19 ноября 2008 - 09:59

У меня указанный код работает и для переопределенного селениума:

private mySelenium selenium;
public void setUp() {
selenium = new mySelenium("localhost",
4444, "*firefox", "http://demo.soft.com...lder/page.aspx");
selenium.start();
}
...
selenium.waitForCondition("selenium.isElementPresent(\""+ "LoginTextBox" +"\")", "10000");
...

Вот только селениум должен называться selenium (private mySelenium selenium), а не как-то иначе типа (private mySelenium myBrowser)

Спасибо))
  • 0
Молодой пожарный не боится пламя!

#20 vitorg

vitorg

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

  • Members
  • PipPipPipPip
  • 408 сообщений

Отправлено 19 ноября 2008 - 10:14

У меня указанный код работает и для переопределенного селениума:


Переопределённый он или нет - не важно, имелось ввиду, что работают только методы из DefaultSelenium, а если были добавлены новые, то эти новые естественно работать в waitForCondition не будут. Я думаю, что и DefaultSelenium здесь ни при чём, а методы могут быть использованы любые, которые позволяет именно Selenium Core.

Вот только селениум должен называться selenium (private mySelenium selenium), а не как-то иначе типа (private mySelenium myBrowser)

Вот в этом сильно сомневаюсь, Selenium RC, а уж тем более Selenium Core знать ничего не знают про переменные теста и ему это должно быть совершенно безразлично. Т.е. ссылка на объект, соответствующий интерфейсу Selenium может называться как угодно, но в waitForCondition всегда надо писать "selenium".
  • 0


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

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