问题 将多个布尔检查简化为单个布尔检查


在我们的一项测试中,我们有以下一系列期望:

expect(headerPage.dashboard.isDisplayed()).toBe(true);
expect(headerPage.queue.isDisplayed()).toBe(true);
expect(headerPage.claimSearch.isDisplayed()).toBe(true);
expect(headerPage.claim.isDisplayed()).toBe(true);
expect(headerPage.case.isDisplayed()).toBe(true);
expect(headerPage.calendar.isDisplayed()).toBe(true);

一方面,有多个简单的期望提供了更精确和可理解的反馈,但另一方面,这看起来像它 违反DRY原则 和 “每次测试一个期望” 通常可以接受的准则。

有没有办法将其转换/简化为单一预期?


headerPage 是一个页面对象, dashboard 和其他页面对象字段是导航链接。


7188
2018-05-16 17:42


起源



答案:


我认为你误解了“每次测试期望”指南的目的。关键不在于将一堆期望结合到一个单一的期望中,而是将您的期望分成单独的测试。

要遵循该指南的精神,您可以像这样编写测试:

describe("The header page", function () {
    var headerPage;
    beforeEach(function () {
        //Common logic here
    });

    it("displays the dashboard", function () {
        expect(headerPage.dashboard.isDisplayed()).toBe(true);
    });

    it("displays the queue", function () {
        expect(headerPage.queue.isDisplayed()).toBe(true);
    });

    it("displays the claimSearch", function () {
        expect(headerPage.claimSearch.isDisplayed()).toBe(true);
    });

    //etc.
});

这比你的更加冗长;但这就是为什么这些是指导而不是规则。这是在您进行测试的详细程度与稍后调试的容易程度之间的权衡。 (“标题页显示仪表板:FAILED”)是一个非常清晰且特定的测试失败消息,与获取相同的失败消息相比,无论哪个期望实际失败。

我绝对不会尝试将所有这些线组合成一行。如果您不想将其拆分为一堆不同的测试用例,我会留下它的样子。


15
2018-05-16 17:58



这很有道理。我也考虑采用不同的方法 - 拥有一个页面对象方法,该方法将返回当前可见的导航链接并改为断言。准备好后也会在这里发布。非常感谢! - alecxe
仅供参考,发布了我最终的结果。 - alecxe


答案:


我认为你误解了“每次测试期望”指南的目的。关键不在于将一堆期望结合到一个单一的期望中,而是将您的期望分成单独的测试。

要遵循该指南的精神,您可以像这样编写测试:

describe("The header page", function () {
    var headerPage;
    beforeEach(function () {
        //Common logic here
    });

    it("displays the dashboard", function () {
        expect(headerPage.dashboard.isDisplayed()).toBe(true);
    });

    it("displays the queue", function () {
        expect(headerPage.queue.isDisplayed()).toBe(true);
    });

    it("displays the claimSearch", function () {
        expect(headerPage.claimSearch.isDisplayed()).toBe(true);
    });

    //etc.
});

这比你的更加冗长;但这就是为什么这些是指导而不是规则。这是在您进行测试的详细程度与稍后调试的容易程度之间的权衡。 (“标题页显示仪表板:FAILED”)是一个非常清晰且特定的测试失败消息,与获取相同的失败消息相比,无论哪个期望实际失败。

我绝对不会尝试将所有这些线组合成一行。如果您不想将其拆分为一堆不同的测试用例,我会留下它的样子。


15
2018-05-16 17:58



这很有道理。我也考虑采用不同的方法 - 拥有一个页面对象方法,该方法将返回当前可见的导航链接并改为断言。准备好后也会在这里发布。非常感谢! - alecxe
仅供参考,发布了我最终的结果。 - alecxe


替代方法。我最终得到的是添加一个返回页面对象的方法 当前可见导航链接的标签

this.getVisibleLinks = function () {
    return $$(".ap-header-nav-tabs li a").filter(function (link) {
        return link.isDisplayed();
    }).getText();
};

然后,上面的测试将转换为简洁和可读:

expect(headerPage.getVisibleLinks()).toEqual(["Dashboard", "Queue", "Claim Search", ...]);

1
2018-05-16 22:19





如果这是您在多个规范中使用的逻辑,那么您可以查看jasmine 自定义匹配器 封装逻辑。

它会写得有点像这样:

var customMatchers = {
    toDisplayWidgets: function(util, customEqualityTests) {
        return {
            compare: function(actual, expected) {
                  function isDisplayingWidgets(page) {
                      return page.dashboard.isDisplayed() && 
                             page.queue.isDisplayed() &&
                             page.claimSearch.isDisplayed() && 
                             page.claim.isDisplayed() &&
                             page.case.isDisplayed() && 
                             page.calendar.isDisplayed();
                  }

                  var result = {};
                  result.pass = isDisplayingWidgets(actual);

                  if (!result.pass) {
                      result.message = 'dashboard is not displayed';
                  }

                  return result;
          }
    }
}

将匹配器添加到当前测试中

jasmine.addMatchers(customMatchers);

然后在你的测试中你可以断言

expect(headerPage).toDisplayWidgets();

1
2018-05-20 15:54





那么使用一个返回所有测试结果的辅助函数呢

expect(headerDisplayTests()).toBe(true);

function headerDisplayTests() {
    return headerPage.dashboard.isDisplayed() && 
            headerPage.queue.isDisplayed() &&
            headerPage.claimSearch.isDisplayed() && 
            headerPage.claim.isDisplayed() &&
            headerPage.case.isDisplayed() && 
            headerPage.calendar.isDisplayed();
}

-1
2018-05-16 17:50



谢谢,我想到了“提取方法”的技巧,但这不会起作用 isDisplayed() 返回一个承诺..protractor.promise.all() 这里需要的。请查看您是否可以调整答案以将其考虑在内。 - alecxe
如果isDisplay()返回一个promise,那么你的例子如何(headerPage.dashboard.isDisplayed())。toBe(true);工作? - nuway
是的,因为量角器有期望修补隐含地解决承诺.. - alecxe
如果这种期望失败,你将很难找到它的哪一部分被打破。 - Роман Парадеев