在浏览器中测试 extjs 代码的任何建议,最好使用 selenium? [英] Any suggestions for testing extjs code in a browser, preferably with selenium?
问题描述
我们已经成功地使用 selenium 来处理高级网站测试(除了模块级别的大量 python doctests).然而,现在我们在很多页面上使用 extjs,并且证明很难将 Selenium 测试合并到像网格这样的复杂组件中.
We've been using selenium with great success to handle high-level website testing (in addition to extensive python doctests at a module level). However now we're using extjs for a lot of pages and its proving difficult to incorporate Selenium tests for the complex components like grids.
有没有人成功地为基于 extjs 的网页编写自动化测试?许多谷歌搜索发现有类似问题的人,但答案很少.谢谢!
Has anyone had success writing automated tests for extjs-based web pages? Lots of googling finds people with similar problems, but few answers. Thanks!
推荐答案
用 Selenium 测试 ExtJS 的最大障碍是 ExtJS 不呈现标准 HTML 元素,而 Selenium IDE 会天真地(并且正确地)生成针对元素的命令只是作为装饰——帮助 ExtJS 处理整个桌面外观的多余元素.以下是我在针对 ExtJS 应用编写自动 Selenium 测试时收集的一些提示和技巧.
The biggest hurdle in testing ExtJS with Selenium is that ExtJS doesn't render standard HTML elements and the Selenium IDE will naively (and rightfully) generate commands targeted at elements that just act as decor -- superfluous elements that help ExtJS with the whole desktop-look-and-feel. Here are a few tips and tricks that I've gathered while writing automated Selenium test against an ExtJS app.
通过在 Firefox 上使用 Selenium IDE 记录用户操作来生成 Selenium 测试用例时,Selenium 会将记录的操作基于 HTML 元素的 id.但是,对于大多数可点击元素,ExtJS 使用生成的 id,如ext-gen-345",即使没有更改代码,这些 id 在后续访问同一页面时也可能会发生变化.在为测试记录用户操作后,需要手动完成所有依赖于生成的 id 的操作并替换它们.可以进行两种类型的替换:
When generating Selenium test cases by recording user actions with Selenium IDE on Firefox, Selenium will base the recorded actions on the ids of the HTML elements. However, for most clickable elements, ExtJS uses generated ids like "ext-gen-345" which are likely to change on a subsequent visit to the same page, even if no code changes have been made. After recording user actions for a test, there needs to be a manual effort to go through all such actions that depend on generated ids and to replace them. There are two types of replacements that can be made:
CSS 定位器以css="开头,XPath 定位器以//"开头(xpath="前缀是可选的).CSS 定位器不那么冗长,更易于阅读,应该优先于 XPath 定位器.但是,在某些情况下,可能需要使用 XPath 定位器,因为 CSS 定位器根本无法对其进行剪切.
CSS locators begin with "css=" and XPath locators begin with "//" (the "xpath=" prefix is optional). CSS locators are less verbose and are easier to read and should be preferred over XPath locators. However, there can be cases where XPath locators need to be used because a CSS locator simply can't cut it.
由于 ExtJS 执行的复杂渲染,某些元素需要的不仅仅是简单的鼠标/键盘交互.例如,一个 Ext.form.CombBox 并不是一个真正的 元素,而是一个文本输入,在文档树的底部有一个分离的下拉列表.为了正确模拟 ComboBox 选择,可以先模拟单击下拉箭头,然后单击出现的列表.但是,通过 CSS 或 XPath 定位器定位这些元素可能很麻烦.另一种方法是定位 ComoBox 组件本身并调用其上的方法来模拟选择:
Some elements require more than simple mouse/keyboard interactions due to the complex rendering carried out by ExtJS. For example, a Ext.form.CombBox is not really a <select>
element but a text input with a detached drop-down list that's somewhere at the bottom of the document tree. In order to properly simulate a ComboBox selection, it's possible to first simulate a click on the drop-down arrow and then to click on the list that appears. However, locating these elements through CSS or XPath locators can be cumbersome. An alternative is to locate the ComoBox component itself and call methods on it to simulate the selection:
var combo = Ext.getCmp('genderComboBox'); // returns the ComboBox components
combo.setValue('female'); // set the value
combo.fireEvent('select'); // because setValue() doesn't trigger the event
在 Selenium 中,可以使用 runScript
命令以更简洁的形式执行上述操作:
In Selenium the runScript
command can be used to perform the above operation in a more concise form:
with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }
应对 AJAX 和慢速渲染
当用户操作导致页面转换或重新加载时,Selenium 对所有等待页面加载的命令都有*AndWait"风格.但是,由于 AJAX 提取不涉及实际页面加载,因此这些命令不能用于同步.解决方案是利用视觉线索,例如 AJAX 进度指示器的存在/不存在或网格中行的外观、附加组件、链接等.例如:
Coping with AJAX and Slow Rendering
Selenium has "*AndWait" flavors for all commands for waiting for page loads when a user action results in page transitions or reloads. However, since AJAX fetches don't involve actual page loads, these commands can't be used for synchronization. The solution is to make use of visual clues like the presence/absence of an AJAX progress indicator or the appearance of rows in a grid, additional components, links etc. For example:
Command: waitForElementNotPresent
Target: css=div:contains('Loading...')
有时元素会在一段时间后才会出现,这取决于用户操作导致视图更改后 ExtJS 呈现组件的速度.理想的方法是等待感兴趣的元素进入我们的掌握范围,而不是在 pause
命令中使用任意延迟.例如,在等待项目出现后点击它:
Sometimes an element will appear only after a certain amount of time, depending on how fast ExtJS renders components after a user action results in a view change. Instead of using arbitary delays with the pause
command, the ideal method is to wait until the element of interest comes within our grasp. For example, to click on an item after waiting for it to appear:
Command: waitForElementPresent
Target: css=span:contains('Do the funky thing')
Command: click
Target: css=span:contains('Do the funky thing')
依赖任意暂停不是一个好主意,因为在不同浏览器或不同机器上运行测试导致的时间差异会使测试用例不稳定.
Relying on arbitrary pauses is not a good idea since timing differences that result from running the tests in different browsers or on different machines will make the test cases flaky.
click
命令无法触发某些元素.这是因为事件侦听器实际上在容器上,监视其子元素上的鼠标事件,最终冒泡到父元素.选项卡控件就是一个例子.要单击选项卡,您必须在选项卡标签处模拟 mouseDown
事件:
Some elements can't be triggered by the click
command. It's because the event listener is actually on the container, watching for mouse events on its child elements, that eventually bubble up to the parent. The tab control is one example. To click on the a tab, you have to simulate a mouseDown
event at the tab label:
Command: mouseDownAt
Target: css=.x-tab-strip-text:contains('Options')
Value: 0,0
现场验证
具有关联正则表达式或 vtypes 进行验证的表单字段(Ext.form.* 组件)将在一定延迟后触发验证(请参阅默认设置为 250 毫秒的 validationDelay
属性),在用户输入文本后或字段失去焦点时立即 - 或模糊(请参阅 validateOnDelay
属性).为了在发出 type Selenium 命令以在字段内输入一些文本后触发字段验证,您必须执行以下任一操作:
Field Validation
Form fields (Ext.form.* components) that have associated regular expressions or vtypes for validation will trigger validation with a certain delay (see the validationDelay
property which is set to 250ms by default), after the user enters text or immediately when the field loses focus -- or blurs (see the validateOnDelay
property). In order to trigger field validation after issuing the type Selenium command to enter some text inside a field, you have to do either of the following:
触发延迟验证
ExtJS 在字段接收到 keyup 事件时触发验证延迟计时器.要触发此计时器,只需发出一个虚拟的 keyup 事件(您使用哪个键都没有关系,因为 ExtJS 会忽略它),然后是比validationDelay 更长的短暂暂停:
ExtJS fires off the validation delay timer when the field receives keyup events. To trigger this timer, simply issue a dummy keyup event (it doesn't matter which key you use as ExtJS ignores it), followed by a short pause that is longer than the validationDelay:
Command: keyUp
Target: someTextArea
Value: x
Command: pause
Target: 500
触发立即验证
您可以在字段中注入一个模糊事件以触发立即验证:
You can inject a blur event into the field to trigger immediate validation:
Command: runScript
Target: someComponent.nameTextField.fireEvent("blur")
在验证之后,您可以检查是否存在错误字段:
Following validation, you can check for the presence or absence of an error field:
Command: verifyElementNotPresent
Target: //*[@id="nameTextField"]/../*[@class="x-form-invalid-msg" and not(contains(@style, "display: none"))]
Command: verifyElementPresent
Target: //*[@id="nameTextField"]/../*[@class="x-form-invalid-msg" and not(contains(@style, "display: none"))]
请注意,display: none"检查是必要的,因为一旦显示错误字段然后需要隐藏它,ExtJS 将简单地隐藏错误字段,而不是将其从 DOM 树中完全删除.
Note that the "display: none" check is necessary because once an error field is shown and then it needs to be hidden, ExtJS will simply hide error field instead of entirely removing it from the DOM tree.
选项 1
命令:单击目标:css=button:contains('Save')
Command: click Target: css=button:contains('Save')
通过标题选择按钮
选项 2
命令:单击目标:css=#save-options 按钮
Command: click Target: css=#save-options button
通过 id 选择按钮
Command: runScript
Target: with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }
首先设置值,然后在有观察者的情况下显式触发 select 事件.
First sets the value and then explicitly fires the select event in case there are observers.
这篇关于在浏览器中测试 extjs 代码的任何建议,最好使用 selenium?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!