2015-10-20 61 views
0

我正在嘗試使用Intern框架編寫功能測試,該框架使用Leadfoot庫實現WebDriver API,因爲我使用Selenium Grid設置在遠程瀏覽器上測試我的webapp。該應用程序已經啓動並正在運行。 功能測試我用的是以下各項之一:爲什麼點擊處理程序不能在Leadfoot中運行?

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的元素。由於超時,我最終得到的是。

由於我在本地執行此操作,我實際上可以觀察並確認點擊事件沒有發生。所以我的web應用程序的預期更改不會發生。

從實習生日誌如下:

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 

硒節點的日誌不顯示的問題,至少在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運行相同的功能測試,並且它運行成功。

回答

0

因爲click()事件是在處理程序被連接之前被瀏覽器觸發的。 問題是get()呼叫和呼叫click()之間:

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

發生了什麼事是,瀏覽器發射click事件附着處理程序之前。處理程序在被測試的應用程序中實現。這意味着在點擊事件發生時沒有處理程序,因此server-name-span-text元素未被創建,因此操作的超時。請注意,我也試過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

1

夫婦技巧來解決這個問題:

使用確保您可以用findByClassName

找到元素,如果它不能找到那麼元素確保.findById('linkservers')工作正常之前。要檢查您可以嘗試前後添加.sleep()以查看它是否可以正常工作,併爲您提供'server-name-span-text'類的元素。

+0

感謝您的提示。我將在另一個答案中描述問題。 – KiaMorot

+0

我跑了一些測試來捕獲,<附加處理程序>,<網站加載結束>的時間戳。我做了15次連續運行,三項的時間戳也是連續的,它們之間的差別大約爲100-200毫秒。這告訴我可能稍後會在JQuery中附加處理程序。我也檢查了on()調用的api,但沒有得出任何結論。讓我知道如果在我的回答中推薦的方式等待get()調用是正確的。 – KiaMorot

相關問題