我们的团队一直在用Selenium测试我们的应用程序,因为它是由JavaScript驱动的,我们总是遇到测试偶尔失败的问题。随着测试次数的增加,至少有两次测试在完整运行中失败的可能性已经确定。
我们最近发现,我们可能有一个竞争条件,在初始化JavaScript有机会将事件处理程序附加到被单击的元素之前,selenium将单击链接。当然,在这一点上,我们正在寻找的效果不会发生,我们会得到一个失败的测试。
目前我们在点击之前添加了一点点延迟,以便给初始化JavaScript代码完成时间,这显然有些苛刻,增加了整体测试执行的时间,并且不保证测试不会仍然存在失败所以我们正在寻找更好的解决方案。
到目前为止,我们提出的最好的想法是将一个隐藏元素注入到Selenium可以等待的DOM中,然后再触发click事件以了解它已准备就绪。当我们处理异步事件,删除和添加元素时,这将是开发人员时间方面的大量额外开销。此外,它还为我们的页面添加了额外的东西,这对应用程序来说并不是必需的。
有没有人有更好的策略?你有什么办法来有效地解决这个问题?
答案 0 :(得分:3)
我们转移到Selenium 2(WebDriver)并使用Page Objects pattern和PageFactory / AjaxElementLocatorFactory - 这个例子是here
答案 1 :(得分:2)
我确实喜欢你:添加一些延迟并等待页面上出现一些元素。我完全没问题。也许切换到Webdriver / selenium 2.0会有所帮助。如果您使用内存数据库或在测试之间共享相同的selenium / selenium服务器,或者甚至使用并行化(例如,使用TestNG很容易),可以减少测试执行。
答案 2 :(得分:1)
您是否尝试过waitForElementPresent命令,然后单击它?
答案 3 :(得分:1)
要消除竞争条件,请使用Selenium的runScript(String initCondition)
结合waitForCondition(String jsConditional, String timeout)
方法。
例如,如果要测试的AJAX功能导致将新元素添加到dom,则可以使用以下内容。
String jsPoll = "";
jsPoll += "selenium.browserbot.getCurrentWindow()";
jsPoll += ".document.getElementById('DOMID')";
selenium.waitForCondition(jsPoll, "30000");
当添加元素并且方法将继续时,条件将评估为true。如果您的AJAX函数交换元素(即:一个div用于另一个类似标识的div),您可以使用以下内容初始化条件。
String jsInit = "";
jsInit += "!selenium.browserbot.getCurrentWindow()";
jsInit += ".document.getElementById('DOMID').setAttribute('SELENIUMTEST','1')";
String jsPoll = "";
selenium.runScript(jsInit);
jsPoll += "selenium.browserbot.getCurrentWindow()";
jsPoll += ".document.getElementById('DOMID').getAttribute('SELENIUMTEST') != 1";
selenium.waitForCondition(jsPoll, "30000");
当AJAX函数换出元素时,条件的计算结果为true。
答案 4 :(得分:1)
IMHO延迟不是一个好的解决方案(只是一种解决方法)。
我们使用iMacros的图像识别功能来测试棘手的AJAX(和Flash)。对于selenium,也许您可以将它与AutoHotKey(包含基本图像搜索并且作为桌面应用程序测试工具流行)结合使用? http://www.autohotkey.com/docs/commands/ImageSearch.htm