Protractor的waitForAngular()在真实设备上的angular-web应用(appium/chrome)上失败了。

6

我(新手)正在使用protractor运行e2e cucumber测试。我有一个基于angularJS的Web应用程序。我正在使用appium在真实的Android设备上远程运行测试。这是我使用的版本:

windows8.1
protractor@1.3.1 (with submodule selenium-webdriver@2.43.5)
appium@1.3.0beta1
android device with 4.4.4

我的 Protractor 配置(摘录),对应于 https://github.com/angular/protractor/blob/master/docs/browser-setup.md

currentDeviceUDID = (...);
var appToTestURL = 'http://my.website.com:9000/app/index.html';

exports.config = {
  seleniumAddress: 'http://localhost:4723/wd/hub';
  chromeOnly: false,
  specs: ['features/sample.feature'],

  capabilities: {
    browserName: 'chrome',
    'appium-version': '1.0',
    platformName: 'Android',
    platformVersion: '4.4.4',
    udid: currentDeviceUDID
  },

  baseUrl: appToTestURL

  framework: 'cucumber',
  cucumberOpts: {
    require: 'features/stepDefinitionsSample.js',
    tags: '@dev',
    format: 'progress'
  },

  // configuring wd in onPrepare
 onPrepare: function () {
    var wd = require('wd'),
    protractor = require('protractor'),
    wdBridge = require('wd-bridge')(protractor, wd);
    wdBridge.initFromProtractor(exports.config);
  },

  allScriptsTimeout: 30000,
  getPageTimeout: 30000
};

如您所见,我已将量角器的webdriver url替换为appium webdriver。我在命令行中使用“appium&”启动appium,然后使用“protactor cucumbertest.conf”运行测试。

手机打开Chrome浏览器,并使用“browser.get(url)”导航到我提供的URL。

问题如下:waitForAngular()调用异步等待网站加载和所有打开的http请求(据我所知),但手机未能成功执行该调用。 手机未对呼叫做出反应,webdriver代理返回500错误。

根据https://github.com/angular/protractor/issues/1358,我了解到waitForAngular()函数被混入protractor的调用中。

['getCurrentUrl', 'getPageSource', 'getTitle'];

在protractor.js文件中waitForAngular()函数的背后是下面的函数,该函数被代理到手机端:
functions.waitForAngular = function(selector, callback) {
  var el = document.querySelector(selector);
  try {
    if (angular.getTestability) {
      angular.getTestability(el).whenStable(callback);
    } else {
      angular.element(el).injector().get('$browser').
      notifyWhenNoOutstandingRequests(callback);
    }
  } catch (e) {
    callback(e);
  }
};

额外信息:当我在webdriver(浏览器)对象上模拟错误时,错误消息指向protractor目录中的chromedriver.exe。我不明白为什么错误不是来自appium的chromedriver。


简而言之,如果没有成功调用waitForAngular方法,我无法在手机上访问页面上的元素,因此无法进行测试。也许我在某些基本配置细节上有误解,欢迎提供任何提示。

编辑:在这里添加了Appium服务器日志:http://pastebin.com/vqBGUdXH


1
你的能力都是正确的,appium服务器也在正常工作。500返回码是在所有命令处理完毕后出现的。建议您到discuss.appium.io发帖询问,那里会得到最好的回复。 - Jess
1个回答

4
我认为我已经找到了问题所在。Appium和Protractor工作正常。
我的AngularJS应用程序导致了这个问题。它使用$timeout进行轮询(我被迫使用没有$interval的angular 1.07)。这会导致Protractor期望页面仍处于加载阶段而没有完成。因此,函数调用waitForAngular()永远不会返回,测试在指定的超时时间后超时。
这种行为是预期的和已知的,也有文档记录(最好先阅读文档;))http://angular.github.io/protractor/#/timeouts
文档建议对于持续轮询,应该将$timeout替换为$interval:
如果您的应用程序持续轮询$timeout或$http,它将永远不会被注册为完全加载。您应该使用$interval服务(interval.js)来处理任何持续轮询的内容(引入于Angular 1.2rc3)。
目前,我通过另一种方式解决了这个问题:禁用内置的Angular同步并手动同步。
this.Before(function(next){
    ptor = protractor.getInstance();
    ptor.ignoreSynchronization = true; //disables waitForangular()
    next();
});
  1. Sync method 1:

    //at a testcase, wait for an element to be visible with a promise/then
    browser.wait(function () {
        element.all(by.css('.myCssClass')).then(function (items) {
            items[0].getText().then(function (text) {
                console.log(text);
            });
        });
        return true;
    }
    
  2. Sync method 2 :

    // "eventually" (chai-as-promised) internally uses "promise" (and therefore acts like "then")
    browser.get(url);
    expect(browser.getTitle()).to.eventually.equal("connect me").and.notify(next);
    

1
我必须在这里补充一点,只要你在$timeout上正确运行.cancel函数,就可以使用$timeout。用$interval替换$timeout并不那么明显,因为它们没有完全相同的行为。查看我的帖子http://stackoverflow.com/questions/40832962/angular-1-5-timeout-using-a-httpinterceptor以及有关如何取消$timeout的评论,然后您仍然可以继续使用waitForAngular。 - Ben Croughs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接