Самым большим препятствием в тестировании ExtJS с Selenium является то, что ExtJS не отображает стандартные элементы HTML, а Selenium IDE наивно (и по праву) генерирует команды, нацеленные на элементы, которые просто действуют как декор - лишние элементы, которые помогают ExtJS с весь настольный внешний вид Вот несколько советов и приемов, которые я собрал при написании автоматического теста Selenium для приложения ExtJS.
Общие советы
Расположение элементов
При создании тестовых примеров Selenium путем записи действий пользователя с помощью Selenium IDE в Firefox Selenium будет основывать записанные действия на идентификаторах элементов HTML. Однако для большинства интерактивных элементов ExtJS использует сгенерированные идентификаторы, такие как «ext-gen-345», которые могут измениться при последующем посещении той же страницы, даже если не было внесено никаких изменений кода. После записи действий пользователя для теста необходимо вручную выполнить все такие действия, которые зависят от сгенерированных идентификаторов, и заменить их. Существует два типа замен:
Замена локатора идентификатора на локатор CSS или XPath
CSS-локаторы начинаются с "css =", а XPath-локаторы начинаются с "//" (префикс "xpath =" является необязательным). CSS-локаторы менее многословны, их легче читать, и им следует отдавать предпочтение перед локаторами XPath. Однако могут быть случаи, когда необходимо использовать локаторы XPath, потому что локатор CSS просто не может его обрезать.
Выполнение JavaScript
Некоторые элементы требуют не просто взаимодействия мыши / клавиатуры из-за сложного рендеринга, выполняемого ExtJS. Например, Ext.form.CombBox на самом деле не элемент <select>
, а текстовый ввод с отдельным раскрывающимся списком, который находится где-то внизу дерева документа. Чтобы правильно смоделировать выбор ComboBox, можно сначала смоделировать щелчок по стрелке раскрывающегося списка, а затем щелкнуть по появившемуся списку. Однако, поиск этих элементов с помощью локаторов CSS или XPath может быть громоздким. Альтернативный вариант - найти сам компонент ComoBox и вызвать для него методы для имитации выделения:
var combo = Ext.getCmp('genderComboBox'); // returns the ComboBox components
combo.setValue('female'); // set the value
combo.fireEvent('select'); // because setValue() doesn't trigger the event
В Selenium команду runScript
можно использовать для выполнения вышеуказанной операции в более сжатой форме:
with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }
Как справиться с AJAX и медленным рендерингом
Selenium имеет разновидности "* AndWait" для всех команд для ожидания загрузки страницы, когда действие пользователя приводит к переходу или перезагрузке страницы. Однако, поскольку выборки AJAX не связаны с фактической загрузкой страниц, эти команды нельзя использовать для синхронизации. Решение состоит в том, чтобы использовать визуальные подсказки, такие как наличие / отсутствие индикатора прогресса AJAX или появление строк в сетке, дополнительные компоненты, ссылки и т. Д. Например:
Command: waitForElementNotPresent
Target: css=div:contains('Loading...')
Иногда элемент появляется только через определенное время, в зависимости от того, насколько быстро ExtJS отображает компоненты после того, как действие пользователя приводит к изменению представления. Вместо использования произвольных задержек с командой pause
идеальным методом является ожидание, пока интересующий элемент попадет в нашу хватку. Например, чтобы щелкнуть элемент после ожидания его появления:
Command: waitForElementPresent
Target: css=span:contains('Do the funky thing')
Command: click
Target: css=span:contains('Do the funky thing')
Полагаться на произвольные паузы не очень хорошая идея, поскольку различия во времени, возникающие в результате выполнения тестов в разных браузерах или на разных компьютерах, делают тестовые случаи нестабильными.
Предметы, не активируемые кликом
Некоторые элементы не могут быть вызваны командой click
. Это происходит потому, что прослушиватель событий на самом деле находится в контейнере, наблюдая за событиями мыши на его дочерних элементах, которые в итоге всплывают до родительского. Элемент управления вкладки является одним из примеров. Чтобы нажать на вкладку, вы должны смоделировать событие mouseDown
на ярлыке вкладки:
Command: mouseDownAt
Target: css=.x-tab-strip-text:contains('Options')
Value: 0,0
Проверка поля
Поля формы (компоненты Ext.form. *), Связанные с регулярными выражениями или vtypes для проверки, будут запускать проверку с определенной задержкой (см. Свойство validationDelay
, которое по умолчанию установлено на 250 мс) после того, как пользователь вводит текст или сразу, когда поле теряет фокус - или размывается (см. свойство validateOnDelay
). Чтобы запустить проверку поля после ввода команды типа Selenium для ввода текста внутри поля, необходимо выполнить одно из следующих действий:
Запуск отложенной проверки
ExtJS запускает таймер задержки проверки, когда поле получает события keyup. Чтобы запустить этот таймер, просто сгенерируйте фиктивное событие keyup (не имеет значения, какой ключ вы используете, так как ExtJS его игнорирует), после чего следует короткая пауза, которая длиннее validationDelay:
Command: keyUp
Target: someTextArea
Value: x
Command: pause
Target: 500
Запуск немедленной проверки
Вы можете вставить событие размытия в поле, чтобы вызвать немедленную проверку:
Command: runScript
Target: someComponent.nameTextField.fireEvent("blur")
Проверка результатов проверки
После проверки вы можете проверить наличие или отсутствие поля ошибки:
Command: verifyElementNotPresent
Target: //*[@id="nameTextField"]/../*[@class="x-form-invalid-msg" and not(contains(@style, "display: none"))]
Command: verifyElementPresent
Target: //*[@id="nameTextField"]/../*[@class="x-form-invalid-msg" and not(contains(@style, "display: none"))]
Обратите внимание, что проверка "display: none" необходима, поскольку после отображения поля ошибки, а затем его необходимо скрыть, ExtJS просто скрывает поле ошибки, а не полностью удаляет его из дерева DOM.
Советы по конкретным элементам
Нажатие кнопки Ext.form.Button
Вариант 1
Команда: нажмите
Цель: css = кнопка: содержит («Сохранить»)
Выбирает кнопку по заголовку
Вариант 2
Команда: нажмите
Цель: css = # кнопка опций сохранения
Выбирает кнопку по ее идентификатору
Выбор значения из Ext.form.ComboBox
Command: runScript
Target: with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }
Сначала устанавливается значение, а затем явно запускается событие выбора, если есть наблюдатели.