【问题标题】:ExtJS functional testing - get internal elements of ExtJS controlsExtJS 功能测试 - 获取 ExtJS 控件的内部元素
【发布时间】:2012-12-18 10:26:39
【问题描述】:

我们决定将 Sencha ExtJS 用于我们新产品的客户端,并计划在客户端进行自动化功能测试。我们研究了几种工具,如 Ranorex、Selenium、Telerik Test Studio 等,到目前为止,我们比其他工具更喜欢 Test Studio。无论如何,无论人们可能使用哪种工具,我要问的问题都是相关的。

我很想知道获取 extjs 控件的内部元素的推荐方法是什么。为了清楚起见,我举个例子。

我有一个数字字段控件,我想测试一下,如果我单击“向上”按钮,字段中的值将增加一个单位。请注意,我确实为数字字段 (id="testDurationHourNumberField") 设置了唯一 ID。 number 字段具有以下(简化的)DOM 结构:

<table id="testDurationHourNumberField">
<tbody>
    <tr id="testDurationHourNumberField-inputRow">
        <td id="testDurationHourNumberField-labelCell">
            <label id="testDurationHourNumberField-labelEl">Label:</label>
        </td>
        <td id="testDurationHourNumberField-bodyEl">
            <table id="testDurationHourNumberField-triggerWrap">
                <tbody>
                    <tr>
                        <td id="testDurationHourNumberField-inputCell">
                            <input id="testDurationHourNumberField-inputEl">
                        </td>
                        <td>
                            <div role="button" id="ext-gen1211"></div>
                            <div role="button" id="ext-gen1212"></div>
                        </td>
                    </tr>
                </tbody>
            </table>
        </td>
    </tr>
</tbody>
</table>

为此,我必须访问输入元素 (id="testDurationHourNumberField-inputEl") 和按钮 (id="ext-gen1211")。访问这 2 个元素的推荐方式是什么?

到目前为止,我有以下选择:

  • 使用 ExtJS 内部 ID - 似乎不太好,因为:
    • 这些是内部 ID,它们不受我的控制,如果我稍后在页面上添加另一个控件,它们可能会发生变化
    • 似乎对于同一个页面,我在不同的浏览器中获得了不同的 ID。例如,在 IE 10 中,按钮的 ID 与我在 Google Chrome 中获得的 ID 不同。
  • 通过唯一 ID 获取控件并通过了解其内部 DOM 结构或属性来获取内部元素 - 似乎不好,因为:
    • 我宁愿不使用这种方式,因为我不知道当升级到 ExtJS 的下一个版本时,内部 DOM 结构不会改变或某些属性名称会改变,我将不得不更新我创建的测试
    • 例如伪代码:getById('testDurationHourNumberField').getElementByAttributeAndIndex('role=button', 0)

您能告诉我推荐的方法吗?

谢谢,
保罗

【问题讨论】:

  • 你的意思是你在功能测试中没有访问 ExtJS 的权限?你必须有 ExtJS 才能渲染 DOM。
  • 在运行 Web 应用程序时我们总是有 ExtJS,但在运行功能测试时我们无法访问它。我们使用 Test Studio/Selenium 等工具进行功能测试,因为它们提供了一种记录用户操作并将其作为测试运行的自动化方式。这些工具通常在 DOM 上运行,它们解析 DOM,并有一组 API 来对 DOM 元素执行。
  • 他们可以运行javascript吗?
  • 我不知道他们是否可以运行 javascript,也许某些工具具有此功能,但是当我发布此问题时,我假设默认情况下,他们不能。

标签: extjs widget functional-testing uniqueidentifier


【解决方案1】:

这就是我在项目中的做法:

it("should increment the control value", function () {
    var ctrl = Ext.ComponentQuery.query('#age')[0],
        upBtn = Ext.ComponentQuery.query('#upButton')[0],
        curValue = ctrl.getValue();

    upBtn.fireEvent('click');

    expect(ctrl.getValue()).toEqual(curValue + 1);
});

我用茉莉花。

更新:

对于功能测试,您应该阅读以下内容:

  1. Any suggestions for testing extjs code in a browser, preferably with selenium? 还有这个:
  2. http://www.sencha.com/blog/testing-ext-js-ext-gwt-applications-with-selenium

【讨论】:

  • 看来你说的是单元测试,但我问的是功能测试。我们也使用 Jasmine 进行单元测试,但在进行功能测试时,我们只对 DOM 进行操作,并且无法访问 ExtJS 库。
【解决方案2】:

我知道已经有一段时间了,但我会在这里写下我们是如何决定解决这个问题的。 对于功能测试,我们使用 Telerik TestStudio,为了获取内部元素,我们使用 GetById 方法,其中每个组件的每个 ID 都必须是唯一的。这种方法的主要问题在于自动生成的 ID:

  • 内部组件的 ID 会根据浏览器获得不同的值
  • 内部组件的 ID 可能会在 ExtJs 升级时发生变化
  • 在页面上添加其他组件时,内部组件的 ID 可能会发生变化(这种情况经常发生)

为了解决这个问题,我们实现了 ExtJS 类的补丁,以确保内部元素的 ID 是唯一的。

对于我的问题中关于数字字段的示例,我们实施了以下补丁,以确保数字字段的按钮具有在不同浏览器上不会更改的唯一 ID。

Ext.define('Waf.patch.extJS411.form.field.Spinner', {
    override: 'Ext.form.field.Spinner',

    getTriggerMarkup: function() {
        var me = this,
            hideTrigger = (me.readOnly || me.hideTrigger);

        me.triggerTpl = '<td style="{triggerStyle}">' +
            '<div class="' + Ext.baseCSSPrefix + 'trigger-index-0 ' + Ext.baseCSSPrefix + 'form-trigger ' + Ext.baseCSSPrefix + 'form-spinner-up"' + 'id="' + me.id + '-buttonUp"' + ' role="button"></div>' +
            '<div class="' + Ext.baseCSSPrefix + 'trigger-index-1 ' + Ext.baseCSSPrefix + 'form-trigger ' + Ext.baseCSSPrefix + 'form-spinner-down"' + 'id="' + me.id + '-buttonDown"' + ' role="button"></div>' +
            '</td>' +
            '</tr>';

        return me.getTpl('triggerTpl').apply({
            triggerStyle: 'width:' + me.triggerWidth + (hideTrigger ? 'px;display:none' : 'px')
        });
    }
});

我们还为遇到此问题的其他类实施了补丁,因此我们涵盖了大部分用例。补丁不多:

  • Ext.form.field.Spinner
  • Ext.form.field.Trigger
  • Ext.panel.Panel
  • Ext.view.BoundList
  • Ext.window.MessageBox

问候, 保罗

【讨论】:

    【解决方案3】:

    您可能想查看自动化功能 GUI 测试工具 RIATest

    ExtJS UI 小部件是 RIATest 中的一等公民。这意味着,与其他 HTML 测试工具不同,当您实际需要使用 ExtJS 组件时,您不需要编写操作 HTML DOM 元素的测试。

    RIATest 知道如何忽略 ExtJS 动态生成的 id,但是如果您手动将 id 分配给组件,该工具使用它们进行识别(参见例如下面示例中的 #tree2)。

    RIATest 中的测试根据 ExtJS UI 小部件运行。

    使用 ExtJS 小部件的 RIATest 脚本示例:

    以下点击带有“下一页”标签的 ExtJS 按钮:

    ExtButton("Next Page")=>click();
    

    以下内容将一行从一个 ExtJS 树拖放到另一个:

    ExtRow("Controller.js")=>dragAndDropTo(
        ExtTreePanel("#tree2")->ExtRow("Custom Ext JS"));
    

    这会折叠 ExtJS 框的标题:

    ExtBox("Feeds")->ExtHeader("FeedsВ")->ExtCollapser()=>click();
    

    (以上所有示例代码均来自在 ExtJS 示例应用程序上运行的真实测试脚本)。

    RIATest 还知道何时自动等待 ExtJS AJAX 完成,因此如果您的 UI 下载动态内容,测试将自动神奇地等待,直到从服务器接收到数据。

    (免责声明:我是 RIATest 团队成员)。

    【讨论】:

      猜你喜欢
      • 2012-08-21
      • 1970-01-01
      • 1970-01-01
      • 2012-11-02
      • 1970-01-01
      • 2019-11-24
      • 1970-01-01
      • 2015-04-09
      • 1970-01-01
      相关资源
      最近更新 更多