Это самая масштабная внешняя IT-конференция ЕРАМ. На ней наши специалисты рассказывают о том, с какими необычными задачами сталкивались на проектах и как находили решения. А еще делятся ценными лайфхаками.
В данный момент оптимизирую свой тестовый проект для приложения на Silverlight 5. Использую классы из UITesting (в редких случаях из UI Automation). Как вариант оптимизации и повышения устойчивости, решил проставить методы вида WaitForControlXXX в необходимых на мой взгляд местах. И первое, с чем столкнулся - мое ожидание того как эти методы должны работать расходится с практическим результатом.
Поясню на примере: создал простой UserControl в Silverlight, который состоит из двух кнопок, одна из которых при запуске не видна. При нажатии на первую кнопку (First) становится видна вторая - Second. А при нажатии на Second программно добавляется третья кнопка - Third. Сделал сопутствующий CodedUITest-проект, в котором планировал проверить работу методов класса UITestControl: WaitForControlPropertyNotEqual (для кнопки Second) и WaitForControlExists - для кнопки Third.
Silverlight-контрол очень простой (развертывается в простом Web-проекте и запускается в браузере):
Теперь самое главное, что я ожидал и что я получил. Тестовый метод выглядит следующим образом:
WaitForXxxxMapClasses.WaitForXxxxMap uimap = new WaitForXxxxMapClasses.WaitForXxxxMap(); // моя UIMap, которую я получил с помощью UI test builder.
//
SilverlightButton first = uimap.UIWaitForXxxxTestingInWindow.UIWaitForXxxxTestingDocument.UISilverlightControlHoPane.UIItemCustom.UIMainPageMainPage.UIFirstButton;
SilverlightButton second = uimap.UIWaitForXxxxTestingInWindow.UIWaitForXxxxTestingDocument.UISilverlightControlHoPane.UIItemCustom.UIMainPageMainPage.UISecondButton;
SilverlightButton third = uimap.UIWaitForXxxxTestingInWindow.UIWaitForXxxxTestingDocument.UISilverlightControlHoPane.UIItemCustom.UIMainPageMainPage.UIThirdButton;
Я ожидал, что метод WaitForControlPropertyNotEqual для кнопки second должен блокировать ход выполнения тестового метода до тех пор, пока высота кнопки не станет больше 0 (т.е. кнопка станет видимой) или пока не кончится время по умолчанию. В MSDN написано так: Blocks the current thread until the specified property of this control is not equal to the specified value, or until the default time-out expires./
Конечно я проверил значение Height - оно равно 0 и параметры объекта Playback.PlaybackSettings, вот они на момент выполнения метода:
Как я понял, функция должна ожидать WaitForReadyTimeout милисекунд и уже потом завершаться ошибкой. Я же планировал нажать на первую кнопку спустя несколько секунд после старта теста и увидеть, как тест нажмет на вторую кнопку, чтобы появилась третья :). Но все оказалось не так...
На самом деле: WaitForControlPropertyNotEqual ничего не ждет - алгоритм продолжается без всяких видимых! пауз и пытается нажать на кнопку, у которой нулевые высота и ширина, а BoundingRectangle вообще с отрицательными величинами (глянул на всякий случай). И сразу появляется ошибка:
...Microsoft.VisualStudio.TestTools.UITest.Extension.PlaybackFailureException: Cannot perform 'Click' on the control. Additional Details: The control details were not specified. ...
А если используем такое нажатие: Mouse.Click(second);, то ошибка примерно все равно о том же: ...
Microsoft.VisualStudio.TestTools.UITest.Extension.FailedToPerformActionOnHiddenControlException: Cannot perform 'Click' on the hidden control. Additional Details: ...
Тогда возникает вопрос... а как тогда должны работать функции ожидания для UITestControl? Как их надо применять, чтобы отрабатывала задержка по времени и тест не валился, если вдруг что-то не успеет огтрисоваться или загрузиться в процессе запуска?
PS я пробовал и такой вариант: second.WaitForControlPropertyNotEqual(UITestControl.PropertyNames.Height, 0, 60000); - никакой разницы, все пролетает за считанные секунды и ошибки те же.
и xpath определен для этих 2-х объектов (Function and Model) как:
public static final By ELEVATION_DEVICE_FUNCTION = By.xpath("//div[contains(@ng-model,'deviceModel.function')]");
public static final By ELEVATION_DEVICE_MODEL = By.xpath("//div[contains(@ng-model,'deviceModelFE.deviceModel')]");
Код выглядит вот так:
@Step(description = "Select function and model")
public void selectFunctionAndModel(String pduFunction, String pduModel) {
driver.findElement(ElevationElements.ELEVATION_DEVICE_FUNCTION).click(); //нажать на комбо
WebElement elementFunctionFromList = driver.findElement(ElevationElements.ELEVATION_DEVICE_FUNCTION);
Select elementFunction = new Select(elementFunctionFromList);
elementFunction.selectByVisibleText(pduFunction); //выбрать элемент
}
или для глобальной функции для универсального использования метода
@Step(description = "select element from drop down list by value")
public void selectElementFromDropBox(WebDriver driver, By elementComboBox, String value) {
waitForElementToBeVisible(elementComboBox);
Select elementFromList = new Select(driver.findElement(elementComboBox));
elementFromList.selectByVisibleText(value);
}
Всё выглядит довольно неплохо, но вся загвоздка в ошибке исполнения:
[18:30:28.888] ** STEP: Select Function And Model [Select function and model]
[18:30:28.888] ** STEP: Wait For Element To Be Visible
org.openqa.selenium.support.ui.UnexpectedTagNameException: Element should have been "select" but was "div"
Build info: version: '3.4.0', revision: 'unknown', time: 'unknown'
System info: host: 'ISRTLVM609', ip: '135.70.231.187', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.8.0_151'
Driver info: driver.version: unknown