我正在开发一个网站并尝试使用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经常出现故障。
存在不可预测的行为这一事实表明我无法控制所需的所有事情(和/或我控制事情的尝试是错误的)。我无法看到我做任何特别奇怪的事情,所以有人必须在此之前遇到过这类问题。
是否存在我未解决的浏览器问题? 在设定价值方面我有什么问题吗? 在我的测试编排中,我有什么问题吗?
答案 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();