【问题标题】:Interacting with element throw Stale Element Reference与元素 throw Stale Element Reference 交互
【发布时间】:2015-06-05 16:41:35
【问题描述】:

我有这个网站:http://embed.plnkr.co/Bs5iDqtXSSnvye2ORI6k/preview

代码:

var app = angular.module('plunker', []);

var a = new Array(1000);

for (var i = 0; i< 1000; i++) {
  a[i] = 'Name' + i;
}

app.controller('MainCtrl', function($scope, $interval) {
  $scope.names = a;

  $scope.start = function () {
    $interval(function () {
      $scope.names.pop();
    }, 50);
  }
});

还有以下规格:

'use strict';

describe('Name list', function () {
    it('should get the text of the last name', function () {
        browser.driver.get('http://embed.plnkr.co/Bs5iDqtXSSnvye2ORI6k/preview');
        browser.switchTo().frame(browser.driver.findElement(protractor.By.tagName('iframe')));
        element(by.buttonText('start')).click();
        expect(element.all(by.tagName('span)).last().getText()).toBe('Name999');
    });
});

还有这个配置:

'use strict';

// An example configuration file.
exports.config = {
    baseUrl: 'http://localhost:3000',
    seleniumAddress: 'http://localhost:4444/wd/hub',
    specs: ['stale.spec.js']
};

当我运行 Protractor 时,出现以下错误:

StaleElementReferenceError:过时的元素引用:元素不是 附加到页面文档(会话信息:chrome=43.0.2357.81)
(驱动信息:chromedriver=2.15.322455 (ae8db840dac8d0c453355d3d922c91adfb61df8f),平台=Mac OS X 10.10.3 x86_64) (警告:服务器未提供任何堆栈跟踪 信息)命令持续时间或超时:9毫秒对于 有关此错误的文档,请访问: http://seleniumhq.org/exceptions/stale_element_reference.html 构建 信息:版本:'2.45.0',修订:'5017cb8',时间:'2015-02-26 23:59:50' 系统信息:主机:'ITs-MacBook-Pro.local',ip: '129.192.20.150',os.name:'Mac OS X',os.arch:'x86_64',os.version: '10.10.3',java.version:'1.8.0_31' 驱动程序信息: org.openqa.selenium.chrome.ChromeDriver 功能 [{applicationCacheEnabled=false, 可旋转=false, mobileEmulationEnabled=false, 铬={userDataDir=/var/folders/rr/63848xd90yscgwpkfn8srbyh0000gq/T/.org.chromium.Chromium.rarNyX}, 需要HeapSnapshot=true,databaseEnabled=false,handlesAlerts=true, 版本=43.0.2357.81,平台=MAC,browserConnectionEnabled=false, nativeEvents=true,acceptSslCerts=true,locationContextEnabled=true, webStorageEnabled=true,browserName=chrome,takeScreenshot=true, javascriptEnabled=true, cssSelectorsEnabled=true}] 会话 ID: 235ec977a69d98c7f5b75a329e8111b2

这意味着我尝试与之交互的元素(获取元素的文本)不再附加到 DOM。这个例子真的是我的规范简单化。在我的真实规范中真正发生的是我尝试获取元素列表的最后一个元素的文本(由 ng-repeat 生成)。还发生的是模型更新,通过删除表示元素列表的数组的最后一个元素。上面的这个例子只是为了重现错误(每次)。

如果我注释掉这一行:element(by.buttonText('start')).click();,说明规范成功。

【问题讨论】:

    标签: webdriver protractor


    【解决方案1】:

    我为此苦苦挣扎,并试图弄清楚为什么会发生这种情况。我首先认为指向列表最后一个元素的元素查找器是在交互完成之前很久就创建的,所以我毫不奇怪在创建之间的那段时间元素可以从 DOM 中分离出来。元素查找器和交互。

    我后来发现,元素是在交互完成之前找到的,每次你与某物交互时。所以指向最后一个元素实际上应该指向与该元素交互的时间的最后一个元素。

    使用 browser.pause() 我能够看到 WebDriver 的真正作用,这是两个任务之间的错误被抛出:

    (pending) Task::414<WebDriver.findElements(By.tagName("span"))>
    | | | | | | Task: WebDriver.findElements(By.tagName("span"))
    | | | | | |     at Array.forEach (native)
    

    在这中间,DOM根据模型更新,列表的最后一个元素被分离。

    (pending) Task::1170<WebElement.getText()>
    | | | | | | Task: WebElement.getText()
    | | | | | |     at Array.forEach (native)
    

    DOM 在这个小执行漏洞中更新。目前该模型每 50 毫秒更新一次,这肯定会引发 Stale Element Reference 错误。但是,如果我将间隔增加到 1000 毫秒,那么出现错误的机会就会少得多。因此,如果您收到此错误,这取决于您的计算机运行速度。

    解决方法取决于您,但我希望有了这些信息,应该更清楚该怎么做。

    【讨论】:

      【解决方案2】:

      浏览器与您的量角器测试异步运行。这个例子确实很好地突出了这一点(它是许多量角器测试的问题,但通常不那么明显)。看起来像一行的东西使情况更加复杂:

      expect(element.all(by.tagName('span')).last().getText()).toBe('Name999');
      

      实际上需要多次往返浏览器(有很多承诺被返回和解决:element.alllastgetText)。对于大多数稳定后“被动”的网页来说,这不是问题,但对于任何在没有用户输入的情况下动态变化的网页,使用量角器进行测试可能会很痛苦。

      要在浏览器中进行查找和测试“原子”,从而回避这个问题,您可以定义一个在浏览器中运行的函数(我的 CSS DOM-fu 很弱,所以希望有人可以调整它以使它不那么可怕):

      expect(browser.executeScript(function() {
         var spans = document.getElementsByTagName('span');
         var lastSpan = spans[spans.length - 1]; // XXX handle empty spans
         return lastSpan.innerText;
      }).toBe('Name999');
      

      请注意,“函数”是在浏览器上序列化和执行的,因此封闭范围内的任何变量都不会起作用。此外,这种方法失去了隐藏在量角器或 webdriver 中的任何浏览器兼容性魔法(例如,如果 getText() 不仅仅是一个 innerText 访问器,我不会感到惊讶)。

      另外,请注意您仍然有竞争条件。在“点击”开始工作和这段代码实际检查 DOM 之间,它可能已经发生了变异,也可能没有(并且“Name999”可能已经消失)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-01
        相关资源
        最近更新 更多