Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:调用名称存储在变量中的方法_Java_Selenium - Fatal编程技术网

Java:调用名称存储在变量中的方法

Java:调用名称存储在变量中的方法,java,selenium,Java,Selenium,我的要求如下: String command = "click"; // this can have value such as clear, getLocation, getSize, getTagName etc. WebDriver driver = new ChromeDriver(options); //creating a webdriver object driver.findElement(By.id("id1")).click(); //Here I want "clic

我的要求如下:

String command = "click";   // this can have value such as clear, getLocation, getSize, getTagName etc. 
WebDriver driver = new ChromeDriver(options); //creating a webdriver object
driver.findElement(By.id("id1")).click(); //Here I want "click" method should be called dynamically as per what I have stored in variable `command`.
那么,有没有可能这样的事情:

driver.findElement(By.id("id1")).<something to call click()>
driver.findElement(By.id(“id1”))。

我已经研究了Java中的反射,但根据我的要求,这看起来很复杂。任何提示都会有帮助

您的变量表示希望对web元素执行的操作(在本例中,单击它)

相应的类型不是
String
。使用
消费者
(或
driver.findElement()
返回的任何类型):

Consumer命令=e->e.点击();
// ...
command.accept(driver.findElement(By.id(“id1”));

这是类型安全、高效、可重构的,并且比反射灵活得多(因为您的使用者可以对元素执行任何它想要的操作,而不限于不带任何参数的单个方法调用。例如,在文本字段中输入一些文本)

最简单的方法是使用反射:

String command = "click";
WebElement element = driver.findElement(By.id("id1"));

Method method = WebElement.class.getMethod(command);
method.invoke(element);
如果还希望通过.id调用
By.id
,则可以执行以下操作:

String command = "click";
String id = "id";

Method byMethod = By.class.getMethod(id, String.class);
WebElement element = driver.findElement((By) byMethod.invoke(null, "id1"));

Method method = WebElement.class.getMethod(command);
method.invoke(element);
在设计方面(可能可以进一步优化和抽象),您可能可以定义一个
Enum
,我们将其命名为
Action

public enum Action {
 CLICK,
 SENDKEY,
 etc
}
在代码中,然后执行以下操作:

Action action = <input>;
// find the element
WebElement element = driver.findElement(By.id("id1"));
switch(action) {
    case CLICK:
        element.click();
        break;
    case SENDKEY:
        element.sendKey();
        break;
    ...
    default:
        System.out.println("Undefined action");
        break;
}
Action=;
//找到元素
WebElement=driver.findElement(By.id(“id1”));
开关(动作){
案例点击:
元素。单击();
打破
案例发送键:
元素sendKey();
打破
...
违约:
System.out.println(“未定义动作”);
打破
}

似乎您正在尝试构建一个关键字驱动的框架。老实说,我会非常惊讶地听到任何成功的故事。我一直想知道这种框架的真正目的是什么?谁会用它?管理者、手动质量保证机构或利益相关者?对我来说,让非技术人员参与测试自动化活动毫无意义。任何自动化都需要良好的技术技能(包括编程和devops)。否则,失效概率相当高

无论如何,您的问题更多的是关于
字符串
功能接口
映射,或者非常智能的反射用法。但主要的问题是,您为此选择了错误的API[输入]。以下一行:

driver.findElement(locator).doSmth();
是一种正确的失败方式,因为
findElement
使用隐式等待。我100%确信,当您面对
NoTouchElementException
/
StaleElementReferenceException
时,您将开始全局重构/修改实现的方法

常识建议对
ExpectedConditions
使用流畅的等待。但这会使您的任务更加复杂,因为除了定位器和操作之外,您还必须考虑用户应该提供的条件

从技术角度来看,我会首先创建公共包装器来封装低级WebDriver API调用。与原始调用相比,映射或反映这样的函数要容易得多。例如,可以在枚举级别隐藏预期条件:

@Getter
@RequiredArgsConstructor
public enum WaitCondition {

    visible(ExpectedConditions::visibilityOfElementLocated),
    enabled(ExpectedConditions::elementToBeClickable);

    private final Function<By, ExpectedCondition<WebElement>> type;
}

本线程中的其他人已经提供了映射/反射示例。请注意:如果您喜欢反射,我建议您查看库,它简化了这个过程。

好的一点,可能有一个
MapHi JB:所以,根据您的说法,我必须提到
消费者
分配期间的
点击
?如果我想调用像
clear
getLocation
等命令,那么我必须再次定义明确性,比如
consumercommand=e->e.clear()我是对的,还是我遗漏了什么?是的。就像您必须更改
String command=“click”插入
String命令=“清除”。除非您确实要使用现有的方法,否则您的IDE将提供自动完成功能,您可以传递参数(即
Consumer command=e->e.sendKeys(“hello”);
)。关于第一部分:然后将您的命令解析为Consumer:即“click”解析为
e->e.click()
,“text\u hello”例如,解析为
e->e.sendKeys(“hello”)
。关于第二部分,使用一个包含消费者的对象和一个
By
实例,允许查找要消费的元素。在某些情况下,甚至可以通过使用方法引用将其缩短一点,例如,Consumer command=WebElement::click;我真的很抱歉,因为我在同一个问题中又问了一个问题。如果我的
id
也存储在变量中,该怎么办。例如,一个包含
id
xpath
的变量,我必须根据该变量采取行动:
driver.findelelement(By.(“id1”)。
在这种情况下,如何扩展您的解决方案?@OmSao我对代码做了一些修改,并为您的第二个问题添加了答案。请告诉我这个代码是否有效,因为我还没有测试过它。
@Getter
@RequiredArgsConstructor
public enum WaitCondition {

    visible(ExpectedConditions::visibilityOfElementLocated),
    enabled(ExpectedConditions::elementToBeClickable);

    private final Function<By, ExpectedCondition<WebElement>> type;
}
protected void click(By locator) {
    click(locator, enabled);
}

protected void click(By locator, WaitCondition condition) {
    waitFor(locator, condition).click();
}

private WebElement waitFor(By locator, WaitCondition condition) {
    return wait.until(condition.getType().apply(locator));
}