Перейти к содержимому

Фотография

Извлечь текст из определённого места на странице С# + webdriver

C# Selenium Webdriver

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 9

#1 Aegis

Aegis

    Новый участник

  • Members
  • Pip
  • 7 сообщений
  • ФИО:Кирилл

Отправлено 30 мая 2018 - 08:07

Здравствуйте!

 

Работаю джуном тестировщиком, помогите пожалуйста разобраться с проблемой!

 

Дано: на странице веб приложения есть таблица, в первой колонке будет текст.

Необходимо из каждой строки сохранять текст, например в переменную, для дальнейшей работы с ним. Какой текст там будет заранее, естественно, неизвестно.

 

Выглядит это вот так:  

 

2f4d42653da6.png

 

 

 

какая ещё информация может понадобиться?


  • 0

#2 Snap

Snap

    Специалист

  • Members
  • PipPipPipPipPip
  • 980 сообщений
  • ФИО:Роман
  • Город:Москва


Отправлено 30 мая 2018 - 10:09

А что не получается?

Не можете составить корректный xpath/css селектор или не знаете команды для извлечения текста элемента?


  • 0

#3 Aegis

Aegis

    Новый участник

  • Members
  • Pip
  • 7 сообщений
  • ФИО:Кирилл

Отправлено 30 мая 2018 - 10:50

Не получалось составить корректный xpath/css селектор!

 

Пока ждал ответа не сидел сложа руки и внутри цикла написал такое:

 

t = driver.FindElement(By.XPath("//tr[" + N + "]/td/table/tbody/tr/td")).Text;

N++;

 

Работает, но я не уверен насколько надёжна такая конструкция и может быть есть вариант проще или корректнее?


  • 0

#4 Snap

Snap

    Специалист

  • Members
  • PipPipPipPipPip
  • 980 сообщений
  • ФИО:Роман
  • Город:Москва


Отправлено 30 мая 2018 - 13:38

Трудно сказать, не видя полностью страницы. 

Но видя приведенный кусок, можно сказать, что таблицы и ее столбцы/строки не имеют уникальных атрибутов, поэтому минимально сократить селектор удастся до //tr[" + N + "]//tr/td

Раз ваш вариант работает, значит вполне имеет право на существование.


  • 0

#5 Noksa

Noksa

    Активный участник

  • Members
  • PipPip
  • 117 сообщений
  • ФИО:Александр

Отправлено 30 мая 2018 - 20:13

Не получалось составить корректный xpath/css селектор!

Пока ждал ответа не сидел сложа руки и внутри цикла написал такое:

t = driver.FindElement(By.XPath("//tr[" + N + "]/td/table/tbody/tr/td")).Text;
N++;

Работает, но я не уверен насколько надёжна такая конструкция и может быть есть вариант проще или корректнее?

Из вашего локатора надо убрать лишнее до //table. Да и в целом переписать его.
К тому же, если в вашей таблице в ячейке будет какой-то элемент с текстом, а не просто текст - локатор не сработает.
Например ссылка с текстом.
Здесь нужно использовать ИЛИ.
Завтра как доберусь к компьютеру могу подробнее написать правильный универсальный локатор.
  • 0

#6 Aegis

Aegis

    Новый участник

  • Members
  • Pip
  • 7 сообщений
  • ФИО:Кирилл

Отправлено 31 мая 2018 - 03:21

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

 

Буду очень благодарен!


  • 0

#7 Noksa

Noksa

    Активный участник

  • Members
  • PipPip
  • 117 сообщений
  • ФИО:Александр

Отправлено 31 мая 2018 - 04:42

Доброго времени суток.

 

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

Для этого нужно написать свой декоратор.

 

В классе вертикальной таблицы у меня определяются элементы следующим образом:

 

1) Все строки: 

public virtual IList<IWebElement> Rows => FindElements(By.CssSelector("tbody tr"));
 
2) Все столбцы:
public virtual IList<IWebElement> Columns => FindElements(By.CssSelector("tr:first-child th"));
 
3) Все ячейки:
public virtual IList<IWebElement> Cells => FindElements(By.CssSelector("tbody tr td"));
 
Здесь надо учитывать то, что поиск элементов происходит от родительского.
Так же использую свой фреймворк, где у меня работают следующие атрибуты:
 
[BlockTitle("Модальное окно с заказом")]
[FindBy(XPath = "//div[@class = \'modal-content\']")]
[TimeToSearch("block_waiting_timing")]
    public class OrderModalBlock : ABlock
    {       
 
        [FindBy(XPath = "(.//table[preceding::*[contains(text(), \'Заказ\')]]) [1]", ParentElement = "Модальное окно с заказом")]
        [ElementTitle("Заказ")]
        private AHorizontalTable _orderTable;

      ...../

   }

 

Соответственно, таблица является дочерним элементом блока элементов.

А элементы внутри таблицы - соответственно дочерними элементами самой таблицы.

 

Сам локатор для поиска текста в ячейке такой (точка в начале Xpath означает, что поиск нужно осуществлять внутри родительского элемента - это важно, если у вас на странице не одна таблица): 

var element = FindElement(By.XPath($".//tbody//tr[{rowId}]//td[contains(text(), \'{textInRow}\')]|.//tbody//tr[{rowId}]//td[*[contains(text(), \'{textInRow}\')]]"));
 
Такой xpath либо найдет текст в самой ячейке, либо в любом элементе в этой ячейке. 
В моём примере, ячейка хранит ссылку, т.е. <td><a...></a></td> - и текст нужно было искать именно в элементе <a>.
 
Если вам нужно искать текст не смотря на регистр, и у вас XPath 1.0, то можно воспользоваться вспомогательным методом. 
Например таким:
 
public static string ContainsTextIgnoreCase(string text)
        {
            return
                $"text()[contains(translate(., \'ABCDEFGHIJKLMNOPQRSTUVWXYZЙФЯЦЫЧУВСКАМЕПИНРТГОЬШЛБЩДЮЗЖХЭЪ\', \'abcdefghijklmnopqrstuvwxyzйфяцычувскамепинртгоьшлбщдюзжхэъ\'), \'{text.ToLower()}\')]/parent::*";
        }

  • 1

#8 Aegis

Aegis

    Новый участник

  • Members
  • Pip
  • 7 сообщений
  • ФИО:Кирилл

Отправлено 31 мая 2018 - 06:24

Ещё такой вопрос:

Заранее определяю элемент: By checkboxes = By.XPath("//input[@name='CurrentObject.Show']");

Потом использую его в коде: driver.FindElement(checkboxes).Click();

 

Но в один прекрасный момент мне понадобилось сделать, как бы корректнее выразится, перебор по этим схожим элементам.

И внутри цикла получается только так: driver.FindElement(By.XPath("(//input[@name='CurrentObject.Show'])" + "[" + n1 + "]")).Click();

 

Можно как-нибудь сделать чтобы это было похоже на : driver.FindElement(checkboxes[n1]).Click(); как-то вот так???


  • 0

#9 Noksa

Noksa

    Активный участник

  • Members
  • PipPip
  • 117 сообщений
  • ФИО:Александр

Отправлено 31 мая 2018 - 07:16

Ещё такой вопрос:

Заранее определяю элемент: By checkboxes = By.XPath("//input[@name='CurrentObject.Show']");

Потом использую его в коде: driver.FindElement(checkboxes).Click();

 

Но в один прекрасный момент мне понадобилось сделать, как бы корректнее выразится, перебор по этим схожим элементам.

И внутри цикла получается только так: driver.FindElement(By.XPath("(//input[@name='CurrentObject.Show'])" + "[" + n1 + "]")).Click();

 

Можно как-нибудь сделать чтобы это было похоже на : driver.FindElement(checkboxes[n1]).Click(); как-то вот так???

 

Вы можете использовать метод FindElements.

 

Например так: driver.FindElements(checkboxes).

 

Он вернёт вам список всех найденных элементов по переданному локатору.

А потом уже можете в foreach пройтись по всем элементам из списка:

 

foreach (var checkBox in checkboxes)

                {
                    checkBox.Click();
                }
 
Если метод только один, то фигурные скобки можно опустить:

foreach (var checkBox in checkboxes) checkBox.Click();                

 
Либо через лямбду:
checkboxes.ToList().ForEach(_ => _.Click());

  • 0

#10 Noksa

Noksa

    Активный участник

  • Members
  • PipPip
  • 117 сообщений
  • ФИО:Александр

Отправлено 31 мая 2018 - 07:21

Ну и да - я вам советую использовать PageObject паттерн, если вы его не используете. 


  • 1



Темы с аналогичным тегами C#, Selenium, Webdriver

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных