测试 link 样式更改

Testing link style changes

在我们的一项测试中,我们正在测试link(a 元素)样式在鼠标悬停在 上之后发生的变化。

默认情况下,link 的字体是黑色的,没有装饰,但是当鼠标悬停在上面时,字体会变成蓝色,并且 link 的文本会变成带下划线的。这是相关测试:

it("should change font style on mouse over", function () {
    expect(scope.page.forgotPassword.getCssValue("color")).toEqual("rgba(11, 51, 60, 1)");
    expect(scope.page.forgotPassword.getCssValue("text-decoration")).toEqual("none");

    browser.actions().mouseMove(scope.page.forgotPassword).perform();

    expect(scope.page.forgotPassword.getCssValue("color")).toEqual("rgba(42, 100, 150, 1)");
    expect(scope.page.forgotPassword.getCssValue("text-decoration")).toEqual("underline");
});

问题是在大约十分之一的运行中,它失败并显示以下错误消息:

Expected 'rgba(11, 51, 60, 1)' to equal 'rgba(42, 100, 150, 1)'.

Expected 'none' to equal 'underline'.

我怀疑它会在 css 样式实际更改之前读取它们。

如何使测试更可靠和稳定?将不胜感激任何提示。

CSS 更新中的这种异步似乎 protractor/webdriver 应该可以等待。您的应用程序是否执行了任何异常操作来实现悬停时的 CSS 更新?它是以某种方式指定动画或更新延迟吗?

也就是说,我认为有时量角器可能不知道更新可能需要一些时间,所以我认为您可以用不同的方法编写测试。与其期望值是您想要的值(并与浏览器中的更改竞争),不如将测试重新表述为 "wait-until-value-I-want-shows-up"? (失败案例有点慢和难看,但希望这种情况很少见。)

检查 text-decoration 移动到 'underline' 似乎更简单(并且可能两者都会改变 "at once",所以您只需要等待一个然后可以检查另一个? )

所以删除:

expect(scope.page.forgotPassword.getCssValue("text-decoration")).toEqual("underline");

并使用类似这样未经测试的代码:

browser.wait(function() { 
 return scope.page.forgotPassword.getCssValue("text-decoration")).then(function(value) {
   return value === 'underline';
 });

(或者为此使用 基础设施?)

您应该能够在函数中隐藏一些丑陋之处:

function waitForValue(valPromise, expectedVal) {
   return browser.wait(function() {
      return valPromise.then(function(value) {
         return value === expectedValue;
      });
   });
}

// Now your test can contain:
waitForValue(scope.page.forgotPassword.getCssValue("text-decoration"), 'underline');

按照@P.T.的建议,我最终制作了一个自定义可重用"Expected Condition":

waitForCssValue = function (elementFinder, cssProperty, cssValue) {
    return function () {
        return elementFinder.getCssValue(cssProperty).then(function(actualValue) {
            return actualValue === cssValue;
        });
    };
};

用法示例:

browser.wait(waitForCssValue(scope.page.forgotPassword, "color", "rgba(42, 100, 150, 1)"), 1000);
browser.wait(waitForCssValue(scope.page.forgotPassword, "text-decoration", "underline"), 1000);