KEMBAR78
Angular UI Testing with Protractor | PPTX
UI Testing with Protractor 
Andrew Eisenberg 
Tasktop Technologies
About me 
• PhD from UBC 
• SpringSource/VMware/Pivotal 
– Spring, Groovy, AspectJ, JS (IDE and languages) 
• Tasktop 
– Platform and Apps teams
Kinds of testing 
• Unit testing 
• Integration testing 
– UI Testing 
• System testing 
Using Protractor
How Protractor works 
• Selenium Server to manage browsers 
• Selenium WebDriver to invoke browser APIs 
• Protractor node app to run tests 
• Jasmine, etc as test framework
How to run Protractor 
• Protractor config file: 
exports.config = { 
onPrepare: function () { … }, 
capabilities: {'browserName’:'firefox’}, 
specs: ['../tests/*.spec.js'], 
baseUrl: 'http://localhost:8080/’, 
jasmineNodeOpts: { … }, 
// and many more options 
} 
• To launch: 
protractor protractor.conf.js
The first test 
describe('HomePage', function () { 
it('should be the default page', 
function () { 
browser.get(browser.baseUrl); 
expect(browser 
.getCurrentUrl()) 
.toEqual(browser.baseUrl 
+ 'projectsinfo'); 
}); 
});
The PageObject pattern 
• Models the services exported by a page 
LoginPage.prototype = { 
isLoggedIn : function() { … }, 
logout : function() { … }, 
login : function() { … }, 
cancelLogin : function() { … } 
}
Secretly, everything is a promise
Debugging! 
Add to script: 
browser.debugger(); 
Launch in debug mode: 
protractor debug protractor.conf.js
SOME THINGS I LEARNED
Avoid complex selectors 
Bad 
element(by.cssContainingText(‘table.data tr.user td.name’, 
‘Jane’); 
element(by.repeater(‘option as option.label for option in 
field.options track by (option.value + option.label)’); 
Good 
element(by.cssContainingText(‘.name’, ‘Jane’); 
element(by.css (‘#name-Jane’); 
element(by.css(‘#options’));
Selectors are brittle 
• ids most stable 
– easy to fix when they change 
– consider dynamically generated ids 
• but be careful they are always valid and unique 
– Should be namespaced by directive 
• but…what if directive repeated multiple times? 
• OK to refactor base code 
– make it more testable 
– expose ids
Impossible to test everything 
• Too many corner cases 
• Happy path 
• A few corner cases 
• Any interesting interactions 
• More complex tests are more brittle 
• Trade-off: 
– time spent writing/maintaining tests vs code
Your tests will be 
Incomplete and 
Brittle 
Deal with it.
State & Reproducibility 
• Better to test against clean state 
• Better to tear down before each test 
• Can be slow to clean 
• Tests should not make assumptions about 
clean state
UI Testing with Protractor 
Andrew Eisenberg 
Twitter: @werdnagreb

Angular UI Testing with Protractor

  • 1.
    UI Testing withProtractor Andrew Eisenberg Tasktop Technologies
  • 2.
    About me •PhD from UBC • SpringSource/VMware/Pivotal – Spring, Groovy, AspectJ, JS (IDE and languages) • Tasktop – Platform and Apps teams
  • 3.
    Kinds of testing • Unit testing • Integration testing – UI Testing • System testing Using Protractor
  • 4.
    How Protractor works • Selenium Server to manage browsers • Selenium WebDriver to invoke browser APIs • Protractor node app to run tests • Jasmine, etc as test framework
  • 5.
    How to runProtractor • Protractor config file: exports.config = { onPrepare: function () { … }, capabilities: {'browserName’:'firefox’}, specs: ['../tests/*.spec.js'], baseUrl: 'http://localhost:8080/’, jasmineNodeOpts: { … }, // and many more options } • To launch: protractor protractor.conf.js
  • 6.
    The first test describe('HomePage', function () { it('should be the default page', function () { browser.get(browser.baseUrl); expect(browser .getCurrentUrl()) .toEqual(browser.baseUrl + 'projectsinfo'); }); });
  • 7.
    The PageObject pattern • Models the services exported by a page LoginPage.prototype = { isLoggedIn : function() { … }, logout : function() { … }, login : function() { … }, cancelLogin : function() { … } }
  • 8.
  • 9.
    Debugging! Add toscript: browser.debugger(); Launch in debug mode: protractor debug protractor.conf.js
  • 10.
  • 11.
    Avoid complex selectors Bad element(by.cssContainingText(‘table.data tr.user td.name’, ‘Jane’); element(by.repeater(‘option as option.label for option in field.options track by (option.value + option.label)’); Good element(by.cssContainingText(‘.name’, ‘Jane’); element(by.css (‘#name-Jane’); element(by.css(‘#options’));
  • 12.
    Selectors are brittle • ids most stable – easy to fix when they change – consider dynamically generated ids • but be careful they are always valid and unique – Should be namespaced by directive • but…what if directive repeated multiple times? • OK to refactor base code – make it more testable – expose ids
  • 13.
    Impossible to testeverything • Too many corner cases • Happy path • A few corner cases • Any interesting interactions • More complex tests are more brittle • Trade-off: – time spent writing/maintaining tests vs code
  • 14.
    Your tests willbe Incomplete and Brittle Deal with it.
  • 15.
    State & Reproducibility • Better to test against clean state • Better to tear down before each test • Can be slow to clean • Tests should not make assumptions about clean state
  • 16.
    UI Testing withProtractor Andrew Eisenberg Twitter: @werdnagreb