Сегодня рассмотрим вопрос, как выбрать требуемое нам значение из выпадающего списка при написании тестов на C# и Selenium WebDriver. В процессе написания тестов я столкнулся с двумя типами выпадающих списков, работу с которыми мы и рассмотрим.
Обычный выпадающий список. Я его так называю так как у него значения выбираются по нажатию на стрелку, т.е. мы сразу видим все значения выпадающего списка:
Ajax выпадающий список. Это список, значения которого мы не увидим пока не начнём вводить что-либо в поле ввода:
Может есть «академические» названия этих списков, но я не тратил время на то чтобы это выяснять. Я практик, а не теоретик.
Выбор значений в каждом из списков отличается, поэтому давайте приступим к рассмотрению примеров работы со списками.
Выбор значения из обычного выпадающего списка
К примеру, есть у нас список, код HTML которого выглядит следующим образом:
<select class="class-spiska"> <option>0%</option> <option>10%</option> <option>18%</option> <option>Без НДС</option> </select>
И если мы хотим выбрать из списка значение «18%», то мы это сделаем при помощи следующего кода:
IWebElement selectElem = driver.FindElement(By.ClassName("class-spiska")); // обращаемся к списку по его классу, если нет ни id, ни class, то обращайтесь по XPath или CssSelector SelectElement select = new SelectElement(selectElem); System.Collections.Generic.IList<openqa.selenium.iwebelement> options = select.Options; select.SelectByText("18%");
Выбор значения из ajax выпадающего списка
К примеру, есть у нас «input» и когда мы вводим в него значения, то система с помощью ajax начинает нам отображать подходящие элементы списка. Пример кода HTML:
<input type="text" class="class-spiska">
Если мы хотим выбрать из списка значение «Миллиметр», то мы это сделаем при помощи следующего кода:
System.Collections.ObjectModel.ReadOnlyCollection iElements; driver.FindElement(By.ClassName("class-spiska")).SendKeys("Миллим"); driver.FindElement(By.ClassName("class-spiska")).Click(); Thread.Sleep(1000); iElements = driver.FindElements(By.TagName("a")); for (int i = 0; i < iElements.Count; i = i + 1) { if (iElements[i].Text == "Миллиметр" && iElements[i].Displayed) { iElements[i].Click(); break; } }
Строка 1 — объявление переменной.
Строка 2 — отправим часть требуемого значения в заполняемое поле выпадающего списка.
Строка 3 — кликаем на заполняемое поле списка, чтобы ajax начал отрабатывать (в моём случае, только так он инициализируется).
Строка 4 — ожидаем появления значений, иначе значения не успеют появиться и на следующих шагах появится ошибка выполнения. Тут экспериментируйте, возможно в вашем случае можно будет убрать данную строку.
Строка 5 — элементы списка, которые появляются, у меня помещены в теги «a», поэтому я говорю, что надо найти все элементы «a»:
Вы смотрите в какие теги заключены ваши элементы списка.
Строка 6 — в строке 5 мы нашли все теги «a» и их количество равно «iElements.Count», теперь начинаем перебирать элементы на странице пока они не кончатся «i < iElements.Count» и…
Строка 8 — если выполняется условие «если элемент перебираемый сейчас содержит требуемый текст И данный элемент видимый», то выбираем данный элемент.
Возможно у вас список будет реализован не с помощью «input», а с помощью другого элемента/тега, но обращаться к нему можно так как я описал.
Эпилог
Хочу обратить ваше внимание на то, что у рассматриваемых мной списков есть «class = class-spiska». Желательно чтобы разработчики при разработке добавляли к спискам «id» или «class», тогда вам будет легче писать тесты. Если у списка нет ничего, то вам к нему придётся обращаться по «By.CssSelector» или по «By.XPath», а мы все прекрасно знаем, что если добавят дополнительные элементы на страницу, то ваши тесты «посыпятся», так как изменятся «By.CssSelector» и «By.XPath».
Если у вас Studio будет на что-то ругаться при добавлении приведённого мной кода, то привожу список всего того, что у меня подключено к проекту, а вы уже сами подберёте чего у вас не хватает:
using System; using System.IO; using System.Threading; using NUnit.Framework; using Selenium; using OpenQA.Selenium; using OpenQA.Selenium.Remote; using OpenQA.Selenium.Firefox; using OpenQA.Selenium.Chrome; using OpenQA.Selenium.PhantomJS; using OpenQA.Selenium.Support.UI;
В цикле Вы ищете по ВСЕМ элементам на странице, которые содержат тег «a». Это не очень продуктивно, поставьте хотя бы break; после нахождения нужного элемента — сразу после iElements[i].Click(); Так вы теоретически сократите время поиска.
А еще лучше ищите сразу с более сильными условиями.
К сожалению, это не всегда легко ))
Да, оператор завершения пропустил. Поправил.
Cool, thanks!