среда, 20 декабря 2017 г.

резюме по первому блоку с базовыми командами в Selenium



Сначала вызывается конструктор драйвера, который запускает вспомогательный исполняемый файл, а тот в свою очередь запускает браузер.
Далее все взаимодейтсвие с браузером происходит через этот сконструированный объект.

Новая страница открывается с помощью команды get, которая иногда принимает более длинную форму navigate to().
Чтобы выполнить какое-то действие с элементом, надо его сначала найти. Для этого используется команда findElement, которая возвращает объект, являющийся представителем реального элемента, находящегося на странице. Как только реальный элемент на странице пропадает, такие действия через его представителя уже совершить нельзя. При попытке выполнить любое действие возникает исключение staleElementsReferentsExcepiton, чи как-то так.
2 ключевые команды, которые можно выплонять с элементами, предназначены для симуляции действия мыши и клавиатуры.
Важное правило - С. выполняет действия только с теми элементами, которые видны в браузере. Кликать по невидимым элементам и заполнять скрытые поля ввода запрещено. При попытке сделать такое, выбрасывается исключение.
В конце сценария автоматизации надо вызывать метод quit. Чтобы остановить все запущенные процессы. И браузер, и вспомогательный исполняемый файл и освободить все захваченные ресурсы.
Если этод метод не вызвать, то в некоторых случаях ЯП сам справится с решением задачи, но это происходит не всегда.


Единообразие во всех языках



обратить внимание на названия.
get, findElement, sendKeys, click, quit.
Они везде одинаковые, отличаются только от договоренностей. Например, в некоторых ЯП юзают вместо кэмел-кейса нижнее подчеркивание, где-то с большой буквы названия методов и т.п.


С. предназначен для симуляции действий юзера, для управления браузером и эти команды выглядят одинаково, имеют одинаковые названия на всех 5 оф. поддерживаемых ЯП.

вторник, 19 декабря 2017 г.

Selenium, разбор кода




Итак, сначала мы объявляем переменную
mainMenu и запиливаем туда массив из названий категорий: "Снова в продаже, "Новые товары" и т.д.
subMenu - это для следующего теста.
Дальше мы делаем цикл:


Внутри цикла объявляем переменную х = 1, потом пишем условие, что пока x<= 13(количество категорий), перебирать категории х++)
В общем, пока х больше или равно 13, мы переходим по категориям и выполняем функцию(?) makeSubElementsTest(x);


В функции мы пишем тест

it('Все категории: категория: ' + mainMenu[x - 1], function () {
В параметрах функции выводится название: "Все категории: категория: ' + mainMenu[x - 1] т.е. название
категории, например, "Снова в продаже"), вторым аргументом функции еще одна 
функция, пустая function (). 


понедельник, 18 декабря 2017 г.

Действия с элементами

2 устройства взаимодействия:
- мышь;
- клава.
2 основные команды, которые мы юзаем:
- клик (мышь);
- send keys (ввод с клавы)












Команда findElement позволяет нам найти поле ввода, возвращается объект, который соответствует этому найденному элементу и у этого объекта вызывается метод sendKeys - ввод текста в это поле ввода.
Далее находим элемент, который соответсвует кнопке и команда .click симулирует нажатие кнопки мыши.
2 важных правила:
1. Элемент должен присутствовать на странице. Если между поиском элемента и использованием этого элемента (перед выполнением sendKeys или click) прошло много времени и может быть выполнялись какие-то другие действия, страница могла обновиться. Тогд этот элемент мог с нее исчезнуть. Даже если вместо него есть другой элемент с таким же локатором, это для него уже другой элемент, не тот же самый. И при попытке выполнить sendKeys или click для исчезнувшего элемента возникнет ошибка stalereference... exception. Искать элементы надо непосредственно перед тем, как мы его будем юзать.
Так что чаще всего в нашем коде будут встречаться именно такие цепочки из двух команд: 
findElement, затем sendKeys
findElement, затем click или какое-то другое действие с найденным элементом.

Чем меньше времени пройдет между поиском элемента и его использованием, тем выше вероятность того, что элемент не успеет никуда исчезнуть.

2. Элемент должен быть видимым. С. пытается симулировать действие реального пользователя, человек не может взаимодействовать с невидимым элементом.

  

воскресенье, 10 декабря 2017 г.

Заметки по тестированию, примерный разбор кода



it('Кнопка наверх', function(){
    let testResult = true;
    return this.browser        
.url('/')
        .isExisting('.footer__back-top .button_view_plain')
        .then(result=> assert.isTrue(result,'.footer__back-top .button_view_plain - не существует'),(err)=> {console.log(err); testResult = false})
        .getText('.footer__back-top .button_view_plain')
        .then(text => assert.isTrue(text === 'наверх', text+' != "наверх"'),(err)=> {console.log(err); testResult = false})
        .isExisting('.footer__back-top .icon svg path')
        .then(result =>; assert.isTrue(result, 'иконка не существует'),(err)=> {console.log(err); testResult = false})
        .click('.footer__back-top .button_view_plain')
        .then(() => assert.isTrue(true),(err)=> {console.log(err); testResult = false})
        .isVisible('.header__logo')
        .then(result => assert.isTrue(result, 'логотип не виден'),(err)=> {console.log(err); testResult = false})
        .then(()=> assert.isTrue(testResult))
});



it('Кнопка наверх', function(){  - типа, название главной функциональности, которую мы проверяем.

let testResult = true; - предположим, что переменная testResult - трушная.

return this.browser  - похоже, что-то для того, чтобы тесты проходили у меня локально на компе, в моем браузере.

.url('/') - проверять по такому-то адресу, там шо-та, видимо, еще в глобальных настройках настроено.

.isExisting('.footer__back-top .button_view_plain') - существует такой-то элемент по такому-то адресу.

.then(result=> assert.isTrue(result,'.footer__back-top .button_view_plain - не существует'),(err)=> {console.log(err); testResult = false})

проверяем, типа, затем переменная "результат", утверждаем, что тру (выводим переменную "результат", если не тру, то такой-то элемент не существует), (err - хз шо это, может, какая-то дефолтовая хрень выводит в консоль эту err; переменная testResult будет равна фолс)
Типа, есичо, если это будет фолсная переменная, она не закрашит систему, а просто отметит в консольке, что там зафейлилось.

.getText('.footer__back-top .button_view_plain') - метод взять текст из такого-то элемента

.then(text => assert.isTrue(text === 'наверх', text+' != "наверх"'),(err)=> {console.log(err); testResult = false})

проверяем, типа, переменная "text" - действительно "наверх", в противном случае выводим, что текст не "наверх", потом
.click('.footer__back-top .button_view_plain') - нажали на элемент
.then(() => assert.isTrue(true),(err)=> {console.log(err); testResult = false}) - 

хрень.

.then(()=> assert.isTrue(testResult)) - предположим, что тру, тогда весь комплект тру.
       
.it - метод, который является тестом.
it('Кнопка наверх', function(){
метод, принимает два параметра: 'Кнопка наверх' - строковое значение (что ттестируем, название теста)
и функцию (сам тест).

let testResult = true; - оператор объявления переменной, действующей внутри блока.
Блок - это код, заключенный в фигурные скобки.

Переменная testResult - булеановская, ей дано значение тру.

return this.browser -  оператор для возврата значения функции, this - указатель на объект
browser - объект

.url('/') - метод .url(с параметром "ссылка"). Этот метод открывает страницу относительно baseUrl
если не указан точный адрес.

.then(result=> assert.isTrue(result,'.footer__back-top .button_view_plain - не существует'),(err)=> {console.log(err); testResult = false})

метод .then(onSuccess, Error)

onSuccess  - данный блок выполняется в случае успеха предыдущей функции.
Error  - выполняется в случае возникновения ошибки в предыдущем блоке.

=> - стрелочная функция (загуглить!)

.then (он в переменную "результат" записывает результат строчки выше, т.е. тру или фолс)
потом => чтобы остаться в пределах then. 
assert - Объект(он объявлен выше, где chai),у которого есть методы:
isTrue()
1. если значение тру - проходит дальше
2. фолс - выводит текст указанный во втором параметре и сфейливается '.footer__back-top .button_view_plain - не существует'






вторник, 5 декабря 2017 г.

Заметки по тестированию, траблшут, с которым столкнулась.

В общем, пишу, ну, как пишу, частично пишу, частично переписываю тесты, которые сделал Никита.
Столкнулась с траблшутом.
У Никиты был такой кусок кода:



В общем, он нажимает на белый текст, шоб исчез попапчик.
Там еще какая-то, кмк, оверлогика была, типа, он сначала нажимает на этот белый текст, потом делает .isExisting и дальше пишет, что атрибут "aria-hidden" элемента popup_target_anchor = true.
И уже потом проверяет, правда ли у этого класса в атрибуте "aria-hidden" значение трушное, т.е. он скрыт, и если элемент и правда скрыт (значение спрятанности трушное), то уже потом выдает результат, мол, да, все норм.
ИМХО, это как-то суперсложно.

У меня долго не получалось, пока не сделала скриншоты происходящего.
Скриншот получился такой:



Из него я поняла, что у меня эти два элемента (попап и белый текстик) для селениума просто наслаиваются друг на друга.
Дальше я тупанула. Я думала, что можно как-то подлезть под этот красненький попап и таки нажать на текст, ибо мне надо было кликнуть все-таки сверху, но Никита сказал, что при клике это анриал.
Все было гораздо проще. При клике на сам этот поапчик, он тоже исчезал. Так я и закодила:


































понедельник, 4 декабря 2017 г.

Поиск элементов

2 сложности:
- no such element exception - не найден.
- stale element reference exception. (stale - устаревший) - потерялся.

Поиск элемента выполняется с помощью команды findElement или findElements.
В качестве параметра эти команды принимают т.н. локатор, описание правил или стратегии поиска элемента(ов).
Например, эта команда найдет элемент, у которого есть атрибут name, имеющий заданное значение. Если на странице несколько таких элементов, значит будет найден первый из них. Когда нас интересует не только первый, а все элементы, надо использовать команду findElements, она возвращает список элементов.
Если по какой-то причине команда findElement не может найти то, о чем попросили, она выбрасывает исключение.



4 причины:
1. Невалидный локатор.
2. Нет такого элемента:
- страница поменялась, изменилась верстка.
- в локаторах использовались какие-то критерии, основанные на изменяющихся свойствах элементов. Например, часто бывает, что id элементов создаются динамически, либо каждый раз они вообще новые, либо заменяются при перекомпиляции целевого приложения. Выпустили разрабы новую версию, а там все локаторы другие.
3. Сейчас нет такого элемента. Мы смотрим - он есть, но в тот момент, когда с.искал элемент, его не было. Скорей всего - надо использовать ожидание, т.е. искать элемент не сразу, а ждать, когда он появится.
4. Элемент может находиться в другом окне или другом фрейме.

findElement - выбрасывает исключение.
findElements - возвращает пустой список.


Посмотрим что возвращает метод findElement.
Поставим точку остановки, запустим сценарий в отладчике и проанализируем содержимое объекта типа WebElement.




Единственное, что хранится внутри этого объекта, это уникальный идентификатор. С. не загружает из браузера никакую инфу об элементах, кроме этого идентификатора. Если надо совершить с элементом какое-то действие или узнать какое-то свойство этого элемента, даже самое простое, например, тег, с. обращается к браузеру. Если мы два раза спросим тег элемента, он будет два раза обращаться к браузеру. Никакого кеширования на стороне клиентской библиотеки нет. Любое действие, любое получение свойства какого-то элемента - это всегда обращение к браузеру.
И при каждом таком обращении С. передает туда этот уникальный id элемента. Внутри браузера все элементы имеют такие уникальные id. Но когда страница меняется, элементы старые исчезают, появляются новые,  у этих элементов будут новые идентификаторы. Даже если новые элементы находятся на том же самом месте, где находились старые элементы и даже если они абсолютно так же выглядят, имеют такой же набор свойств, такой же текст, у них все равно будут новые идентификаторы.
Когда С. обращается к браузеру и передает туда id исчезнувшего элемента, возникает исключение stale element reference exception. (stale - устаревший). Браузер сообщает, что элемента с таким id больше нет, он исчез.
Если искусственно создать такую ситуацию, например, вписать эту строчку:


Оно обновит страничку, айдишник у этого элемента будет другой. Локатор "q" будет тот же, а айдишник будет другим, это уже другой элемент.

Главное, что надо запомнить, это то, что, нужно искать элемент непосредственно перед использованием.
Если мы сохранили элемент в какую-то переменную, потом выполнили какие-то действия со страницей и после этого что-то пытаемся сделать с элементом, сохраенным в переменную, это исключение может возникнуть, ибо страница могла поменяться.
Надо выполнять поиск элемента непосредственно перед использованием.

Консоль разработчика, посмотреть код ошибки

Вкладка Network, там, где ошибочка, мы в левом блоке нажимаем на эту ошибочку. Справа открывается блок с несколькими вкладочками. Выбираем вкладку 'Response'.

Заметки по тестированию

В общем, ребята еще не допилили автозаполнение полей и дико бесит вбивать данные по сто раз на стринце чекаута.
Сережа тока что подсказал, как настроить автозаполнение в браузере.
В общем, зайти в настройки и в панельке поиска вбить address.
Потом найти там пункт "Autofill settings", там уже настроить автозаполнение полей)

 

воскресенье, 3 декабря 2017 г.

Запуск браузера, открытие страниц.

Во всех 5 поддерживаемых официально языках инициализация браузера выполняется путем конструирования объекта соответствующего класса.
Конструктор пытается найти исполняемый вспомогательный файл и запускает его, передавая туда какие-то опции.
В свою очередь этот вспомогательный исполняемый файл пытается найти браузер и запускает его.
Если какое-то действие фейл, значит из конструктора будут выключены исключения, драйвер не проинициализируется.
Траблы:
- браузер не запускается.
- вспомогательный файл не запускается.
Браузер забыть сложно, а вот вспомогательный файл очень даже легко, но С. выдает вполне внятную ошибку.
Вторая трабла - невозможность установить соединение между клиентской библиотекой и вспомогательным исполняемым файлом. Даже если он хорошо запустился, это не означает, что С. сможет с ним общаться. Т.к. общение происходит по сети, какие-нибудь настройки сетевого окружения или какая-нибудь программа прокси, файервол или антивирус может заблокировать сетевое окружение. В этом случае, конечно, сообщение об ошибке будет другим, типа, не удается установить соединение. Вспом. исп. файл запущен, но к браузеру не можем добраться, например, из-за траблов с сетевым подключением.
Если, например, впн, то часть трафика может идти как-то хитро, поэтому в каждом случае надо разбираться отдельно.

После запуска страниц откырвается специальная пустая страница и нам надо открыть страницу целевого приложения. driver.get or driver navigate to



Используем такой метод и в качестве параметра туда передается адрес, но полный, обязательно с "http://". Если в адресе не указан протокол, С. считает его невалидным.
Обычно это настраивается 1 раз. Типа, как юзер, открыл приложение, а дальше ходит по ссылкам.
Юзается, когда надо симитировать открытие ссылки, полученной, например, в скайпе или по электропочте.
+ используем тогда, когда надо оптимизировать переходы. Если для перехода из одного раздела целевого приложения в другое нужно нажать несколько кнопок в меню - это долго и сложно, можно вместо этого сразу перейти по нужному адресу. 


пятница, 1 декабря 2017 г.

Ключевые команды Selenium

Все начинается с запуска браузера.


(желтенькие - наиболее часто используемые)

Т.к. браузером управляет драйвер, значит мы инициализируем драйвер, а он запускает браузер.
 С. не может запуститься и управлять браузером, который уже работает. Он может управлять только тем драйвером, который сам запустил.
Все 5 официально поддерживаемых ЯП - ООП и инициализация драйвера выполняется путем создания объекта подходящего класса. Т.е. вызывается конструктор, который создает объект. И сразу же при вызове конструктора запускается вспомогательный исполняемый файл, который в свою очередь запускает браузер.

После того, как драйвер создан, бывает нужно настроить некоторые параметры. Например, установка разных таймаутов, таких как таймаут установки загрузки страницы. Сюда же относятся и те, которые предназначены для настройки параметров браузера. Например, добавление или удаление куков. Сами по себе манипуляции с куками не приводят ни к каким результатам, просто изменяется текущее состояние браузера, а эффект можно будет заметить только когда загрузится следующая страница.

Загрузка страниц, обновление текущей страницы, переход на следующую и на предыдущую страницу, то, что соответствует в браузере нажатию кнопок "Вперед", "Назад". Несмотря на то, что эти команды кажутся очень простыми, здесь есть несколько скрытых подводных камней.

Дейсвтия с окнами. Специальные команды, которые позволяют открыть новое окно, в С. нет. Можно с помощью JS-кода, т.е. это делается при помощи совершенно другой команды, которая относится к другой группе.
С. умеет переключаться с одного окна на другое. И закрывать текущее окно. И если текущее окно было последним, значит браузер при этом тоже останавливается. Здесь тоже есть ловушки.

Действия с диалоговыми окнами. Это маленькие окошечки, в которых показывается кнопка "ОК" или кнопка "Cancel", а также там можно ввести какой-то текст. А еще диалоги, когда мы хотим загрузить файл на сервер или наоборот загрузить файл с сервера и сохранить его на локальный диск, ну, и другие виды диалога. С некоторыми С. умеет взаимодействовать, с некоторыми не умеет и их надо научиться избегать.

Работа с элементами страницы. Сначала элемент нужно найти. С. поддерживает несколько различных стратегий поиска элементов. После того, как элемент найден, можно получить его свойства, узнать что это за тег, какие у него есть атрибуты, текстовое содержание этого элемента, стили, текст, шрифт, размер и положение элемента на странице.
Команды, которые ищут элементы и команды которые получают свойства элементов - пассивные. Это симуляция тех действий, которые чловек выполняет глазами. Смотрит на страницу и делает какие-то выводы из того, что он делает.

Но кроме этого человек совершает еще и какие-то действия. Выполняет клики мышкой и вводит какой-то текст с клавы. Это действия с элементами. Поддерживаются как простые действия, так и сложные (комбинации простых, например, клик мышкой, зажав клавишу Ctrl на клаве).

Иногда встречаются элементы. Это нечто среднее между обычным элементом и окном - фреймы, т.е. окна, вложенные внутрь страницы. С ними С. тоже работает.

Выполнение JS-кода на странице приложения. Если надо сделать что-то необычное, какое-то действие, для которого нет подходящей команды в интерфейсе в С., можно выполнить произвольный JS-код на странице браузера.