Jasmine - 通过 Webdriver 测试链接 I/O

Jasmine - Testing links via Webdriver I/O

我一直在使用来自 Jasmine 的 Webdriver I/O 进行 end-to-end 测试。一个特定的场景给了我很大的挑战。

我有一个页面有 5 links。 link 的数量实际上是一个挑战,因为页面是动态的。我想测试 links 以查看每个 links' title 是否与它 links 到的页面的 title 相匹配。由于 link 是动态生成的,我不能只对每个 link 进行硬编码测试。所以,我正在尝试以下操作:

it('should match link titles to page titles', function(done) {
  client = webdriverio.remote(settings.capabilities).init()
    .url('http://www.example.com')
    .elements('a').then(function(links) {
      var mappings = [];

      // For every link store the link title and corresponding page title
      var results = [];
      for (var i=0; i<links.value.length; i++) {
        mappings.push({ linkTitle: links.value[0].title, pageTitle: '' });
        results.push(client.click(links.value[i])
          .getTitle().then(function(title, i) {
            mappings[i].pageTitle = title;
          });
        );
      }

      // Once all promises have resolved, compared each link title to each corresponding page title
      Promise.all(results).then(function() {
        for (var i=0; i<mappings.length; i++) {
          var mapping = mappings[i];
          expect(mapping.linkTitle).toBe(mapping.pageTitle);
        }
        done();          
      });                  
    });
  ;
});

我什至无法确认我是否正确获得了 link 称号。我相信有些事情我完全误解了。我什至没有得到每个 links title 属性。我肯定没有得到相应的页面标题。我想我在这里迷失了封闭世界。但是,我不确定。

更新 - 11 月 24 日 我还是没弄明白。但是,我认为这与 Webdriver I/O uses Q promise 库这一事实有关。我得出这个结论是因为以下测试有效:

it('should match link titles to page titles', function(done) {
  var promise = new Promise(function(resolve, reject) {
    setTimeout(function() { resolve(); }, 1000);
  });

  promise.then(function() {
    var promises = [];
    for (var i=0; i<3; i++) {
      promises.push(
        new Promise(function(resolve, reject) {
          setTimeout(function() {
            resolve();
          }, 500);
        })
      );
    }

    Promise.all(promises).then(function() {
      expect(true).toBe(true)
      done();
    });
}); 

但是,以下 无效 工作:

it('should match link titles to page titles', function(done) {
  client = webdriverio.remote(settings.capabilities).init()
    .url('http://www.example.com')
    .elements('a').then(function(links) {
      var mappings = [];

      // For every link store the link title and corresponding page title
      var results = [];
      for (var i=0; i<links.value.length; i++) {
        mappings.push({ linkTitle: links.value[0].title, pageTitle: '' });
        results.push(client.click(links.value[i])
          .getTitle().then(function(title, i) {
            mappings[i].pageTitle = title;
          });
        );
      }

      // Once all promises have resolved, compared each link title to each corresponding page title
      Q.all(results).then(function() {
        for (var i=0; i<mappings.length; i++) {
          var mapping = mappings[i];
          expect(mapping.linkTitle).toBe(mapping.pageTitle);
        }
        done();          
      });                  
    })
  ;
});

我没有收到任何例外情况。然而,Q.all 中的代码似乎并没有被执行。我不确定在这里做什么。

阅读 WebdriverIO 手册,我觉得您的方法有一些错误:

  • elements('a') returns WebElement JSON 个对象(https://code.google.com/p/selenium/wiki/JsonWireProtocol#WebElement_JSON_Object) NOT WebElements, so there is no title property thus linkTitle will always be undefined - http://webdriver.io/api/protocol/elements.html
  • 此外,因为它是一个 WebElement JSON 对象,所以您不能将其用作 client.click(..) 输入,它需要一个选择器字符串而不是一个对象 - http://webdriver.io/api/action/click.html。单击 WebElement JSON 对象 client.elementIdClick(ID) 而不是采用 WebElement JSON 对象的 ELEMENT 属性 值。
  • 当执行 client.elementIdClick 时,client 将导航到页面,尝试在下一个 ID 的 for 循环周期中调用 client.elementIdClick 将失败,因为有没有这样的元素,因为你离开了页面。听起来像 invalid element cache.....

因此,我为您的任务提出另一个解决方案:

  • 像使用 elements('a')
  • 一样查找所有元素
  • 对每个元素使用 client.elementIdAttribute(ID) 读取 hreftitle 并存储在对象中
  • 遍历所有对象,使用 client.url('href') 导航到每个 href-s,使用 .getTitle 获取页面的 title 并进行比较object.title.

我试验的来源,不是 Jasmine 的 运行,但应该给出一个想法:

    var client = webdriverio
        .remote(options)
        .init();

    client
        .url('https://www.google.com')
        .elements('a')
        .then(function (elements) {
            var promises = [];

            for (var i = 0; i < elements.value.length; i++) {
                var elementId = elements.value[i].ELEMENT;

                promises.push(
                    client
                        .elementIdAttribute(elementId, 'href')
                        .then(function (attributeRes) {
                            return client
                                .elementIdAttribute(elementId, 'title')
                                .then(function (titleRes) {
                                    return {href: attributeRes.value, title: titleRes.value};
                                });
                        })
                );
            }

            return Q
                .all(promises)
                .then(function (results) {
                    console.log(arguments);
                    var promises = [];
                    results.forEach(function (result) {
                        promises.push(
                            client
                                .url(result.href)
                                .getTitle()
                                .then(function (title) {
                                    console.log('Title of ', result.href, 'is', title, 'but expected', result.title);
                                })
                        );
                    });

                    return Q.all(promises);
                });
        })
        .then(function () {
            client.end();
        });

注意:

  • 当链接使用 JavaScript 事件处理程序而不是 href 属性触发导航时,这无法解决您的问题。