Saturday, May 23, 2015

I saw Darryl Parker speak on Protractor testing for AngularJS on Wednesday night at eBay's offices.

When I attempt to retrace the steps he undertook in his setup at my own laptop like so:

  1. node --version
  2. npm --version
  3. npm install protractor -g
  4. webdriver-manager update
  5. webdriver-manager start
  6. mkdir e2eTest
  7. cd e2eTest
  8. touch config.js
  9. touch test.spec.js

 
 

I hit a brick wall at the third command (where g stands for global, FYI) and cannot continue making the rest of what is to come impossible to navigate. Grr. I guess I'll type up my notes nonetheless, huh? The last two lines create two files, the first a config file and the second a file which contains an actual test. One should then run the test with:

protractor config.js

 
 

webdriver-manager will run on port 4444. Jasmine (BDD stuff) is used as the default testing framework. Selenium is used by Protractor to empower the end-to-end testing. A Julie Ralph seems to have spearheaded Protractor's creation. By default, Protractor will only work with AngularJS and try to find (demand/require) the angular var, but this may be sidestepped with a particular setting allowing one to end-to-end test anything with Protractor. That said, the $httpBackend mocking for the backend (REST calls in a stereotypical AngularJS application that lives standalone and not as the frontend to a C# app) will obviously not work beyond AngularJS itself. Darryl prefers to use directive testing in AngularJS when he can but falls over to end-to-end testing when he cannot. In his presentation he walked us, the audience, through many red/green/refactor traditional approaches to writing tests. Anyways, the config file looks like this:

exports.config = {
   seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
   specs: ['*.spec.js']
};

 
 

The config file points to all files ending in .spec.js as tests to run. The one test we have so far looks like this:

describe{'Protractor Demo', function(){
   it('should show a title', function(){
      browser.get('http://juliemr.github.io/protractor-demo/');
      expect(browser.getTitle()).toEqual('Super Calculator');
   });
});

 
 

http://juliemr.github.io/protractor-demo/ is a super simple calculator app that Julie Ralph made in AngularJS that is being tested in this case. This URL could obviously be swapped out with your own. A more complicated example which puts values into the calculator, clicks the button, and then verifies the result will look like so:

describe{'Super Calculator', function(){
   it('should add two numbers', function(){
      browser.get('http://juliemr.github.io/protractor-demo/');
      element(by.model('first')).sendKeys(1);
      element(by.model('second')).sendKeys(2);
      element(by.id('gobutton')).click();
      expect(element(by.binding('latest')).getText()).toEqual('3');
   });
});

 
 

Alright, the button is found here by just having an id of gobutton, but the first and second inputs are found by ng-model settings, which, like the id, may just be observed as inline tag attributes by looking at the HTML itself. by.binding('latest') however matches up to {{latest}} in source code which will not be visible to observers looking directly at the HTML wrapping the 3 which just looks like this:

<h2 class="ng-binding">3</h2>

 
 

Darryl knew about the binding (yes, the thing in double curly braces) by way of pulling Julie's source code from her GitHub. If you are testing your own Angular app, obviously, you too will have access to and knowledge of these "invisible" bindings. The two tests above both pass.

No comments:

Post a Comment