编辑:我创建了一个repo,我的问题的简化版本重现了这个问题.
我正在尝试使用browserstack,selenium-webdriver和tape设置自动前端测试.
我们的想法是定义多个浏览器和设备,这些浏览器和设备必须使用X量的给定测试一个接一个地进行测试.在下面的示例中,我在OSX上只定义了一个测试和两个浏览器.
为了只定义浏览器一次并处理测试,我创建了一个repo test-runner,它应该作为dev-dependency添加到需要在给定设备和浏览器上测试的repos.
测试运行器获得所有需要的测试通过,启动第一个浏览器,在该浏览器上运行测试,一旦完成所有测试,浏览器关闭quit(),下一个浏览器启动并再次测试.
测试亚军
/index.js
const webdriver = require( 'selenium-webdriver' ) // --- // default browser configs // --- const defaults = { "os" : "OS X","os_version" : "Mojave","resolution" : "1024x768","browserstack.user" : "username","browserstack.key" : "key","browserstack.console": "errors","browserstack.local" : "true","project" : "element" } // --- // browsers to test // --- const browsers = [ { "browserName" : "Chrome","browser_version" : "41.0" },{ "browserName" : "Safari","browser_version" : "10.0","os_version" : "Sierra" } ] module.exports = ( tests,url ) => { // --- // Asynchronous forEach loop // helper function // --- async function asyncForEach(array,callback) { for (let index = 0; index < array.length; index++) { await callback(array[index],index,array) } } // --- // runner // --- const run = async () => { // --- // Iterate through all browsers and run the tests on them // --- await asyncForEach( browsers,async ( b ) => { // --- // Merge default configs with current browser // --- const capabilities = Object.assign( {},defaults,b ) // --- // Start and connect to remote browser // --- console.info( '-- Starting remote browser hang on --',capabilities.browserName ) const browser = await new webdriver.Builder(). usingServer( 'http://hub-cloud.browserstack.com/wd/hub' ). withCapabilities( capabilities ). build() // --- // Navigate to page which needs to be checked (url) // --- console.log('-- Navigate to URL --') await browser.get( url ) // --- // Run the tests asynchronously // --- console.log( '-- Run tests --- ' ) await asyncForEach( tests,async ( test ) => { await test( browser,url,capabilities,webdriver ) } ) // --- // Quit the remote browser when all tests for this browser are done // and move on to next browser // Important: if the browser is quit before the tests are done // the test will throw an error beacause there is no connection // anymore to the browser session // --- browser.quit() } ) } // --- // Start the tests // --- run() }
如果您想知道这个asyncForEach函数是如何工作的,我从here开始.
我的回购
/test/front/index.js
const testRunner = require( 'test-runner' ) const url = ( process.env.NODE_ENV == 'development' ) ? 'http://localhost:8888/element/...' : 'https://staging-url/element/...' // tests to run const tests = [ require('./test.js') ] testRunner( tests,url )
/test/front/test.js
const tape = require( 'tape' ) module.exports = async ( browser,driver ) => { return new Promise( resolve => { tape( `Frontend test ${capabilities.browserName} ${capabilities.browser_version}`,async ( t ) => { const myButton = await browser.wait( driver.until.elementLocated( driver.By.css( 'my-button:first-of-type' ) ) ) myButton.click() const marked = await myButton.getAttribute( 'marked' ) t.ok(marked == "true",'Button marked') //--- // Test should end now //--- t.end() resolve() } ) }) }
/package.json
{ ... "scripts": { "test": "NODE_ENV=development node test/front/ | tap-spec","travis": "NODE_ENV=travis node test/front/ | tap-spec" } ... }
当我想运行测试时,我在my-repo中执行npm run test
请记住,我们只有一个测试(但也可能是多个测试),并且定义了两个浏览器,因此行为应该是:
>启动浏览器1并导航(Chrome)
>浏览器1(Chrome)上的一项测试
>关闭浏览器1(Chrome)
>启动浏览器2并导航(Safari)
>浏览器2上的一项测试(Safari)
>关闭浏览器2(Safari)
>完成
问题
异步的东西似乎工作得很好,浏览器按照预期一个接一个地启动.问题是,即使我调用t.end()并且没有进行第二次测试(第4次测试失败),第一次测试也没有完成.
我尝试了什么
我尝试使用t.pass()并使用NODE_ENV =开发磁带测试/ front / |运行CLI tap-spec但它没有帮助.
我也注意到,当我在test.js中没有解析()时,测试结束就好了,但当然我没有进入下一个测试.
我也尝试调整我的代码,如this issue的解决方案,但没有设法让它工作.
与此同时,我还在磁带github页面上打开了一个issue.
因此,我希望这个问题不是一个痛苦的阅读,任何帮助将不胜感激.
解决方法
https://github.com/substack/tape/issues/223
https://github.com/substack/tape/issues/160
解决方案似乎是在调用任何异步代码之前,在开头使用tape.add声明测试.
如果您只是按顺序打开浏览器,我还会尝试重构一些可能不需要的异步代码.