我们一直在使用selenium非常成功地处理高级网站测试(除了模块级别的广泛python doctests)。然而,现在我们在很多页面上使用extjs,并证明很难将Selenium测试用于像网格这样的复杂组件。
有没有人成功为基于extjs的网页编写自动化测试?很多谷歌搜索发现有类似问题的人,但答案很少。谢谢!
答案 0 :(得分:173)
答案 1 :(得分:5)
这blog给了我很多帮助。他在这个主题上写了很多,看起来它仍然活跃。这家伙似乎也很欣赏好的设计。
他基本上讨论了使用发送javascript来执行查询和使用Ext.ComponentQuery.query方法来检索内容,就像在内部使用ext应用程序一样。这样你可以使用xtypes和itemIds,而不必担心尝试解析任何疯狂的自动生成的东西。
我发现this article特别有帮助。
可能很快会在这里发布更详细的内容 - 仍然试图让我的头脑如何正确地做到这一点
答案 2 :(得分:4)
我一直用selenium测试我的ExtJs Web应用程序。其中一个最大的问题是在网格中选择一个项目以便用它做点什么。
为此,我编写了辅助方法(在SeleniumExtJsUtils类中,这是一组有用的方法,可以更容易地与ExtJs交互):
/**
* Javascript needed to execute in order to select row in the grid
*
* @param gridId Grid id
* @param rowIndex Index of the row to select
* @return Javascript to select row
*/
public static String selectGridRow(String gridId, int rowIndex) {
return "Ext.getCmp('" + gridId + "').getSelectionModel().selectRow(" + rowIndex + ", true)";
}
当我需要选择一行时,我只需要打电话:
selenium.runScript( SeleniumExtJsUtils.selectGridRow("<myGridId>", 5) );
为了实现这个目的,我需要在网格上设置我的id,而不是让ExtJs自己生成它。
答案 3 :(得分:4)
要检测该元素是否可见,请使用以下子句:
not(contains(@style, "display: none")
最好使用它:
visible_clause = "not(ancestor::*[contains(@style,'display: none')" +
" or contains(@style, 'visibility: hidden') " +
" or contains(@class,'x-hide-display')])"
hidden_clause = "parent::*[contains(@style,'display: none')" +
" or contains(@style, 'visibility: hidden')" +
" or contains(@class,'x-hide-display')]"
答案 4 :(得分:3)
您能否更深入地了解使用extjs测试时遇到的问题类型?
我觉得有用的一个Selenium扩展名是waitForCondition。如果您的问题似乎是Ajax事件的问题,您可以使用waitForCondition等待事件发生。
答案 5 :(得分:3)
Ext JS网页可能很难测试,因为它们最终会像Ext JS网格一样生成复杂的HTML。
HTML5 Robot通过使用一系列最佳实践来解决这个问题,这些实践是基于非动态的属性和条件可靠地查找和交互组件。然后,它提供了与您需要与之交互的所有HTML,Ext JS和Sencha Touch组件执行此操作的快捷方式。它有两种口味:
例如,如果您想要查找包含文本&#34; Foo&#34;的Ext JS网格行,您可以在Java中执行以下操作:
findExtJsGridRow("Foo");
...你可以在Gwen中做以下事情:
extjsgridrow by text "Foo"
关于如何使用Ext JS特定组件,Java和Gwen都有很多文档。该文档还详细说明了所有这些Ext JS组件的结果HTML,您也可能会发现它们很有用。
答案 6 :(得分:2)
通过网页上的网格ID获取网格的有用提示: 我认为你可以从这个API扩展更多有用的功能。
sub get_grid_row {
my ($browser, $grid, $row) = @_;
my $script = "var doc = this.browserbot.getCurrentWindow().document;\n" .
"var grid = doc.getElementById('$grid');\n" .
"var table = grid.getElementsByTagName('table');\n" .
"var result = '';\n" .
"var row = 0;\n" .
"for (var i = 0; i < table.length; i++) {\n" .
" if (table[i].className == 'x-grid3-row-table') {\n".
" row++;\n" .
" if (row == $row) {\n" .
" var cols_len = table[i].rows[0].cells.length;\n" .
" for (var j = 0; j < cols_len; j++) {\n" .
" var cell = table[i].rows[0].cells[j];\n" .
" if (result.length == 0) {\n" .
" result = getText(cell);\n" .
" } else { \n" .
" result += '|' + getText(cell);\n" .
" }\n" .
" }\n" .
" }\n" .
" }\n" .
"}\n" .
"result;\n";
my $result = $browser->get_eval($script);
my @res = split('\|', $result);
return @res;
}
答案 7 :(得分:2)
当没有对象引用可用时,itemId可用作获取组件引用的替代方法。不要使用带有Ext.getCmp的id,而是使用带有Ext.container.Container.getComponent的itemId,它将检索itemId或id。由于itemId是容器内部MixedCollection的索引,因此itemId在本地作用于容器 - 避免与需要唯一ID的Ext.ComponentManager发生潜在冲突。
重写Ext.AbstractComponent
的{{1}}方法,我将自定义数据属性(其名称来自每个组件的自定义onBoxReady
属性)设置为组件的testIdAttr
值,如果存在。将itemId
类添加到Testing.overrides.AbstractComponent
文件的application.js
数组中。
requires
此方法为开发人员提供了一种在代码中重用描述性标识符的方法,并在每次呈现页面时使这些标识符可用。不再搜索非描述性的,动态生成的ID。
答案 8 :(得分:2)
我们正在开发一个使用selenium并遇到extjs问题的测试框架(因为它是客户端渲染)。我发现在DOM准备就绪后查找元素很有用。
public static boolean waitUntilDOMIsReady(WebDriver driver) {
def maxSeconds = DEFAULT_WAIT_SECONDS * 10
for (count in 1..maxSeconds) {
Thread.sleep(100)
def ready = isDOMReady(driver);
if (ready) {
break;
}
}
}
public static boolean isDOMReady(WebDriver driver){
return driver.executeScript("return document.readyState");
}
答案 9 :(得分:1)
对于非正式HTML的复杂UI,xPath始终是您可以依赖的东西,但对于使用ExtJ的不同UI实现而言有点复杂。
你可以使用Firebug和Firexpath作为firefox扩展来测试某个元素的xpath,并简单地将完整的xpath作为参数传递给selenium。
例如在java代码中:
String fullXpath = "xpath=//div[@id='mainDiv']//div[contains(@class,'x-grid-row')]//table/tbody/tr[1]/td[1]//button"
selenium.click(fullXpath);
答案 10 :(得分:1)
当我使用WebDriver测试ExtJS应用程序时,我使用了下一种方法:我按标签文本查找字段,并从标签获得@for
属性。例如,我们有一个标签
<label id="dynamic_id_label" class="TextboxLabel" for="textField_which_I_am_lloking_for">
Name Of Needed Label
<label/>
我们需要为WebDriver指点一些输入://input[@id=(//label[contains(text(),'Name Of Needed Label')]/@for)]
。
因此,它将从@for
属性中选择id并进一步使用它。这可能是最简单的情况,但它为您提供了定位元素的方法。当你没有标签时会更难,但是你需要找到一些元素并编写你的xpath来寻找兄弟姐妹,下降/提升元素。