Automation and Integration Tests in Sitecore – Using Nightwatch.js

Sitecore is complex.

I mean, really complex. And flexible. One of the most flexible technologies you will use in your career. You can do pretty much everything you want by creating a custom this, another custom that, two processors, one pipeline, a few services, etc.

And this is its power. That’s why so many huge companies out there keep buying and using Sitecore.

Not only that but for me as a developer this is why it is so much fun. It’s hard and complicated, of course, but all things that are worth doing in our life are like that. A shoot-out to my daughter Cécile, daddy loves you.

daughter

Now let’s get back on track.

Almost every Sitecore project I worked on had a pretty decent unit tests coverage. Unit tests are more often than not on the radar of all teams. They know they should be unit testing their components, and since it’s really easy to create those tests (when using the right architecture, of course) they will end up doing so.

But never integration tests. They are often left for “phase two” since they are complicated (really?) and not that necessary (what?!). But wait… As I said Sitecore is complex, with a lot of different components interacting with each other. And let’s be honest, we all know that when we put all those components together in a feature, that’s when everything will break.

giphy

The goal of this post is to show you how integration tests and automation can be really easily developed when the right framework is used. We don’t need to reinvent the wheel…

What is this Nightwatch.js thing?

It’s a Selenium-based open-source Javascript framework that you can (and should) use to create your tests and tasks. That simple.

Instead of having to create the method to click on that button, use it from the framework. Same thing for writing something on that login textbox. Or for changing the current page or context. Nightwatch.js covers it all.

And the best part is that it has basically four fundamental concepts and once you master them you can consider yourself a master of Nightwatch.js.

The 4 Fundamental Concepts

1. Commands

A Nightwatch.js command is a method that represents a very specific action. Nothing fancy or complex here. Only simple stuff.

Clicking on a button? That can be a command. Navigating to another page? Absolutely. Republishing your website and then rebuilding all your Solr indexes? What the hell, I said simple stuff man! Keep the complexes things for the third fundamental concept.

giphy-1

The framework already comes with a bunch of out-of-the-box commands that you can use. Clicking, writing something in an input field or navigating are a few ones. And actually, you can do some real automation by using only them!

However, Nightwatch is flexible enough so you can create some custom command if you find yourself repeating this very specific set of actions on your tests over and over again. Here is an example of a real custom command I created to navigate to one of the thousands iFrames Sitecore has:

[navigateToJqueryModalDialogsFrameIFrame.ts]

import { NightwatchBrowser } from 'nightwatch';

export function command(this: NightwatchBrowser): NightwatchBrowser {
    this.pause(2000);
    this.frame(null);
    this.frame('jqueryModalDialogsFrame');
    return this;
}

2. Assertions

After executing some actions on your Sitecore pages, you will need to validate something, right? We are talking about tests after all.

Assertions are exactly this. A method which represents a validation you can execute during your tests or automation tasks.

Again, Nightwatch.js offers so many different out-of-the-box assertions, but you can create your custom one if you want. Pretty honestly, it’s really rare that you find yourself needing to create one of those. The default assertions are really all you need.

Assertions and commands are the base of any Nighwatch.js solution.

3. Page Objects

Those are classes that represent pages or fragments or pages. Bringing it back to our Sitecore context, the login page would be a page object. And then the content editor would be another page object.

Each one of them must contain methods related to that page. Those methods represent major actions (different from Commands, which must be very specific actions) such as Sitecore Republish, or even Rebuild Lucene Indexes. And finally, those methods will be using commands and assertions to achieve their results. You see? All the pieces are getting together…

Here is an example of a page object method:

[sitecoreContentEditor.ts]

searchHomeItem: function (this: INightwatchSitecoreContentEditor): INightwatchSitecoreContentEditor {
	this.waitForElementVisible('#TheeSearch', 10000, 'The content editor searchbox is visible')
	    .setValue('#TheeSearch', 'Home')
	    .click('.scSearchButton')
	    .waitForElementVisible('#SearchResult a[title="/Home"]', 10000, 'The Home item is returned as result');
	return this;
},

4. Tests

The final and most important concept. Those are classes that represent a unit of test/automation task. And this detail is very important. A unit. Keep this in mind when you create your tests, they can’t be executed partially, so make sure you separate all your integration tests properly.

Each one of them should test a business operation, such as “Search Page Features” or automate a major operation, such as the “Full Republish” of your website. It will use the methods you defined on each Page Objects, or even use the Commands and Assertions directly.

Another point super important is that your test is going to generate a report at the end, so ideally you should separate its execution into sub-sections so this report is easy to be understood.

Here is an example of a test class:

[publishWebsite.ts]

import { NightwatchBrowser } from 'nightwatch';

export = {

    beforeEach: function (client: NightwatchBrowser): void {
        client.maximizeWindow();
    },

    'Log in to Sitecore Instance': function (client: NightwatchBrowser): void {
        client.page.sitecoreLogin()
            .navigate()
            .loginSitecore();
    },

    'Publish from master to web': function (client: NightwatchBrowser): void {
        client.page.sitecoreContentEditor()
            .navigate()
            .republishSite();
    },

    after: function (client: NightwatchBrowser): void {
        client.end();
    }
};

Putting Everything Together

Once you have created your Page Objects and Tests/Tasks, you can create a npm script to make your life easier when calling them. Just add something like this to your package.json:

"scripts": {
    "publish-website": "node nightwatch-runner --test bin/tests/sitecore/publishWebsite.js --env local",
    "search-pages": "node nightwatch-runner --test bin/tests/coveo/search-pages/searchPageFeatures.js --env local"
}

And then you can run those tests and tasks, sit back and enjoy the moment:

[npm run-script publis-website]

automated publish

automated publish report

[npm run-script search-pages]

automated search features.gif

autmated search report

This is just an example of how automation can save you a lot of time. Pretty much every QA process will start by installing a Sitecore package and then publishing the entire website. You can automate both… we did.

After this boring process, you will start clicking here, checking something there, writing some words here and there… And again, you can automate all that.

Can you imagine how life would be easier if you could reduce your QA process timeline by 70% just by automating the majority of tasks and tests? We are at Coveo the living proof that it is achievable.

Of course, it’s really hard to start this. Even harder to pay the tech debt you have from all the already created features that aren’t tested automatically.

The secret here is really to take baby steps. Start by automating only one thing. We started by automating the installation of the Coveo for Sitecore package. When the team sees how much time they are saving, it will be easier to keep advancing.

giphy-2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s