【问题标题】:Why does a click handler NOT run in Leadfoot?为什么点击处理程序不在 Leadfoot 中运行?
【发布时间】:2015-10-20 14:05:31
【问题描述】:

我正在尝试使用Intern 框架编写功能测试,该框架使用Leadfoot 库来实现WebDriver API,因为我正在使用Selenium Grid setup 在远程浏览器上测试我的webapp。该应用程序已经启动并运行。 我使用的功能测试如下:

define(function (require) {
var tdd = require('intern!tdd');
var assert = require('intern/chai!assert');
var url = '...';
var server = '...';

tdd.suite("Init suite",function(){
    tdd.before(function () {
      // executes before suite starts
    });

    tdd.after(function () {
      // executes after suite ends
    });

    tdd.beforeEach(function () {
      // executes before each test
    });

    tdd.afterEach(function () {
      // executes after each test
    });
    tdd.test('Checking servers', function () {
        var that = this.remote;
        return that
            .setFindTimeout(15000)
            .get(url)
            .findById('linkservers')
                .click()
                .then(function(){
                    console.log("Click resolved");
                })
            .end()
            .findDisplayedByClassName('server-name-span-text')
                .getVisibleText()
                .then(function(texts){
                    var t=0;
                    var tlen = 0;
                    if (Array.isArray(texts))
                    {
                        tlen = texts.length
                        for (t=0;t<tlen;t++)
                            console.log("server["+t+"]: "+texts[t]);
                        assert.strictEqual(texts[0],server,"server is: "+texts[0]);
                    } else {
                        assert.strictEqual(texts,server,"server is: "+texts[0]);
                    }
                })
            .end();
    });
});

});

要开始我的测试,我使用实习生跑步者:./node_modules/.bin/intern-runner config=tests/intern.cfg -reporters=Runner

我的问题的本质是findDisplayedByClassName('server-name-span-text') 找不到类名,即使我正在使用等待元素显示的findDisplayed 调用。该元素未显示,因为由于某种原因click() 调用未正确触发事件(猜测)。我的意思是 webapp 代码中的点击处理程序没有执行,因此没有创建类名为 server-name-span-text 的元素。我最终得到的是由于超时而失败的findDisplayedByClassName

当我在本地运行它时,我实际上可以观察并确认点击事件没有发生。所以我的 webapp 中的预期变化不会发生。

实习生的日志如下:

Listening on 0.0.0.0:9000
Tunnel started
‣ Created session firefox on LINUX (2d94ea44-dea8-411a-8ee5-a3d7b749cc7b)
Click resolved
× firefox on LINUX - Init suite - Checking servers (15.588s)
NoSuchElement: An element could not be located on the page using the given search parameters.
  at <node_modules/intern/node_modules/leadfoot/lib/findDisplayed.js:37:21>
  at <node_modules/intern/node_modules/dojo/Promise.ts:393:15>
  at run  <node_modules/intern/node_modules/dojo/Promise.ts:237:7>
  at <node_modules/intern/node_modules/dojo/nextTick.ts:44:3>
  at doNTCallback0  <node.js:417:9>
  at process._tickCallback  <node.js:346:13>
  at Command.findDisplayed  <node_modules/intern/node_modules/leadfoot/Command.js:23:10>
  at Command.prototype.(anonymous function) [as findDisplayedByClassName]  <node_modules/intern/node_modules/leadfoot/lib/strategies.js:28:16>
  at Test.test  <tests/functional/loadgui.js:36:6>
  at <node_modules/intern/lib/Test.js:211:24>
  at <node_modules/intern/node_modules/dojo/Promise.ts:393:15>
  at runCallbacks  <node_modules/intern/node_modules/dojo/Promise.ts:11:11>
  at <node_modules/intern/node_modules/dojo/Promise.ts:317:4>
  at run  <node_modules/intern/node_modules/dojo/Promise.ts:237:7>
  at <node_modules/intern/node_modules/dojo/nextTick.ts:44:3>
  at doNTCallback0  <node.js:417:9>
No unit test coverage for firefox on LINUX
firefox on LINUX: 1/1 tests failed


TOTAL: tested 1 platforms, 1/1 tests failed

selenium 节点的日志没有显示问题,至少在 INFO 级别:

15:33:59.735 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Executing: [find element: By.id: linkservers])
15:33:59.742 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Done: [find element: By.id: linkservers]
15:33:59.750 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Executing: [click: 9 [[FirefoxDriver: firefox on LINUX (84846fb0-1467-45a9-bbfe-a6333ddef515)] -> id: linkservers]])
15:33:59.811 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Done: [click: 9 [[FirefoxDriver: firefox on LINUX (84846fb0-1467-45a9-bbfe-a6333ddef515)] -> id: linkservers]]
15:33:59.824 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Executing: [find elements: By.className: server-name-span-text])
15:34:14.844 INFO [13] org.openqa.selenium.remote.server.DriverServlet - Done: [find elements: By.className: server-name-span-text]
15:34:14.957 INFO [192] org.openqa.selenium.remote.server.DriverServlet - Executing: [execute script: return (function getCoverageData(coverageVariable) {
                var coverageData = (function () { return this; })()[coverageVariable];
                return coverageData && JSON.stringify(coverageData);
        }).apply(this, arguments);, [__internCoverage]])
15:34:14.970 INFO [192] org.openqa.selenium.remote.server.DriverServlet - Done: [execute script: return (function getCoverageData(coverageVariable) {
                var coverageData = (function () { return this; })()[coverageVariable];
                return coverageData && JSON.stringify(coverageData);
        }).apply(this, arguments);, [__internCoverage]]
15:34:14.980 INFO [192] org.openqa.selenium.remote.server.DriverServlet - Executing: [delete session: 2d94ea44-dea8-411a-8ee5-a3d7b749cc7b])
15:34:15.047 INFO [192] org.openqa.selenium.remote.server.DriverServlet - Done: [delete session: 2d94ea44-dea8-411a-8ee5-a3d7b749cc7b]

我该如何解决这个问题?

注意: 实习生版本是“3.0.6”,前导版本是“1.6.4”。 我尝试使用 Selenium IDE 运行相同的功能测试,它运行成功。

【问题讨论】:

    标签: intern leadfoot


    【解决方案1】:

    解决此问题的几个技巧:

    在使用findDisplayedByClassName 之前,请确保您可以找到带有findByClassName 的元素

    如果找不到该元素,请确保 .findById('linkservers') 正常工作。要检查您可以尝试在之前和之后添加.sleep(),看看它是否真的有效,并为您提供'server-name-span-text' 类的元素。

    【讨论】:

    • 感谢您的提示。我将在另一个答案中描述这个问题。
    • 我运行了一些测试来捕获 的时间戳。我进行了 15 次连续运行,三个项目的时间戳也是连续的,它们之间的差异约为 100-200 毫秒。这告诉我,处理程序可能稍后附加在 JQuery 中。我还检查了on() 调用的api,但无法得出任何结论。让我知道在我的回答中等待get() 呼叫的推荐方式是否正确。
    【解决方案2】:

    因为click() 事件在附加处理程序之前由浏览器触发。 问题出在get() 调用和click() 调用之间:

    ...
    .get(url)
        .findById('linkservers')
            .click()
    ...
    

    发生的情况是浏览器在附加处理程序之前触发了单击事件。处理程序在被测应用程序中实现。这意味着在触发 click 事件时没有处理程序,因此未创建 server-name-span-text 元素,因此 findDisplayedByClassName 操作超时。请注意,我还尝试了findByClassName 操作,因此我得到了异常NoSuchElement。快速的解决方法是在get() 调用之后添加sleep(),虽然非常讨厌。


    解决方案 1:

    define(function (require) {
    var tdd = require('intern!tdd');
    var assert = require('intern/chai!assert');
    var url = '...';
    var server = '...';
    
    tdd.suite("Init suite",function(){
    tdd.before(function () {
      // executes before suite starts
    });
    
    tdd.after(function () {
      // executes after suite ends
    });
    
    tdd.beforeEach(function () {
      // executes before each test
    });
    
    tdd.afterEach(function () {
      // executes after each test
    });
    tdd.test('Checking servers', function () {
        var that = this.remote;
        return that
            .setFindTimeout(15000)
            .get(url)
            .sleep(1000) //#Fix-1
            .findById('linkservers')
                .click()
                .then(function(){
                    console.log("Click resolved");
                })
            .end()
            .findDisplayedByClassName('server-name-span-text')
                .getVisibleText()
                .then(function(texts){
                    var t=0;
                    var tlen = 0;
                    if (Array.isArray(texts))
                    {
                        tlen = texts.length
                        for (t=0;t<tlen;t++)
                            console.log("server["+t+"]: "+texts[t]);
                        assert.strictEqual(texts[0],server,"server is: "+texts[0]);
                    } else {
                        assert.strictEqual(texts,server,"server is: "+texts[0]);
                    }
                })
            .end();
    });
    });
    

    更新: 如前所述,显式等待对于这类问题来说是一个讨厌的解决方案。下一个解决方案基于在应用程序端执行异步脚本,executeAsync() 调用。此脚本返回一个必须由应用程序解决的承诺,以结束异步调用的等待。当然,应用程序必须与这个实现的延迟对象合作,以便确定应用程序在哪个点加载。否则这样的方法是行不通的。优雅的方式呈现如下。


    解决方案 2:

    define(function (require) {
    var tdd = require('intern!tdd');
    var assert = require('intern/chai!assert');
    var url = '...';
    var server = '...';
    
    tdd.suite("Init suite",function(){
    tdd.before(function () {
      // executes before suite starts
    });
    
    tdd.after(function () {
      // executes after suite ends
    });
    
    tdd.beforeEach(function () {
      // executes before each test
    });
    
    tdd.afterEach(function () {
      // executes after each test
    });
    tdd.test('Checking servers', function () {
        var that = this.remote;
        return that
            .setFindTimeout(15000)
            .get(url)
            .executeAsync(function(done){
                //application side.
                application.loaded
                     .then(function(){
                          //at this moment the application has loaded
                          //so we resolve our intern side promise
                          done();
                      })
             })
            .findById('linkservers')
                .click()
                .then(function(){
                    console.log("Click resolved");
                })
            .end()
            .findDisplayedByClassName('server-name-span-text')
                .getVisibleText()
                .then(function(texts){
                    var t=0;
                    var tlen = 0;
                    if (Array.isArray(texts))
                    {
                        tlen = texts.length
                        for (t=0;t<tlen;t++)
                            console.log("server["+t+"]: "+texts[t]);
                        assert.strictEqual(texts[0],server,"server is: "+texts[0]);
                    } else {
                        assert.strictEqual(texts,server,"server is: "+texts[0]);
                    }
                })
            .end();
    });
    });
    

    如果您希望也可以将一些参数返回给您在应用程序端解析的回调。有关此内容的更多信息以及更多信息,您可以查看docs

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-10
      • 1970-01-01
      • 1970-01-01
      • 2021-08-16
      • 1970-01-01
      • 2014-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多