有关在浏览器中测试extjs代码的建议,最好是使用selenium吗?

时间:2008-09-20 05:53:50

标签: unit-testing extjs selenium web-testing

我们一直在使用selenium非常成功地处理高级网站测试(除了模块级别的广泛python doctests)。然而,现在我们在很多页面上使用extjs,并证明很难将Selenium测试用于像网格这样的复杂组件。

有没有人成功为基于extjs的网页编写自动化测试?很多谷歌搜索发现有类似问题的人,但答案很少。谢谢!

11 个答案:

答案 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组件执行此操作的快捷方式。它有两种口味:

  1. Java - 熟悉基于Selenium和JUnit的API,内置了对所有现代浏览器的Web驱动程序支持。
  2. Gwen - 一种人性化的语言,可快速轻松地创建和维护浏览器测试,并附带自己的集成开发环境。所有这些都基于Java API。
  3. 例如,如果您想要查找包含文本&#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)

通过自定义HTML数据属性轻松测试

来自Sencha documentation

  

当没有对象引用可用时,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来寻找兄弟姐妹,下降/提升元素。