在测试自动化中使用Java枚举
在决定用于存储测试数据的数据类型时,您可能需要满足以下条件:
允许声明多个属性
无行为或行为极少
允许轻松创建多个相似实体
对象几乎可以满足这些要求。但是,创建多个实体将意味着创建几个仅具有少量属性且没有行为或行为最少的对象。最小的行为转化为少量的方法。基本上,对于您需要的每个实体,都必须创建一个新的对象。那将是浪费。相反,可以使用一种特殊类型的Object Enum。
我们可以使用Enums来表示概念,例如:工作日,一年中的月份,浏览器或语言。在本文中,我想举例说明Enums的用法,该枚举具有多个属性和一个表示国家的构造函数。您可以在本文末尾找到GitHub链接,以链接到此处示例的所有代码。有关枚举是什么的信息,请参考官方文档。
在测试中使用Java枚举:国家/地区示例
对于此示例,让我们考虑一下,在测试中,您需要填写国家/地区特定的注册表。您需要在此表单中提供的一些详细信息是:国家/地区,该国家/地区的城市以及国家/地区专用的电话号码,所有这些都属于您要填写注册表格的客户。您正在使用的网站在全球许多国家/地区都可以使用。
为了进行测试,让我们缩小将要使用的国家/地区的范围:奥地利,爱沙尼亚和西班牙。这些国家/地区中的每个国家/地区都有我们需要在注册表格中提供的3个属性:国家/地区名称,城市列表和电话前缀。基于此前缀,我们可以生成一个测试电话号码。为了代表每个国家/地区,我们将使用枚举。用于表示国家/地区的常数值为:AT,EE和ES。
我们将声明枚举如下:
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
cities; public int phoneNumberPrefix;
Country(String label, List
cities, int phoneNumberPrefix) { this.label = label;
this.cities = cities;
this.phoneNumberPrefix = phoneNumberPrefix;
}
}
首先我们为国家常数指定允许值的集合,以及所有属性的允许值。我们通过声明标签,城市和phoneNumberPrefix来定义这些属性的类型。它们是:一个字符串,一个字符串列表和一个整数。
构造函数在内部用于生成Enum值。因此,例如,“ AT”具有属性,其顺序与构造函数中参数的顺序相对应:“ 标签 ”属性值为“奥地利”,属于该国家/地区的“ 城市 ” 列表为:“维也纳”, “ Salzburg”,“ Innsbruck”和“ phoneNumberPrefix ”为43。
我们可以按如下方式检索与Enum常量相对应的属性:Country.CONSTANT.propertyName。例如:Country.AT.label将给我们“奥地利”。如您所见,Country属性是静态的。
在注册表格上,从下拉列表中选择国家,从另一个下拉列表中选择城市,并通过在字段中键入来提供电话号码。
为国家/地区特定信息创建的Page类包含以下条目:
private WebElement countryDropdown;
private WebElement cityDropdown;
public WebElement phoneNumberField;
public WebElement submitButton;
public Select countrySelect() {
return new Select(countryDropdown);
}
public Select citySelect() {
return new Select(cityDropdown);
}
countrySelect()方法将返回一个Select(引用)国家/地区下拉列表。同样,citySelect()方法返回引用城市下拉菜单的Select。phoneNumberField WebElement将用于输入电话号码。
在本文中,我将省略打开浏览器,打开网页和关闭浏览器的部分。您可以在本文结尾处提供的GitHub存储库中看到所有这些部分。
方案1:填写西班牙客户的注册表
打开浏览器并访问注册页面后,测试将需要填写西班牙客户的详细信息。我们将选择国家/地区,然后选择瓦伦西亚市,然后输入由10位数字组成的随机电话号码。注册表的国家部分如下所示:
因此,我们将为此活动创建一个新测试:
void selectCountryCityAndTypePhoneNumber() {
}
首先,我们将选择国家。这意味着,从国家/地区下拉列表中,我们将选择与“ ES”枚举条目的“ 标签 ”属性相对应的值。这很容易检索:Country.ES.label。选择国家的步骤如下:
page.countrySelect().selectByVisibleText(Country.ES.label);
接下来,我们需要从相应的下拉列表中选择城市。完成访问城市列表的操作:Country.ES.cities。访问与Valencia相对应的List元素(第三个元素)已完成:Country.ES.cities.get(2)。从城市下拉列表中选择此值:
page.citySelect().selectByVisibleText(Country.ES.cities.get(2));
现在,最后一步意味着需要生成电话号码,其第一个数字代表国家/地区前缀。可以从枚举中检索前缀,如下所示: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.commonsgroupId>
<artifactId>commons-lang3artifactId>
<version>3.9version>
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开始,即检查国家/地区下拉列表是否包含正确的值。我们将首先构建“预期”内容。我们知道我们已经将期望值存储为Enum中的“ label ”参数,但是我们还需要处理下拉菜单中显示的空文本选项。请记住,我们将使用Selenium读取网页中的值,并将它们作为String返回,我们可以创建一个预期的String国家值列表。首先,我将创建列表并向其中添加第一个元素,它是一个空字符串。这将对应于国家下拉列表中的空字符串。
List<String> expectedCountries = new ArrayList<>();
expectedCountries.add("");
现在,我们需要添加枚举中所有的' label '值。为此,我们需要遍历所有Enum项,并将每个对应的“ label ”字符串值添加到预期字符串列表中。我们将使用' Country.values() '方法遍历每个Enum条目。
for (Country country : Country.values()) {
expectedCountries.add(country.label);
}
此时,我们的预期国家列表包含4个条目:“”,“奥地利”,“爱沙尼亚”,“西班牙”。
现在,我们可以从网页上读取国家/地区值,并将其存储到“实际”值列表中。因为我们正在处理“选择”,所以我们需要遍历属于“选择”的所有“选项” WebElement。我们需要将“ getText()”应用于每个“选项”,并将这些结果字符串添加到实际字符串列表中。
List<String> actualCountries = new ArrayList<>();
for (WebElement option : page.countrySelect().getOptions()) {
actualCountries.add(option.getText());
}
在比较预期列表和实际列表之前,我们需要考虑一下,枚举标签和下拉选项值的顺序可能不相同。因此,我们应该对它们进行排序,然后进行比较。
Collections.sort(expectedCountries);
Collections.sort(actualCountries);
assertEquals(expectedCountries, actualCountries);
完整代码如下:
@Test
void checkCountries() {
List
expectedCountries = new ArrayList<>(); expectedCountries.add("");
for (Country country : Country.values()) {
expectedCountries.add(country.label);
}
List
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”循环中,让我们从“国家/地区”下拉列表中选择与当前Enum条目的“ label ”属性相对应的国家/地区:
page.countrySelect().selectByVisibleText(country.label);
此时,我们希望在城市下拉列表中填充与所选国家/地区对应的值。为了确保下拉选项正确,我们将首先创建“实际”城市名称列表。我们将从网页上读取以下值:
List<String> actualCities = new ArrayList<>();
for (WebElement option : page.citySelect().getOptions()) {
actualCities.add(option.getText());
}
我们还必须创建预期城市名称列表。在枚举中,这些存储为字符串属性的“ city ”列表。我们将通过首先向列表中添加一个空字符串来创建期望值列表。然后,我们将使用'addAll()'方法立即添加' 城市 '列表中的所有项目。
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
actualCities = new ArrayList<>(); for (WebElement option : page.citySelect().getOptions()) {
actualCities.add(option.getText());
}
List
expectedCities = new ArrayList<>(); expectedCities.add(0, "");
expectedCities.addAll(country.cities);
Collections.sort(expectedCities);
Collections.sort(actualCities);
assertEquals(expectedCities, actualCities);
}
}