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

как найти на странице javascript-скрипт и вызвать его в тесте ?

selenium
angularjs
locators
ajax
python
javascript
webdriver
Теги: #<Tag:0x00007f7b705db3d8> #<Tag:0x00007f7b705db270> #<Tag:0x00007f7b705db0e0> #<Tag:0x00007f7b705daf78> #<Tag:0x00007f7b705dae10> #<Tag:0x00007f7b705dac58> #<Tag:0x00007f7b705dab18>

(Yuryi) #1

Привет. Перерыл в поиске все темы связанные с #javascript , но не нашёл ответа. В общем, никогда не сталкивался со скриптами, всегда хватало простых действий через #webdriver , на этот раз на проекте оказалось что привязаться ( в плане #locators ) вообще почти не к чему, всё динамическое.

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

<button class="uri-button component_ok_set" ng-click="ctrl.confirmemailproperty()" main="" use-template="true" tabindex="1">

Я так понимаю confirmemailproperty() - это #javascript -метод, который можно вызвать.

Как это сделать в #python ? Можно ли обращаться к нему прямо по имени ?


(Lev Yarushin) #2

Можно пример кода страницы? Привязаться всегда есть к чему, возможно просто не замечаете.
Что касается обращения к JS непосредственно в тесте - это можно сделать при помощи метода execute_script
Вот тут хороший пример: http://infoheap.com/python-selenium-execute-javascript-code/

from selenium import webdriver

driver = webdriver.PhantomJS("/usr/local/bin/phantomjs")
driver.get("http://dev.infoheap.com/")
jscode='''
var global_total_links=0;
jQuery("a").each(function() {
  global_total_links++;
});
return global_total_links;
'''
retval = driver.execute_script(jscode);
print retval
driver.close()

(Yuryi) #3

Я извиняюсь, не совсем точно сформулировал вопрос. То, что скрипты вызываются с помощью execute_script я нашёл.

Меня больше интересует то как вызвать конкретный скрипт на странице. Т.е. у меня есть элемент (за элемент не ругайте, пишу дома на память, но общая суть - та же) <div class="popup_confirmation_property_btn hide" ng_click="ctrl.confirmemailproperty();" css_блаблабла--span-OK></span></div>. Я пробовал вставлять в execute script и отдельно "confirmemailproperty();", и "ctrl.confirmemailproperty();" и "return confirmemailproperty()", но ничего из этого не работает.

Итого,
1-ый вопрос: “ctrl.confirmemailproperty();” - это же скрипт ?
2-ой вопрос: как его вызвать ?

п.с. к сожаленію пример страницы предоставить не могу, всё приватное. На счёт того, что привязаться можно всегда - это понятно, просто настало время подтянуть знания по джс :slight_smile:


(Lev Yarushin) #4

Похоже у вас Angular. Вот так попробуйте:

А ещё, возможно стоит поглядеть в сторону Protractor/CodeceptJS, тестировать Angular ими гораздо проще.


(Сергей Кузьмин) #5

для тех то пишет на Python есть https://github.com/kpodl/pytractor
для тех то пишет на Java есть https://github.com/caarlos0/jProtractor / https://github.com/henrrich/jpagefactory
для тех то пишет на .net есть https://github.com/bbaia/protractor-net


(Pavel Ponomaryov) #6

Вы end to end тесты пишете ведь? Делайте всё именно так, как делал бы пользователь - дождитесь пока будет виден элемент, а далее взаимодействуйте с ним, иначе толку от ваших тестов не будет никакого. Если нужна помощь с построением локаторов - вам тут помогут, подскажут где почитать, но не изобретайте велосипедов - не нужно вам взаимодействовать с скриптами на странице. Определить уникальный локатор можно всегда - практически без исключений.


(Bolatbek) #7

Не всегда можно дождаться элемента.


(Pavel Ponomaryov) #8

Пример приведите пожалуйста.


(Dzmitry Ihnatsyeu) #9

Если ваш сайт не из 90-х, то наверняка js скрипт будет лежать не в #dom , а если это #nodejs , то вы и не увидите ссылок на скрипты в принципе.

У вас 2 варианта:

  1. Подливать напрямую js в репозиторий вашего проекта и выполнять его на сервере.
    Как по мне, вариант плохой ( конечно если вам не хочется написать еще и сервер)
  2. Вызывает событие, которое и триггерит выполнение скрипта. Наиболее подходящий вариант

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

@pavelp дал вам самый действенный совет


(Bolatbek) #10

Пример простой.

У меня на проекте на сайте есть табличная часть, которая обновляется по клику (некий фильтр). Между кликом и запросом к серверу (ajax запрос) есть таймаут в 0.5 секунд (требование бизнеса). После запроса табличная часть обновляется, в зависимости от того, что человек выбрал. Тест должен проверять, что табличная часть соответствует выбранным фильтрам. Как будете ждать нужный вам элемент?


(Dzmitry Ihnatsyeu) #11

@Mes , большинство сайтов сейчас представляют собой one-page solution, т.е. элементы динамические. Обратите внимание на WebDriverWait для ожидания элементов, которые появляются на странице со временем, а не при загрузке html.

Проверяйте контекст таблицы, а не локаторы, если они не уникальные.
Cоставте mapping context - expected table

Обратитесь к разработчикам, спросите их о возможности добавления уникальных идентификаторов.
Качество дело не только тестировщиков, если вам скажут разбираться самим ( только QA) , значит ваше начальство не особо и интересует качество проекта


(Pavel Ponomaryov) #12

именнно для этих ситуаций и существуют ExpectedConditions. Вы можете с их помощью реализовать ожидания любых условий. Проще, конечно использовать существующие обёртки вроде #selenide , чтобы не изобретать велосипеды самому.


(Bolatbek) #13

Как это вы видите? Как будет выглядеть ваш expected condition?

А мне проще скриптом дождаться окончания всех запросов и потом проверять таблицу.
В том же протракторе (на который ссылаются выше) есть функция waitForAngular, который по сути через execute_script запускает скрипт ожидания всех запросов, то есть “взаимодействует со скриптом на странице”.


(Dzmitry Ihnatsyeu) #14

а если на странице есть запросы, которые выполняются переодически? Сейчас у вас их может не быть на странице, но отбрасывать такую возможность я бы не стал. Как вы будете ждать завершения всех запросов? Такой подход концептуально не верен. Ждите элемент с помощью WebDriverWait + ExpectedConditions. Как это сделать вам расскажет гугл.

В любом случае вам выбирать, но еще раз: тело скрипта вам не получить со страницы, скрипты хранятся на веб-сервере. Хотите выполнять скрипт - храните его у себя в проекте.


(Bolatbek) #15

Ну, во-первых, ожидать окончания запросов можно легко и просто. Тоже гуглится.
Во-вторых, чтобы выполнить скрипт от jQuery или Angular мне не надо его у себя хранить.


(Pavel Ponomaryov) #16

Во-первых я бы не полагался на protractor для e2e тестов. Ваши девелоперы завтра решат переписать приложение на React и гудбай 100500+ тестов. Будете переписывать по новой. Вот человек пишет про боль перевода протракторовских тестов на react http://www.joelotter.com/2015/04/18/protractor-reactjs.html Можно конечно обойти вокруг всего - но зачем делать ставку на то, что может в один момент сломать все ваши тесты ? Упомяну лишь, что сам я тесты для protractorа не писал, но его использовали наши фронтэнд разработчики… до тех пор пока приложение было на angular :wink:


(Dzmitry Ihnatsyeu) #17

Буду благодарен, если расскажете как выполнить js скрипт ( имеется ввиду хранящийся в файле, например, scriptTest.js) не сохраняя его у себя.


(Bolatbek) #18

Непонятен вопрос.
Есть свой скрипт, который лежит у меня и надо его исполнить в браузере?
Тот же execute_script c телом вышеуказанном скрипта.


(Bolatbek) #19

Я не юзаю протрактор, из него только взял скрипт для ожидания ангуляра и только.


(Dzmitry Ihnatsyeu) #20

вы сказали, что чтобы выполнить js script, который находится на сервере ( это понятно из того, что кода скрипта нет в html, только ссылка на него, либо отсуствие ссылки как таковой из-за особенностней реализации js frameworkа) вам не нужно хранить файл со скриптом у себя. Мне интересно, как вы выполняете такой скрипт?