Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

Не могу получить текст любого веб элемента с сайта http://booking.uz.gov.ua (JAVA)


(ValentinT) #1

После запуска через Junit код выполняется , но не могу получить текст в консоль (только с этого сайта ) , пожалуйста не пинайте так как только стал на путь WebDriver с Java

        public abstract class AbstractPage {
	 protected WebDriver driver ;  
	 
	 public AbstractPage(WebDriver driver) {
		this.driver = driver ; 
	}
}
	
	     
    public class HomePage extends AbstractPage {
	 	
	public HomePage (WebDriver driver) { 
			super(driver) ; 
			PageFactory.initElements(driver,this) ;
	 }
 
	
	 @FindBy (xpath=".//*[@id='stations_from']//div[1]") 
		private WebElement suggestChoiceStationFrom;
	 
	 @FindBy (xpath=".//*[@id='stations_till']//div[1]") 
		private WebElement suggestChoiceStationTill;
	
	
	@FindBy (xpath=".//*[@id='station_from']/input") 
	private WebElement textFieldFrom ;
	  
	@FindBy (xpath=".//*[@id='station_till']/input") 
	private WebElement textFieldTill ;
	
	 @FindBy (xpath="//button[@name='search']") 
	private WebElement searchButton;
	 
	 @FindBy (xpath=".//*[@id='date_dep']") 
	private WebElement chooseFieldDateTrip;
	 
	public TrainPage searchTrains  (String stationFrom , String stationTill , String date) {
		textFieldFrom.sendKeys(stationFrom);
		textFieldTill.sendKeys(stationTill);
		suggestChoiceStationFrom.click();
		suggestChoiceStationTill.click();
		setDate(date);		 
		searchButton.click();
		return new TrainPage(driver)  ; 
	}
	
	private  void setDate (String date) {
		chooseFieldDateTrip.clear();
		chooseFieldDateTrip.sendKeys(date);
		
	}
}

    public class ResultPage extends AbstractPage{
	
	@FindBy (xpath="//*[@id='ts_res_tbl']//a")
	private List<WebElement> numberTrains ;
	
	 
	public ResultPage(WebDriver driver) { 
		super(driver) ; 
		PageFactory.initElements(driver,this) ;
		
	}	
	public void getNumberTrains () {
		for (WebElement e : numberTrains) {
			System.out.println(e.getText()) ;
		}
		  
	}
}

    public class PageTest {
	private WebDriver driver ;
	private final String baseUrl = "http://booking.uz.gov.ua/ru/" ; 
    private HomePage homePage ;
    private TrainPage trainPage ;
    private ResultPage resultPage ;
 
	@Before 
	public void setUp () {
		driver = new FirefoxDriver ()  ;
		driver.get(baseUrl);
	}
	
	@Test
	public void searchTrain () {
	      homePage = new HomePage (driver) ; 
	      trainPage=new TrainPage(driver) ; 
	      resultPage = new ResultPage(driver) ;
	      trainPage = homePage.searchTrains ("Львов","Киев" ,"29.11.2013" );
	      resultPage.getNumberTrains () ;
	      
	}
} 

(Сергей Блохин) #2

С сайтом всё хорошо. Это уже должно радовать.

# encoding: utf-8
# file: get_text.rb
# lang: ruby
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
driver.get 'http://booking.uz.gov.ua'
element = driver.find_element :xpath, '//*[@id="langs"]/li[1]/a/b'
element.text # => "укр" 

(Дмитрий Жарий) #3

@vtimchenko87, сперва, проверьте какая версия WebDriver, которую вы используете. Всегда используйте последнюю, ну или, хотя-бы чтобы она была > 2.30

:warning: только в диагностических целях, перед сбором информации с таблицы, поставьте
Thread.sleep(4000);
Если тест отработает правильно, замените Thread.sleep(4000); на метод класса WebDriverWait

Локатор для ссылок в таблице у вас правильный. Я подозреваю, что либо таблица не успела погрузиться, либо по направлению не было поездов в указанное время.


(ValentinT) #4

Да , получил текст с этого xpath '//*[@id="langs"]/li[1]/a/b' , но почему не могу получить текст с этого элемента "//*[@id='ts_res_tbl']//tr[1]/td[1]/a" ?


(ValentinT) #5

Спасибо , но WebDriver 2.35.0


(ValentinT) #6

Дмитрий спасибо Вам огромное тест отработал когда дописал Thread.sleep(4000);


(ValentinT) #7

На этот метод заменить нужно driver.manage().timeouts().implicitlyWait(4, TimeUnit.SECONDS); ?


(Дмитрий Жарий) #8

Есть разные подходы, implicit wait будет действовать глообально на все элементы.
WebDriverWait действует локально и ожидает выполнения некоторого условия, вот есть такая тема

Есть еще такая статья про варианты ожиданий:

http://xpinjection.com/2013/04/04/waits-and-timeouts-in-webdriver/


(Александр Таранков) #9

Попробуй также AjaxElementLocatorFactory, возможно этот механизм лучше подойдет


(ValentinT) #10

Спасибо Вам Александр


(mamax) #11

заинтересовала данная тематика!
Так как часто ежу домой и в Киев решил тоже написать свой фреймворк для booking.uz.gov.ua!
драйвер проходиться по кнопкам “Выбрать” и оставляет заказы в корзину, потом делает скриншот и через каждые 30 мин этот скрин приходит на почту! Таким образом мы можем видеть все поезда и их стоимость по данному направлению и в выбранное время, просто зайдя в свой почтовый ящик!

Ссылка на гитхаб
https://github.com/mamax/bookingTrains


Азы архитектуры фреймворка на PageObjects
(vmaximv) #12

Критиковать и ругать можно? :slight_smile:


(Дмитрий Жарий) #13

А есть чем? :smiley:

Как по мне, то достаточно чистый код:

  • Четко выделенные методы действия в PageObject’ ах, например в OrderPage.java
  • В OrderTest.java достаточно четко выраженный код сценария.

В SendMail, конечно, накручено с кучей параметров. Я бы вынес эти 16 параметров лучше в отдельный класс, и принимал бы его как единственный параметр в SendMail.sendMail


(vmaximv) #14

Закрыв глаза на сoding conventions, локаторы и т.д., я не говорю, что это очень плохой код - бывает в разы хуже, но и на идеальный он тоже не тянет. Поэтому и спрашиваю - важна ли для автора критика.


(mamax) #15

критика приветствуется


(vmaximv) #16

Ну если бегло:

  1. Зачем так сложно?
orderPage = PageFactory.initElements(getWebdriver(), OrderPage.class);
return PageFactory.initElements(driver, ResultPage.class);
  1. Зачем использовать ExpectedConditions.visibilityOfElementLocated(), если можно задекларить элементы и использовать visibilityOf(WebElement element)?

  2. Локаторы в тестах - это не тру, хардкод - тоже.

                resultPage = orderPage.getBilet("Êèåâ", "Âèííèöà", "19.12.2013", "18:00");
                resultPage.WaitForPageToLoadByCss(".num");
  1. Слипы тоже
Thread.sleep(4000L);
  1. Трай-кэтч, за редким исключением, тоже. Особенно с кэтченьем всего-и-вся: catch(Exception e).
    Здесь, если бельё в поезде отсутствует, скрипт будет честно ждать 8 секунд имплисит вейта, которые абсолютно не нужны. Куда более гармонично будет выглядеть что-нибудь isExist(WebElement el), который будет сетать имплисит вейт в ноль, а потом восстанавливать. Что-то вроде https://code.google.com/p/selenium/issues/detail?id=1880#c10.
                        try{                                
                                if (Postel.isSelected()){
                                        Postel.click();
                                }                                
                        }catch(Exception e){ 
                                System.out.println("error - there is no Postel in this train "+ e.getMessage());
                                e.printStackTrace();                                
                        }
  1. Зачем такие извращения с public static void main(String[] args) и мавеном, когда у листенера testng есть onFinish(ITestContext testContext)?
  2. Ну и не удержусь - там же вполне вменяемый локатор рисуется?
 @FindBy (xpath="//tbody/tr/td[4]/div[1]/label/input")

(mamax) #17

привет!
спасибо! дельные комментарии! я согласен! перезалил!
по пункту 3 там по другому было непросто выкрутиться,чтобы дождаться блочка(он яваскриптом подтягивается) но я вспомнил про Xpath)
4. - если использовать конструкцию

public static boolean isPresentAndDisplayed(final WebElement element) {
  try {
    return element.isDisplayed();
  } catch (NoSuchElementException e) {
    return false;
  }
}

то тут тоже по имплиситу нужно ждать!
5. Знаю лутше тянуть джарники мейвеном, но пока руки не дошли нормально разобраться, с антом как-то проще
6. исправил


(Дмитрий Жарий) #18

Я для себя выбрал такой путь, что имплисит вейт у меня по дефолту – ноль.
Для проверки, использую код, похожий на тот, что приведенный по ссылке, но усложненный обстоятельствами:

  1. Отлавливаю не все Exceptions, а только от вебдрайвера, и сохраняю ошибки в переменную. Это необходимо для того, чтобы в случае таймаута вывести предыдущию ошибку в лог
  2. Поддерживается таймаут в ожидании. Да… было один раз, что скрипт хотел ожидать элемента вечсность. Пришлось убить и таймаут добавить.
  3. Есть метод с одним параметром и таймаутом по умолчанию.

На C# есть очень удобная конструкция методов-расширений, и в реальном коде, это выглядет так:

// внутри пейджобжекта
this.txtLoginField.Wait().SendKeys(“hello”)

Т.е. Wait-у неявно прийдет параметр txtLoginField, которого он и будет ждать.

А в Java-подобном варианте, это бы вглядело так:

UntilVisible(this.txtLoginField).SendKeys(“hello”);
       public static IWebElement UntilVisible(IWebElement element, TimeSpan timeOut)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();

            while (true)
            {
                WebDriverException lastException = null;
                try
                {
                    if (element.Displayed)
                    {
                        return element;
                    }
                    System.Threading.Thread.Sleep(100);
                }
                catch (ElementNotVisibleException e)     { lastException = e; }
                catch (NoSuchElementException e)         { lastException = e; }
                catch (StaleElementReferenceException e) { lastException = e; }

                if (sw.Elapsed > timeOut)
                {
                    string exceptionMessage = lastException == null ? "" : lastException.Message;
                    string errorMessage = string.Format("Wait.UntilVisible: Element was not displayed after {0} Milliseconds" +
                                                        "\r\n Error Message:\r\n{1}", timeOut.TotalMilliseconds, exceptionMessage);
                    throw new TimeoutException(errorMessage);
                }
            }
        }

(vmaximv) #19

Мелочи поправили, а основное либо не поняли, либо не исправили.
Попробую на пальцах:
A. Почему не сделать так, и навсегда забыть о PageFactory и getWebDriver()?

        public Page() {
                this.driver = getWebDriver();
                PageFactory.initElements(driver, this);
        }

B. То, что вы объявили переменные “String fromCity” и т.д. ничего не меняет - это все равно хардкод, ровно как и magic numbers, а-ля “new WebDriverWait(driver, 10)” и прочее. Входные данные на то и “входные” - они должны быть отдельно, особенно в данном случае. Вот например скачал я с гит хаба и хочу использовать, вот только незадача - мне надо направление Киев-Минск в 11-00, в Киев 11.01.2014, а обратно 14-го, да и email надо бы изменить. И да - джаву я не знаю. Вы представляете сколько мне времени придется потратить, изучая сорсы, что бы найти где-что поменять? В одном только SendEmail адрес нужно поменять в 4-х местах.

С. У вас люто-бешено закручена отправка emails. Я, признаться, впал в пятиминутный ступор, когда пытался в этом разобраться. К чему эта гора таргетов в build.xml и void main(String[] args), когда более логично это бы смотрелось в листенере по onFinish()?


(Дмитрий Жарий) #20

*:rage2: @vmaximv is on killing spree *

Уполномоченный званием модератора, данным мне великим основателем этого форума,

за острые высказывания, переполненные нетерпимостью к коду
отпугивание потенциальных контрибъютеров
и архитектурную дискриминацию

присуждаю @vmaximv вот это: :poop: