使用Selenium和jUnit进行不可预测的行为

时间:2016-04-20 07:13:41

标签: selenium junit

我正在开发一个网站并尝试使用Selenium和jUnit进行测试。尽管我尽了最大的努力,但我在测试和网站之间遇到了竞争条件。 该网站的前端是HTML和jQuery。后端(通过AJAX)是PHP。

网站

我有两个必需的文本输入字段(年份和年龄),以及其他一些我在测试中没有改变的问题。只要两个文本输入都是非空的,就会对后端进行AJAX调用。这将返回0+结果。如果返回0结果,则屏幕上的结果div会显示一些文本,表示没有结果。如果返回> 0结果,则会将一个表写入显示结果的结果div。

我不希望网站等到例如在进行AJAX调用之前输入了4位数的年份,因为它可以查看古代历史(是的,真的)。因此,一旦两者都非空,就应该进行调用。如果您输入缓慢,则表示输入例如2015年将触发年= 2,年= 20,年= 201和年= 2015的通话。 (这没关系。)

测试

我正在使用页面对象 - 一个用于输入,一个用于输出。在测试开始时,我等待屏幕上出现提示(请输入一些数据),因为它是由JavaScript生成的,用于检查输入字段的状态 - 所以我知道页面已经加载并且JavaScript已经运行

在为输出创建页面对象后立即等待提示。这是页面对象中的相关方法:

// Wait until the prompt / help text is displayed.  Assumes that the prompt text always contains the word "Please"
public void waitForText() {
    wait.until(ExpectedConditions.textToBePresentInElementLocated(By.id("resultContainer"), "Please"));
}

设定年份的方法是

public void setYear(String year){

    WebElement yearField = driver.findElement(By.id(yearInputId));

    if (yearField == null) {
        // This should never happen
        Assert.fail("Can't find year input field using id " + yearInputId);
    } else {
        yearField.sendKeys(new String [] {year});
        driver.findElement(By.id(ageInputId)).click();  // click somewhere else
    }
}

并且有一个相应的年龄。

我有一系列等待事情发生的方法,这些方法似乎没有阻止问题(如下)。这些操作会等待当前结果值与之前的结果值不同,等待返回一定数量的结果等。

我为Chrome创建了一个驱动程序,如下所示:

import org.openqa.selenium.chrome.ChromeDriver;
// ...
        case CHROME: {
            System.setProperty("webdriver.chrome.driver", "C:\\path\\chromedriver.exe");
            result = new ChromeDriver();
            break;
        }

问题

有些时候,事情还可以。有些时候,两个输入都通过测试填充了合理的值,但显示“有0个结果”消息。有些时候,测试通过填写输入部分挂起。当我使用Firefox进行测试时似乎很好,但Chrome经常出现故障。

存在不可预测的行为这一事实表明我无法控制所需的所有事情(和/或我控制事情的尝试是错误的)。我无法看到我做任何特别奇怪的事情,所以有人必须在此之前遇到过这类问题。

是否存在我未解决的浏览器问题? 在设定价值方面我有什么问题吗? 在我的测试编排中,我有什么问题吗?

1 个答案:

答案 0 :(得分:1)

当您开始键入时,脚本仍在加载,或者当您开始处理下一个字段或验证时,还有一个待处理的Ajax调用。 您可以尝试使用低级脚本同步调用:

const String JS_WAIT_NO_AJAX = 
    "var callback = arguments[0]; (function fn(){ " +
    "  if(window.$ && window.$.active == 0) " +
    "      return callback(); " +
    "  setTimeout(fn, 60); " +
    "})();";

JavascriptExecutor js = (JavascriptExecutor)driver;
driver.manage().timeouts().setScriptTimeout(20, TimeUnit.SECONDS);

js.executeAsyncScript(JS_WAIT_NO_AJAX);
driver.findElement(By.Id("...")).sendKeys("...");

js.executeAsyncScript(JS_WAIT_NO_AJAX);
driver.findElement(By.Id("...")).click();