So, is Protractor easier than Selenium?

Yes!

In this blog post I plan to give you a taste of why you’d benefit from using Protractor for your JavaScript tests instead of using Selenium webdriver directly, even if your app has nothing to do with AngularJS yet – or just a partial usage. 

If you peek inside Protractor you’ll see the good old Selenium Web Driver (aka WebDriverJS aka selenium-webdriver).

Protractor is essentially a wrapper for the JavaScript Selenium webdriver. Therefore – you get all the capabilities of the webdriver – along with a number of very useful additions.

Oh – so they probably added some Angular stuff – right?

Yes!

They added accessors to angular models, bindings, ng-options – and finding elements inside ng-repeat. These additions make querying for elements much easier. For example – let’s get all the ages of the cats that the repeater adds:


<div ng-repeat="cat in pets">
    <span>{{cat.name}}</span>
    <span>{{cat.age}}</span>
</div>

// test code:
// ---------
// Returns a promise that resolves to an array of
// WebElements from a column
var ages = element.all(
    by.repeater('cat in pets').column('{{cat.age}}'));

Ever struggled with the challenge of determining when the page is truly ready, i.e. all the asynchronously fetched resources are ready and processed? Check out waitForAngular that does exactly that.

But I don’t use Angular yet – should I keep reading?

Yes!

They added other goodies – accessors (locators) by button text, partial button text – and the very cool option to find by a combination of CSS and text (get me all the divs with class ‘pet’ and text ‘dog’).

Also – they added the addLocator function to help you add your own locators – so that, for a fictional example, you can get elements by their handlebars properties.

But I’m already using Selenium extensively

First of all, pat yourself on the back – you’re already in better shape than most teams out there. You can install Protractor and use it with your existing infrastructure. Simply configure Protractor to operate against your Selenium servers.

Please note: You’ll have to take some additional steps to run Protractor successfully on non-Angular pages. We will cover this issue in the next post.

OK – please continue

Ye… oh – great, let’s see now:

One more addition that makes life easier for users is globals.

Protractor adds these objects to the global namespace: browser, element and by. Now go ahead and spot the difference between the two canonical examples:

Protractor (9 lines of code, not including the comments):


// starting right here with two Jasmine lines.
// All the rest is preconfigured separately and very easily.
describe('angularjs homepage', function() {
    it('should add one and two', function() {
        // Just go ahead and use the webdriver – the configuration
        // took care of the initialization
        browser.get('http://juliemr.github.io/protractor-demo/');
        // much shorter than driver.findElement… webdriver.By…
        element(by.model('first')).sendKeys(1);
        element(by.id('gobutton')).click();
        // please appreciate how naturally
        // expect works with this flow
        expect(element(by.binding('latest')).getText()).
             toEqual('3');
    });
});

Selenium (17, longer, lines of code, not including the comments):


// Defining some requirements – to be able to use assertions
// and test syntax
var assert = require('assert'),
    test = require('selenium-webdriver/testing'),
    webdriver = require('selenium-webdriver');

// Now we can write a test
test.describe('Google Search', function() {
    test.it('should work', function() {
        // We need to setup the webdriver…
        var driver = new webdriver.Builder().
            withCapabilities(webdriver.Capabilities.chrome()).
            build();

        // finally we can actually do something
        driver.get('http://www.google.com');
        // all the functions are accessed via driver of webdriver.
        // Much typing!
        driver.findElement(webdriver.By.name('q'))
            .sendKeys('webdriver');
        driver.findElement(webdriver.By.name('btnG')).click();
        // spoon-feeding the assertion using then
        // and resolving the value
        driver.getTitle().then(function(title) {
            assert.equal(title, 'webdriver - Google Search');
        });
    
        // calling this ourselves
        driver.quit();
    });
});

More! I want moar!!!

Sure, why not?

Starting to work with Protractor is a breeze. You get the Jasmine test library out of the box – with a bonus patch to the ‘expect’ function to easily provide validation through assertion. You get webdriver-manager to take care of the local webdriver server for you and make it easy to test against a remote server. You don’t have to run your tests directly as scripts using node – as your initial attempts with selenium will have you do.

This brings us to another point – Protractor has much better documentation, in my opinion.

Conclusion

Protractor is neat – and I see it as a very useful evolution from Selenium Webdriver for JavaScript.

It’s not limited to testing only AngularJS apps – even though these two are usually mentioned together. However – it was designed mainly for Angular and some work is required, at least currently, to use it on non-angular pages. We will review this in the next post. If you plan to gradually move your site/app to Angular – you can start writing your Protractor E2E tests right now – and I will show you how.

If you’re already using Angular, there’s a bunch of guides out there that will help you get started with Protractor – and I intend to provide more information in future posts.

 

Release Apps with Flawless UI - with Applitools Eyes

Written by Doron Zavelevsky, Sr. Frontend Developer @ Applitools