Protractor and Jasmine Data Provider

Write Once, Test Many

   Quality Assurance
protractor jasmine data provider

With any framework that picks up traction and becomes widely used, comes an awesome community of developers looking to make that framework better than it is on its own. Package managers like NPM and Homebrew provide a bountiful host of tools and extensions that can be helpful (and sometimes life-saving) to your project. One such tool is Jasmine Data Provider, an NPM module for Protractor.

Jasmine Data Provider supplies an extra method to extend Protractor’s built-in describe method, allowing for multiple data sets to be run against the same test. This becomes valuable when testing application features like Google Maps integration and e-commerce transactions, where you have varying data that needs to be verified using the same process. Jasmine Data Provider takes everything that makes Protractor great and adds an extra level of functionality to your test suite, and this tutorial will cover how to integrate it into your own automation stack. Let’s get started!

Setting Up

While I encourage you to use this tutorial to implement Jasmine Data Provider into your own Protractor suite, you can clone the example project I have set up and follow along, comparing what I show here with what is already written there.

This tutorial assumes you have an understanding of how to install Protractor and get it running. If you need help with this step, Mallory Mooney has an excellent guide on getting started with Protractor here. Once Protractor is installed and ready to be used, we need to install the module that is most important to this article — Jasmine Data Provider.

$ npm install jasmine-data-provider --save-dev

This will install Jasmine Data Provider in your node_modules folder and in your package.json under devDependencies, making it available for use in your project. You are free to install it globally, but best practice is to keep the global scope as clean as possible.

To make sure our test will actually run when we’re ready to do so, open a new command line prompt at the root of your test directory and enter the script:

$ webdriver-manager update
$ webdriver-manager start

This will ensure Selenium is up to date and start a selenium server, allowing your tests to execute against it.

Your Spec File

I provided a few examples of the different kinds of scenarios Jasmine Data Provider could be useful for above. In this tutorial, we’re going to use it to see which team members on the Modus Create ‘About’ page are present and if their Twitter pages are linked to their portrait. Before we jump into our spec file, let’s take a look at the data we want to run our test against.

'use strict';

module.exports = {
    twitterInfo: {
        'Andrew Owen': {handle: 'modusAndrew'},
        'Steve Dalgetty': {handle: 'stevedalgetty'},
        'Dave Ackerman': {handle: 'dmackerman'},
        'Fake Jay Garcia': {handle: 'notjaygarcia'}
    }
}

This module is pretty straightforward. It exports an object twitterInfo along with all of its sub-objects. These each include a description which holds the person’s name and any data about that description we want – in this case, just their Twitter handle. As is best practice, we also declare Strict Mode at the top of the file, to ensure our syntax is clean and our code secure. With that file complete, we now have a module ready for use anywhere in our project and we’ll use it in our spec file shown below.

var employee = require('./employeeData.module.js');
var using = require('jasmine-data-provider');

describe('find Modus twitter accounts', function() {

    beforeEach(function() {
        browser.ignoreSynchronization = true;
        browser.get('https://moduscreate.com/about');
    });

    using(employee.twitterInfo, function(data, description) {

        it("Twitter found for " + description, function() {
            expect(element(by.cssContainingText('.name', description)).isPresent()).toBeTruthy(
                'Employee not found'
            );
            expect(element(by.css('a[href="http://www.twitter.com/' + data.handle + '"]')).isPresent()).toBeTruthy(
                'Employee does not have twitter linked'
            );
            element(by.css('a[href="http://www.twitter.com/' + data.handle + '"]')).click();
            expect(browser.getTitle()).toEqual(description + " (@" + data.handle + ") | Twitter"); 
        })
    });

    afterEach(function() {
        browser.ignoreSynchronization = false;
    })
})

If you’re familiar with Protractor, most of example.spec.js should make sense. beforeEach and afterEach are used for setup and teardown and the describe method starts our test definition. The part we’re interested in, however, is the function using on line 11.

using(employee.twitterInfo, function(data, description) { … 

This new function using pulled from our Jasmine Data Provider, wraps around any or all test statements we want to repeat, uses employee.twitterInfo as the provided data (hence the name, Data Provider) and takes two arguments, data and description.

  • description returns the left side of the sub-object under twitterInfo – in our case the employee’s name.

  • data returns the value of any key defined within the curly brackets after the description, so for example, when we use data.handle for Andrew Owen, it will return modusAndrew.

This function is the real power behind Jasmine Data Provider. With it, our test will run over and over until it no longer has data from twitterInfo to pull in. Instead of writing a brand new test every time we add a new user, we simply need to add their name and twitter handle to the module file, and Jasmine Data Provider will handle the rest. Hooray! Write once; test many.

Now before we get to running the test, let’s go the extra mile and give Protractor a clean way to do it.

Extra Credit – Suite Config

Just like adding more specs to your config file will increase the time it takes for your tests to complete, adding more data to your module file will increase the time it takes for that one spec file to complete. Eventually, as your test suite grows larger, having to wait for one spec file to complete before moving on to the rest can really bog down your project, especially if you’re implementing automated tests into your build process.

One way we can avoid this is by assigning our spec file to a suite. This will give our spec file a unique identifier that we can use when running our tests to specify which ones we want to run and which we do not.

To add your spec file to a suite, open up your protractor.config.js file and add this below your specs config:

suites: {
    repeatable: '#path_to_your_spec/example.spec.js'
},

Now your spec file is attached to a suite called repeatable and will only be run when specified. You are free to rename repeatable to whatever you like so long as it’s meaningful to you and those running your tests. To run this suite, open a new command line prompt and enter:

protractor protractor.conf.js --suite repeatable

And Voilà! You now have a configured, working test suite ready to be used when you need it, if you need it.

Screenshot 2016-03-17 14.14.21

Conclusion

Jasmine Data Provider is a lightweight and powerful tool that adds incredibly useful coverage to your existing automation stack. As your application gets more and more complex, increasing your intellectual arsenal becomes increasingly important. What useful modules and tools have helped you step your automation game up? Let us know in the comments!

Big shout out to GitHub user mortalflesh for creating the Jasmine Data Provider and sharing it with the community.


Like What You See?

Got any questions?