Будущих студентов курса "Java QA Automation Engineer" приглашаем принять участие в открытом уроке на тему "HTTP. Postman, newman, fiddler (charles), curl, SOAP. SOAPUI".
А сейчас предлагаем ознакомиться с переводом полезного материала.
Для хранения тестовых данных обычно требуется такой тип данных, который:
допускает объявление нескольких свойств;
имеет минимальное поведение или вообще его не имеет;
позволяет легко создавать несколько одинаковых сущностей.
Объекты почти соответствуют этим требованиям. Но тогда для создания нескольких сущностей потребовалось бы создавать несколько объектов с небольшим количеством свойств и минимальным поведением (либо вообще без оного). Под минимальным поведением я имею в виду небольшое количество методов. По сути, для каждой нужной вам сущности пришлось бы создавать новый объект, а это бесполезная трата ресурсов. Вместо этого можно использовать Enum
, объект особого типа.
С помощью Enum
можно представлять такие понятия, как дни недели, месяцы года, браузеры или языки. В этой статье я хочу привести примеры использования объектов Enum
с несколькими свойствами в рамках конструктора, обрабатывающего выбор страны. В конце статьи приведена ссылка на GitHub, где размещены все использованные в статье примеры кода. Информация об объектах Enum
доступна в официальной документации.
Использование enum-перечислений Java в тестировании: пример со странами
Для этого примера давайте предположим, что тестирование подразумевает заполнение регистрационной формы для конкретной страны. В этой форме вам среди прочего нужно указать: страну, город этой страны, а также номер телефона из этой страны — все эти сведения относятся к клиенту, от имени которого заполняется регистрационная форма. Сайт с этой формой будет доступен во многих странах по всему миру.
Для выполнения тестирования давайте сузим список используемых стран до Австрии, Эстонии и Испании. У каждой из этих стран будет три свойства, которые необходимо вывести в регистрационную форму: название страны, список городов и код страны в номере телефона. Используя этот код, мы можем сформировать тестовый номер телефона. Все страны у нас будут перечислены в объекте Enum
. Постоянные значения (константы), используемые для обозначения стран: AT, EE и ES.
Объявим объект Enum
следующим образом:
public enum Country {
AT("Austria", Arrays.asList("Vienna", "Salzburg", "Innsbruck"), 43),
EE("Estonia", Arrays.asList("Tallinn", "Haapsalu", "Tartu"), 372),
ES("Spain", Arrays.asList("Malaga","Madrid","Valencia","Corralejo"), 34);
public final String label;
public final List<String> cities;
public int phoneNumberPrefix;
Country(String label, List<String> cities, int phoneNumberPrefix) {
this.label = label;
this.cities = cities;
this.phoneNumberPrefix = phoneNumberPrefix;
}
}
Как видите, сначала мы указываем набор допустимых значений для констант стран, а также допустимые значения для всех их свойств. Мы определяем типы этих свойств, объявив label
, cities
и phoneNumberPrefix
. Этими типами являются: String
, List<String>
и int
.
Конструктор используется внутри кода для формирования значений Enum
. Итак, например, AT
имеет свойства, порядок которых соответствует порядку параметров из конструктора: свойство label
имеет значение «Австрия», список cities
(городов), относящихся к этой стране: «Вена», «Зальцбург» и «Инсбрук», а свойство phoneNumberPrefix
имеет значение «43».
Мы можем получить свойство, соответствующее константе Enum
, следующим образом: Country.КОНСТАНТА.имяСвойства
. Пример: Country.AT.label
даст нам свойство «Австрия». Как видите, свойства Country
являются статическими.
В регистрационной форме страна выбирается из раскрывающегося списка, город указывается в другом раскрывающемся списке, а номер телефона вводится в поле.
Класс Page
содержит информацию по конкретной стране и включает следующие записи:
@FindBy(css = "#country") private WebElement countryDropdown;
@FindBy(css = "#city") private WebElement cityDropdown;
@FindBy(css = "#phone") public WebElement phoneNumberField;
@FindBy(css = "[type='submit']") public WebElement submitButton;
public Select countrySelect() {
return new Select(countryDropdown);
}
public Select citySelect() {
return new Select(cityDropdown);
}
Метод countrySelect()
возвращает функцию Select
со ссылкой на раскрывающийся список стран. Аналогичным образом метод citySelect()
возвращает функцию Select
со ссылкой на раскрывающийся список городов. Для ввода номера телефона будет применяться элемент WebElement phoneNumberField
.
В этой статье я пропущу те части кода, в которых открывается браузер, открывается веб-страница и закрывается браузер. Все эти части можно посмотреть в репозитории GitHub, ссылку на который я укажу в конце статьи.
Сценарий 1. Заполнение регистрационной формы от имени испанского клиента
Как только откроется браузер со страницей регистрации, наш тест должен будет заполнить поля данными для клиента из Испании. Мы выберем страну, затем город Валенсию, после чего введем произвольный номер телефона из 10 цифр. Часть регистрационной формы со сведениями о стране будет выглядеть вот так:
Итак, создадим новый тест для этого действия:
@Test
void selectCountryCityAndTypePhoneNumber() {
}
Сначала выберем страну. Для этого в раскрывающемся списке стран мы выберем значение, соответствующее свойству label
записи ES в Enum
. Делается это просто: Country.ES.label
. Выбор страны выполняется следующим образом:
page.countrySelect().selectByVisibleText(Country.ES.label);
Далее, нам нужно выбрать город из соответствующего раскрывающегося списка. Доступ к списку городов производится так: Country.ES.cities
. Доступ к элементу списка, соответствующему Валенсии (третьему элементу), производится так: Country.ES.cities.get(2)
. Выберем это значение из списка городов:
page.citySelect().selectByVisibleText(Country.ES.cities.get(2));
И на последнем шаге нам нужно сформировать номер телефона, первые две цифры которого соответствуют коду страны. Этот код можно получить из объекта Enum
следующим образом: Country.ES.phoneNumberPrefix
. Формирование произвольного номера, состоящего из 10 символов: Country.ES.phoneNumberPrefix + randomNumeric(8)
.
Чтобы использовать метод randomNumeric
, сначала нужно импортировать соответствующий класс из библиотеки Apache Commons следующим образом:
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
Если у вас нет этой библиотеки в проекте, нужно ее импортировать. Для проекта Maven нужно просто добавить следующую запись в файл pom.xml
(обязательно используйте последнюю версию):
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
Вот как выглядит полный тест:
@Test
void selectCountryCityAndTypePhoneNumber() {
page.countrySelect().selectByVisibleText(Country.ES.label);
page.citySelect().selectByVisibleText(Country.ES.cities.get(2));
page.phoneNumberField.sendKeys(Country.ES.phoneNumberPrefix + randomNumeric(8));
}
Сценарий 2. Проверка имеющихся стран
Во втором и третьем сценариях нам нужно будет проверить, что раскрывающиеся списки стран и городов отображают только ожидаемые значения. Раскрывающиеся списки из этого примера работают следующим образом: когда они не открыты (пользователь не щелкнул их), в раскрывающемся списке стран не выбрано ничего, а раскрывающийся список городов полностью пуст. В этот момент раскрывающийся список городов отключен, и из него нельзя выбрать какой-либо вариант.
После нажатия раскрывающегося списка стран открывается список имеющихся вариантов. В этом списке должны отражаться значения, указанные в объекте Enum
как свойства label
. Стоит отметить, что для корректного отображения в раскрывающемся списке стран также имеется пункт без текста. Согласно изначальным требованиям, в раскрывающихся списках не должно быть никакого заранее выбранного значения.
После выбора страны активируется раскрывающийся список городов. В соответствии с выбранной страной в открытом раскрывающемся списке городов должны отображаться только города, соответствующие этой стране. Не забывайте, что для корректного отображения в этом раскрывающемся списке также есть один пункт без текста.
Составляемые нами тесты должны проверять наличие в соответствующих раскрывающихся списках всех нужных нам стран и городов, которые мы сохранили в объекте Enum
. Опять же, не забывайте, что в обоих списках у нас есть пустые пункты.
Начнем со сценария номер 2, а именно с проверки наличия в раскрывающемся списке стран правильных значений. Сначала сформируем наш ожидаемый (expected) контент. Нам известно, что ожидаемые значения у нас хранятся в параметрах label
в нашем объекте Enum
, но нам также нужно обработать пункт без текста, который отображается в раскрывающемся списке. Учитывая, что мы будем считывать значения с веб-страницы с помощью Selenium, а также, что они возвращаются как строки (String), мы можем создать список ожидаемых строковых значений стран. Во-первых, я создам список и добавлю в него первый элемент, которым будет пустая строка. Этот элемент будет соответствовать пустой строке из раскрывающегося списка стран.
List<String> expectedCountries = new ArrayList<>();
expectedCountries.add("");
Теперь нужно добавить все значения свойств label
, имеющиеся в нашем объекте Enum
. Для этого нам нужно пройти по всем элементам Enum
и добавить строковое значение каждого соответствующего свойства label
в список ожидаемых значений. Чтобы прочесать каждую запись объекта Enum
, воспользуемся методом Country.values()
.
for (Country country : Country.values()) {
expectedCountries.add(country.label);
}
Теперь в нашем списке ожидаемых стран содержатся четыре пункта: «», «Австрия», «Эстония», «Испания».
Далее можно переходить к считыванию значений стран с веб-страницы и сохранению этих значений в список фактических (actual) значений. Поскольку мы имеем дело с Select
, нам нужно будет пройти по всем вариантам WebElements
, относящимся к Select
. Нам нужно применить getText()
к каждому варианту (option) и добавить итоговые строки в список фактических значений.
List<String> actualCountries = new ArrayList<>();
for (WebElement option : page.countrySelect().getOptions()) {
actualCountries.add(option.getText());
}
Перед сравнением ожидаемого и фактического списков нам нужно учесть, что, возможно, наши параметры в объекте Enum и значения вариантов в раскрывающемся списке идут не в одном порядке. Поэтому их нужно отсортировать, а затем произвести сравнение.
Collections.sort(expectedCountries);
Collections.sort(actualCountries);
assertEquals(expectedCountries, actualCountries);
Весь тест выглядит следующим образом:
@Test
void checkCountries() {
List<String> expectedCountries = new ArrayList<>();
expectedCountries.add("");
for (Country country : Country.values()) {
expectedCountries.add(country.label);
}
List<String> actualCountries = new ArrayList<>();
for (WebElement option : page.countrySelect().getOptions()) {
actualCountries.add(option.getText());
}
Collections.sort(expectedCountries);
Collections.sort(actualCountries);
assertEquals(expectedCountries, actualCountries);
}
Сценарий 3. Проверка имеющихся городов
В нашем предыдущем сценарии нам не нужно было взаимодействовать с самими раскрывающимися списками. Однако в этом сценарии нам необходимо проверить, что для каждой выбранной страны в раскрывающемся списке городов отображаются только правильные города. Поскольку информацию в список городов после выбора страны в соответствующем раскрывающемся списке загружает JavaScript, тест должен выбрать поочередно каждую страну и проверить для каждой из них содержимое раскрывающегося списка городов.
Начнем писать тест с прохода по имеющимся записям объекта Enum
:
for (Country country : Country.values()) {
Затем, давайте внутри петли for
в раскрывающимся списке стран выберем ту страну, которая соответствует свойству label
текущего пункта Enum
:
page.countrySelect().selectByVisibleText(country.label);
В этот момент раскрывающийся список городов, как мы надеемся, будет заполнен значениями, соответствующими выбранной стране. Чтобы удостовериться, что пункты раскрывающегося списка правильные, мы сначала создаем список фактических (actual) названий городов. Мы считаем эти значения с веб-страницы:
List<String> actualCities = new ArrayList<>();
for (WebElement option : page.citySelect().getOptions()) {
actualCities.add(option.getText());
}
Мы также должны создать список ожидаемых названий городов. В объекте Enum они хранятся в свойствах List<String> cities
. Мы создадим список ожидаемых значений, первым делом добавив в него пустую строку. Затем мы воспользуемся методом addAll()
и сразу добавим все пункты из списка cities
.
List<String> expectedCities = new ArrayList<>();
expectedCities.add(0, "");
expectedCities.addAll(country.cities);
Теперь остается только сравнить списки фактических и ожидаемых значений. Разумеется, предварительно отсортировав эти списки.
Collections.sort(expectedCities);
Collections.sort(actualCities);
assertEquals(expectedCities, actualCities);
Итак, в этом сценарии, выполняя проход по каждой стране, мы проверяем соответствующий ей список городов. Для каждой страны с нуля создаются списки ожидаемых и фактических городов. Они содержат только информацию, соответствующую этой стране. Теперь весь тест выглядит следующим образом:
@Test
void checkCities() {
for (Country country : Country.values()) {
page.countrySelect().selectByVisibleText(country.label);
List<String> actualCities = new ArrayList<>();
for (WebElement option : page.citySelect().getOptions()) {
actualCities.add(option.getText());
}
List<String> expectedCities = new ArrayList<>();
expectedCities.add(0, "");
expectedCities.addAll(country.cities);
Collections.sort(expectedCities);
Collections.sort(actualCities);
assertEquals(expectedCities, actualCities);
}
}
Заключение
Надеюсь, эти примеры будут вам полезны и вдохновят вас использовать объекты Enum
для тестирования подходящих конструкций. Весь код можно посмотреть в моем репозитории проекта на GitHub:
Удачного тестирования!
Узнать подробнее о курсе "Java QA Automation Engineer".
Записаться на открытый урок "HTTP. Postman, newman, fiddler (charles), curl, SOAP. SOAPUI".
Chronicler
Вам за такое ужасное качество перевода совсем не стыдно? Понятно что есть гугл транслейт. Но хоть прочитали бы перед тем как копипастить сюда.
sshikov
Вы знаете, некоторые тексты гугл уже переводит лучше чем ряд местных «редакторов». Неоднократно видел такое, причем на разные темы (ИТ или скажем космонавтика).