Selenium 2 (WebDriver):在调用 Alert.getText() 之前检查文本是否存在

发布于 2024-11-25 13:55:24 字数 1334 浏览 2 评论 0原文

我遇到了在切换到警报之前检查警报是否存在<中描述的问题< /a>.我发现捕获 NullPointerException 非常糟糕。有没有人更优雅地解决这个问题?

我当前的解决方案使用捕获 NPE 的等待。客户端代码只需调用 waitForAlert(driver, TIMEOUT)

/**
 * If no alert is popped-up within <tt>seconds</tt>, this method will throw
 * a non-specified <tt>Throwable</tt>.
 * 
 * @return alert handler
 * @see org.openqa.selenium.support.ui.Wait.until(com.​google.​common.​base.Function)
 */
public static Alert waitForAlert(WebDriver driver, int seconds) {
    Wait<WebDriver> wait = new WebDriverWait(driver, seconds);
    return wait.until(new AlertAvailable());
}

private static class AlertAvailable implements ExpectedCondition<Alert> {
    private Alert alert = null;
    @Override
    public Alert apply(WebDriver driver) {
        Alert result = null;
        if (null == alert) {
            alert = driver.switchTo().alert();
        }

        try {
            alert.getText();
            result = alert;
        } catch (NullPointerException npe) {
            // Getting around https://groups.google.com/d/topic/selenium-users/-X2XEQU7hl4/discussion
        }
        return result;
    }
}

I came across the problem described in Checking If alert exists before switching to it. I find horrible to capture a NullPointerException. Has anyone solved this problem more elegantly?

My current solution uses a wait that captures the NPE. The client code just have to invoke waitForAlert(driver, TIMEOUT):

/**
 * If no alert is popped-up within <tt>seconds</tt>, this method will throw
 * a non-specified <tt>Throwable</tt>.
 * 
 * @return alert handler
 * @see org.openqa.selenium.support.ui.Wait.until(com.​google.​common.​base.Function)
 */
public static Alert waitForAlert(WebDriver driver, int seconds) {
    Wait<WebDriver> wait = new WebDriverWait(driver, seconds);
    return wait.until(new AlertAvailable());
}

private static class AlertAvailable implements ExpectedCondition<Alert> {
    private Alert alert = null;
    @Override
    public Alert apply(WebDriver driver) {
        Alert result = null;
        if (null == alert) {
            alert = driver.switchTo().alert();
        }

        try {
            alert.getText();
            result = alert;
        } catch (NullPointerException npe) {
            // Getting around https://groups.google.com/d/topic/selenium-users/-X2XEQU7hl4/discussion
        }
        return result;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

乱了心跳 2024-12-02 13:55:24

FluentWait.until() 的 JavaDoc

重复将此实例的输入值应用于给定函数,直到发生以下情况之一:

  1. 该函数既不返回 null 也不返回 false,
  2. 函数抛出一个不可忽略的异常,
  3. 超时结束
    ……(剪断)

由于 NullPointerException 表示错误条件,并且 WebDriverWait 仅忽略 NotFoundException,因此只需删除 try/捕获块。在 apply() 中抛出未经检查、未忽略的 Exception 在语义上等同于在现有代码中返回 null

private static class AlertAvailable implements ExpectedCondition<Alert> {
    @Override
    public Alert apply(WebDriver driver) {
        Alert result = driver.switchTo().alert();
        result.getText();
        return result;
    }
}

JavaDoc for FluentWait.until()

Repeatedly applies this instance's input value to the given function until one of the following occurs:

  1. the function returns neither null nor false,
  2. the function throws an unignored exception,
  3. the timeout expires
    .......(snip)

Since NullPointerException denotes a false condition, and WebDriverWait is only ignoring NotFoundException, just remove the try/catch block. An unchecked, unignored Exception thrown in apply() is semantically equivalent to returning null as in your existing code.

private static class AlertAvailable implements ExpectedCondition<Alert> {
    @Override
    public Alert apply(WebDriver driver) {
        Alert result = driver.switchTo().alert();
        result.getText();
        return result;
    }
}
倥絔 2024-12-02 13:55:24

基于@Joe Coder 答案,这种等待的简化版本是:

/**
 * If no alert is popped-up within <tt>seconds</tt>, this method will throw
 * a non-specified <tt>Throwable</tt>.
 * 
 * @return alert handler
 * @see org.openqa.selenium.support.ui.Wait.until(com.​google.​common.​base.Function)
 */
public static Alert waitForAlert(WebDriver driver, int seconds) {
    Wait<WebDriver> wait = new WebDriverWait(driver, seconds)
        .ignore(NullPointerException.class);
    return wait.until(new AlertAvailable());
}

private static class AlertAvailable implements ExpectedCondition<Alert> {
    @Override
    public Alert apply(WebDriver driver) {
        Alert alert = driver.switchTo().alert();
        alert.getText();
        return alert;
    }
}

我编写了一个简短的测试来证明这个概念:

import com.google.common.base.Function;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestUntil {
    private static Logger log = LoggerFactory.getLogger(TestUntil.class);

    @Test
    public void testUnit() {
        Wait<MyObject> w = new FluentWait<MyObject>(new MyObject())
                .withTimeout(30, TimeUnit.SECONDS)
                .ignoring(NullPointerException.class);
        log.debug("Waiting until...");
        w.until(new Function<MyObject, Object>() {
            @Override
            public Object apply(MyObject input) {
                return input.get();
            }
        });
        log.debug("Returned from wait");
    }

    private static class MyObject {
        Iterator<Object> results = new ArrayList<Object>() {
            {
                this.add(null);
                this.add(null);
                this.add(new NullPointerException("NPE ignored"));
                this.add(new RuntimeException("RTE not ignored"));
            }
        }.iterator();
        int i = 0;
        public Object get() {
            log.debug("Invocation {}", ++i);
            Object n = results.next();
            if (n instanceof RuntimeException) {
                RuntimeException rte = (RuntimeException)n;
                log.debug("Throwing exception in {} invocation: {}", i, rte);
                throw rte;
            }
            log.debug("Result of invocation {}: '{}'", i, n);
            return n;
        }
    }
}

在这段代码中,在untilMyObject.get() 被调用四次。第三次,它抛出一个被忽略的异常,但最后一次抛出一个未被忽略的异常,中断了等待。

输出(为了便于阅读而进行了简化):

Waiting until...
Invocation 1
Result of invocation 1: 'null'
Invocation 2
Result of invocation 2: 'null'
Invocation 3
Throwing exception in 3 invocation: java.lang.NullPointerException: NPE ignored
Invocation 4
Throwing exception in 4 invocation: java.lang.RuntimeException: RTE not ignored

------------- ---------------- ---------------
Testcase: testUnit(org.lila_project.selenium_tests.tmp.TestUntil):  Caused an ERROR
RTE not ignored
java.lang.RuntimeException: RTE not ignored
    at org.lila_project.selenium_tests.tmp.TestUntil$MyObject$1.<init>(TestUntil.java:42)
    at org.lila_project.selenium_tests.tmp.TestUntil$MyObject.<init>(TestUntil.java:37)
    at org.lila_project.selenium_tests.tmp.TestUntil$MyObject.<init>(TestUntil.java:36)
    at org.lila_project.selenium_tests.tmp.TestUntil.testUnit(TestUntil.java:22)

请注意,由于 RuntimeException 未被忽略,因此不会打印“Returned from wait”日志。

Based upon @Joe Coder answer, a simplified version of this wait would be:

/**
 * If no alert is popped-up within <tt>seconds</tt>, this method will throw
 * a non-specified <tt>Throwable</tt>.
 * 
 * @return alert handler
 * @see org.openqa.selenium.support.ui.Wait.until(com.​google.​common.​base.Function)
 */
public static Alert waitForAlert(WebDriver driver, int seconds) {
    Wait<WebDriver> wait = new WebDriverWait(driver, seconds)
        .ignore(NullPointerException.class);
    return wait.until(new AlertAvailable());
}

private static class AlertAvailable implements ExpectedCondition<Alert> {
    @Override
    public Alert apply(WebDriver driver) {
        Alert alert = driver.switchTo().alert();
        alert.getText();
        return alert;
    }
}

I have written a short test to proof the concept:

import com.google.common.base.Function;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestUntil {
    private static Logger log = LoggerFactory.getLogger(TestUntil.class);

    @Test
    public void testUnit() {
        Wait<MyObject> w = new FluentWait<MyObject>(new MyObject())
                .withTimeout(30, TimeUnit.SECONDS)
                .ignoring(NullPointerException.class);
        log.debug("Waiting until...");
        w.until(new Function<MyObject, Object>() {
            @Override
            public Object apply(MyObject input) {
                return input.get();
            }
        });
        log.debug("Returned from wait");
    }

    private static class MyObject {
        Iterator<Object> results = new ArrayList<Object>() {
            {
                this.add(null);
                this.add(null);
                this.add(new NullPointerException("NPE ignored"));
                this.add(new RuntimeException("RTE not ignored"));
            }
        }.iterator();
        int i = 0;
        public Object get() {
            log.debug("Invocation {}", ++i);
            Object n = results.next();
            if (n instanceof RuntimeException) {
                RuntimeException rte = (RuntimeException)n;
                log.debug("Throwing exception in {} invocation: {}", i, rte);
                throw rte;
            }
            log.debug("Result of invocation {}: '{}'", i, n);
            return n;
        }
    }
}

In this code, in the until the MyObject.get() is invoked four times. The third time, it throws an ignored exception, but the last one throws a not-ignored exception, interrupting the wait.

The output (simplified for readability):

Waiting until...
Invocation 1
Result of invocation 1: 'null'
Invocation 2
Result of invocation 2: 'null'
Invocation 3
Throwing exception in 3 invocation: java.lang.NullPointerException: NPE ignored
Invocation 4
Throwing exception in 4 invocation: java.lang.RuntimeException: RTE not ignored

------------- ---------------- ---------------
Testcase: testUnit(org.lila_project.selenium_tests.tmp.TestUntil):  Caused an ERROR
RTE not ignored
java.lang.RuntimeException: RTE not ignored
    at org.lila_project.selenium_tests.tmp.TestUntil$MyObject$1.<init>(TestUntil.java:42)
    at org.lila_project.selenium_tests.tmp.TestUntil$MyObject.<init>(TestUntil.java:37)
    at org.lila_project.selenium_tests.tmp.TestUntil$MyObject.<init>(TestUntil.java:36)
    at org.lila_project.selenium_tests.tmp.TestUntil.testUnit(TestUntil.java:22)

Note that as the RuntimeException is not ignored, the "Returned from wait" log is not printed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文