Selenium测试运行得太快,而不是等待选择单选按钮

时间:2015-10-14 14:03:14

标签: java selenium selenium-webdriver

我有一个运行速度太快的Selenium Grid和WebDriver 2.48.2测试。大多数时间测试停止,因为在按下按钮之前未选择单选按钮。

使用基于JSON文件的JavaScript设置单选按钮,以便在一个部分内动态创建任意数量的单选按钮。单击“继续”按钮后,该部分将被销毁,并使用新的单选按钮创建一个新部分。

我尝试了隐含的等待但没有成功。

driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);

唯一对我有用的解决方案是延迟,以便有足够的时间点击单选按钮。

driver.findElement(By.id("radiobuttonid")).click();
Thread.sleep(delay);

但在我看来,这不是一个理想的解决方案,延迟时间可能不够长,或者时间太长,浪费时间;可以有任意数量的单选按钮,因此时间会呈指数级增长。

我尝试使用不同的explicit waits设置各种expected conditions,但没有成功。

我已经尝试等待创建单选按钮,因为它可能不存在(presenceOfElementLocated& elementToBeClickable)。我已经尝试等待它被选中(elementToBeSelected)。

由于描述简短且容易被误解,我无法准确找到预期的条件应该做什么。

理想情况下,我希望在单击单选按钮后立即继续测试。如果可能的话,最好的方法是什么?

修改

下面的L.Bar suggestion对我来说不起作用,但确定单选按钮存在非常有帮助,只是在单选按钮被选中之前点击了继续按钮

编辑2

这只是为了扩展耶利米的正确答案。我将代码放入一个方法,使其可重用。

private static Predicate<WebDriver> forceSelectionOfElement (final String id)
{
    return new Predicate<WebDriver>()
    {
        @Override
        public boolean apply(WebDriver arg0)
        {
            WebElement element = arg0.findElement(By.id(id));                
            boolean rval = element.isSelected();

            if (!rval) {
                element.click();
            }

            return rval;
        }
    };
}

用法

WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(forceSelectionOfElement("q___01_02_01___1___a"));

记得要导入这个命名空间,我花了很长时间才弄清楚我导入了错误的命名空间:)

import com.google.common.base.Predicate;

3 个答案:

答案 0 :(得分:4)

我遇到了类似的问题,但在我的情况下,我的“点击”事件在某个地方丢失了。我的测试将继续,点击代码将触发,但元素的状态永远不会明显改变,测试将失败。我最后通过添加一个对所选状态更持久的自定义谓词来利用WebDriverWait的循环行为。

WebDriverWait wait = new WebDriverWait(driver, 5);
        final By lookup = By.id("radio");
        LOG.debug("Wait for radio to be clickable.");
        wait.until(ExpectedConditions.elementToBeClickable(lookup)); //I assume this implies visibility.
        LOG.debug("Element clickable.  Proceeding into click behavior.");
        wait.until(new Predicate<WebDriver>() {
            @Override
            public boolean apply(WebDriver arg0) {
                LOG.debug("Resolving 'myId' Element");
                WebElement radio = arg0.findElement(lookup);                
                boolean rval = radio.isSelected();
                LOG.debug("Element Resolved and has a state of " + (rval ? "selected" : "not selected"));
                if (!rval) {
                    LOG.debug("Clicking on the Element!");
                    radio.click();
                }
                //If we return false we will loop.  So the first time through we let this click the radio for us.
                //Second time through we should find that the element is clicked.  If it's not we click it again until it represents the state we're wanting.
                return rval;;
            }});

自定义谓词

  1. 解析WebElement
  2. 捕获当前的选定状态
  3. 如果未选择WebElement,请单击
  4. 返回当前所选状态。
  5. 所以这不应该允许测试继续进行,直到元素的点击状态是我想要的。到目前为止,基本上完成了我想要的工作。

    值得注意的是,Thread.sleep被认为不是硒相互作用的最佳实践。这就是ExplicitWait概念所要考虑的内容。我已经链接了一个最新的主题,其中我知道正在讨论这个问题。

    Thread.sleep works but implicit wait, webdriverwait and fluent wait does not?

    最好的运气!

答案 1 :(得分:3)

我的方法:

public bool IsElementPresent(By by, IWebDriver driver)
{
    try
    {
        driver.FindElement(by);
        return true;
    }
    catch (NoSuchElementException)
    {
        return false;
    }
}

public bool IsElementPresent(By by, IWebDriver driver, int sec)
{
    bool itemExist = false;

    itemExist = IsElementPresent(by, driver);
    while (!itemExist && sec >= 0)
    {
        Thread.Sleep(1000);
        itemExist = IsElementPresent(by, driver);
        sec--;
    }

    if (sec == -1)
        return false;
    else
        return true;
}

调用测试是否存在

//Checking if element exist 10 sec
if(IsElementPresented(By.Id("radiobuttonid"),driver,10))
{
//element exist click on it
}
else
{
//didn't exist.
}

答案 2 :(得分:1)

你说过你探索过ExpectedConditions,你试过ExpectedConditions.elementToBeSelected()吗?您应该能够检测是否选中了单选按钮,然后向前移动。试试这样的事情

WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement radio = driver.findElement(By.id("radiobuttonid"));
radio.click();
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("ID of message element")));
// do stuff

修改

从OP

获取更多信息后更改了代码