alecxe
alecxe

Reputation: 474141

Simplifying multiple boolean checks into a single one

In one of our tests, we have the following set of expectations:

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);

On one hand, having multiple simple expectations provide a more precise and understandable feedback, but, on another, this looks like it violates the DRY principle and the "one expectation per test" commonly acceptable guideline.

Is there a way to convert/simplify it to a single expect?


headerPage is a Page Object, dashboard and other page object fields are navigation links.

Upvotes: 11

Views: 349

Answers (4)

Ben Fogel
Ben Fogel

Reputation: 561

If this is logic you are using across multiple specs, you could look into jasmine custom matchers to encapsulate the logic.

It would be written somewhat like this:

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;
          }
    }
}

Add the matcher to your current test

jasmine.addMatchers(customMatchers);

And then in your tests you could just assert with

expect(headerPage).toDisplayWidgets();

Upvotes: 1

alecxe
alecxe

Reputation: 474141

Alternative approach. What I've ended up with was to add a page object method that returns the labels of the currently visible navigation links:

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

Then, the above test would be transformed to a concise and readable:

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

Upvotes: 1

Retsam
Retsam

Reputation: 33439

I think you've misunderstood the purpose of the "one expectation per test" guideline. The point isn't to combine a bunch of expectations into a single expectation, it's to split up your expectations into separate tests.

To follow the spirit of that guideline, you would write your tests like this:

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.
});

That's a fair bit more verbose than what you have; but that's why these are guidelines not rules. It's a tradeoff between how verbose you make your tests, versus how easy they are to debug later. ("The header page displays the dashboard: FAILED") is a very clear and specific test failure message, compared to getting the same failure message regardless of which expectation actually failed.

I definitely would not try to combine all of these lines into a single line. If you don't want to split it into a bunch of different test cases I would just leave it how it is.

Upvotes: 14

nuway
nuway

Reputation: 2394

what about using a helper function that returns results of all the tests, something like

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();
}

Upvotes: -1

Related Questions