想动态使用 Enum 文件名来获取常量

Want to use Enum file name dynamically to fetch constants

我有一个包含键值对的配置文件 language = "IN" 我有多个页面对象枚举文件,名称为 PageObject_US,PageObject_UK,PageObject_IN

每个页面对象枚举文件都有可以访问的常量,例如 PageObjects_US.String.lable

但我想要实现的是一种创建如下内容的方法

  1. 从配置文件中获取参数并将其存储在字符串中 像 String language = "IN"
  2. 然后使用“PageObjects_”+语言连接得到(PageObjects_IN)
  3. 以便返回值可用于从 PageObjects_IN.String.label.
  4. 中获取常量

代码块如下:


if(!ENV.equalsIgnoreCase("development") && VALIDATION.equalsIgnoreCase("yes")) {        
            Elements.ByTitle(webDriver,PageObjects_IN.GREAT.label);
            Elements.ByID(webDriver,  PageObjects_IN.COUNTER.label);
}

在上面我想在 运行 时使用枚举文件 PageObjects_IN 因为我有很多枚举文件

下面是枚举

public enum PageObjects_IN {
    // Text
    GREAT("great"), 
    COUNTER("counter");


    public final String lable;

    PageObjects_IN(final String lable) {
        this.lable = lable;
    }

}

这是可能的(使用反射)但强烈不推荐,因为它会降低 Java 语言构造的效率。

不推荐的方式

假设您有一个包裹click.webelement.cucumber.po,您将其存放在

public enum PO_EN {
    GREAT("great_en"),
    COUNTER("counter_en");

    public final String label;

    PO_EN(String label){
        this.label = label;
    }
}

public enum PO_IN {
    GREAT("great_in"),
    COUNTER("counter_in");

    public final String label;

    PO_IN(String label){
        this.label = label;
    }
}

然后要获取一个值,您可以这样做:

String lang = "EN";
// Take class
Class clazz = Class.forName("click.webelement.cucumber.po.PO_" + lang);
// Find an object that represent enum constant
Object val = Arrays
        .stream(clazz.getEnumConstants()).filter(o -> "GREAT".equals(o.toString()))
        .findAny()
        .get();
// Take field value for that object
Field f = clazz.getField("label");
System.out.println(f.get(val));

这是 error-prone 方法,您不会从编译阶段受益。

推荐方法 - 1

而不是 enum 使用 类.

public abstract class PO {

    public abstract String great();
    public abstract String counter();

}

public class PO_EN extends PO{
    @Override
    public String great() {
        return "great_en";
    }

    @Override
    public String counter() {
        return "counter_en";
    }
}

public class PO_IN extends PO{
    @Override
    public String great() {
        return "great_in";
    }

    @Override
    public String counter() {
        return "counter_in";
    }
}

所以你的测试会简单得多

String lang = "EN";
Class clazz = Class.forName("click.webelement.cucumber.po.PO_" + lang);
PO val = (PO) clazz.getDeclaredConstructor().newInstance();
System.out.println(val.great());

推荐方法 - 2

您可以将 PageFactory 工具用于您的页面对象,并使用 this lib 来参数化您的定位器,例如(如果您使用 test ng):

@DataProvider(name = "languages")
Object[][] dataProvider(){
    return new Object[][]{
            {"en", "great_en", "counter_en"},
            {"in", "great_in", "counter_in"}
    };
}

@Test(dataProvider = "languages")
public void testPage(String language, String great, String counter){
    DefaultParameterProvider
            .properties
            .set(Map.of("p.great", great, "p.counter", counter));
    MyPage myPage = new MyPage(driver);
    ...
}

你的页面应该是这样的:

public class MyPage extends PageObjectParameterized {

    @FindByParameterized(xpath = "//button[@name='{wec:p.great}']")
    WebElement great;

    @FindByParameterized(xpath = "//label[text()='{wec:p.counter}']")
    WebElement counter;

    @FindBy(xpath = "//input")
    WebElement input;
    
    public MyPage(SearchContext searchContext) {
        super(searchContext);
    }
}