Сегодня рассмотрим вопрос, как выбрать требуемое нам значение из выпадающего списка при написании тестов на C# и Selenium WebDriver. В процессе написания тестов я столкнулся с двумя типами выпадающих списков, работу с которыми мы и рассмотрим.

Обычный выпадающий список. Я его так называю так как у него значения выбираются по нажатию на стрелку, т.е. мы сразу видим все значения выпадающего списка:

Картинка: Выпадающий список - Как выбрать значение из выпадающего списка (Selenium WebDriver, C#)

Ajax выпадающий список. Это список, значения которого мы не увидим пока не начнём вводить что-либо в поле ввода:

Картинка: Выпадающий список при вводе - Как выбрать значение из выпадающего списка (Selenium WebDriver, C#)

Может есть «академические» названия этих списков, но я не тратил время на то чтобы это выяснять. Я практик, а не теоретик.

Выбор значений в каждом из списков отличается, поэтому давайте приступим к рассмотрению примеров работы со списками.

Выбор значения из обычного выпадающего списка

К примеру, есть у нас список, код 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»:

Картинка: HTML - Как выбрать значение из выпадающего списка (Selenium WebDriver, C#)

Вы смотрите в какие теги заключены ваши элементы списка.
Строка 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;