On Github willbuck / midwestjs-2015-protractor
Will Buck
Follow along with the slides @ tinyurl.com/wb-mjs-2015
Find the repo at @ tinyurl.com/wb-mjs-2015-code
- Don't forget your name, slickSimulating the browser as the user will see it, integrations and all*
- caveat on integrations we'll talk about laterThis is an easy win for a CI system!
- This saved a ton of back and fourth with our QA team - Empowered them to kick off builds - For those unfamiliar, we use the term smoke testing in software to mean that the build didn't cause anything to smoke - Where there's smoke there's a fire - Fun fact: the term smoke test is also used in mechanical engineering like the picture here to look for leaksLike time tracking entries (credit @jimthedev)
- Anything you don't like doing? Why not protractor?By adding up many little things, there are a multitude of reasons a test can break
- Brittle like peanut-brittle - Many of these reasons don't conceptually 'break' the functionality - But they certainly could cause your test as you wrote it to fail - Can also fail intermittently due to downtimes or hiccups in any of your potentially many integrations - We have some means of mitigating this, but they aren't perfectIsolate the 5-10 tests that cover critical paths
Take care to test only core things after they're stable
- Small number of tests so devs can have a reasonably fast feedback loop - Can create suites if you still want heavier coverage - Testing only core stable features after they've solidified means they are unlikely to break easily - I'd recommend against TDD with E2E unless you've hardened a prototype of your user interaction pieces alreadyPrioritize: what is most critical?
- This can be a good exercise in general to understanding "what provides the most value to me / my users" - For twitter, it's probably posting a text tweet, retrieving your following list's tweets, following a new user, and ads showing up - DMs, profile settings, lists, these are way less critical most likelytl:dr; check out the protractor home page
- There's a few key pieces to keep track of - The protractor home page goes over all of this really nicelynpm install protractor
-g or --save-dev optional
- Probably good to -g if you intend to do this regularlyHow the page should behave
describe('angularjs homepage todo list', function() {
it('should add a todo', function() {
browser.get('https://angularjs.org');
element(by.model('todoList.todoText')).sendKeys('write first protractor test');
element(by.css('[value="add"]')).click();
var todoList = element.all(by.repeater('todo in todoList.todos'));
expect(todoList.count()).toEqual(3);
});
});
- Comment on default anatomy here:
- jasmine desc/it/expect,
- protractor element/by
- Default is Jasmine but Mocha/Chai, Cucumber, etc also optionsprotractor.conf.js
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['todo-spec.js']
};
- Tons of options here, be sure to check the docs (which browsers to run, preparation functions, etc)# in one console webdriver-manager update && webdriver-manager start # in another protractor protractor.conf.js # Or have your conf do both! just omit seleniumAddress & # Make sure you ran webdriver-manager update- Really pretty easy to get started with - Mind the conference wifi running npm install if you're trying to follow along though ;) - TRANSITION: So, now that we know what we need to get started, lets check out how we test some web pages!
YES, YOU CAN!
- You can test ANY website with Protractor, despite it being tailored for Angular - Any combination of css, html and js you can reach with a browser, you can write tests for - Some things are a little less ideal without angular, but overall I found it very usefulIn your conf:
exports.config = {
onPrepare: function() {
global.isAngularSite = function(flag){
browser.ignoreSynchronization = !flag;
};
}
};
Before all your tests:
beforeEach(function() {
isAngularSite(false);
});
- Need this to avoid waiting for angular failures
- If you don't have this, non-angular sites WILL failNOT with by.model, I'll tell you that
- Many examples show uses of by.model or by.binding or by.repeater - Regular websites don't have these angular-specific concepts - We'll be getting some sugar from protrator, but you'll essentially be doing webdriver w/ promises - What do I mean by that?by.css() and by.xpath() are your friends here
// from test-midwestjs.com/homepage.po.js
this.littleBirdie = element(by.css('div#logo div a:first-child'));
- If you're familiar with jquery you'll probably feel right at home with css selectors
- Do note though, these can get busted inadvertantly by a CSS / HTML developer
- It probably won't feel like they did anything wrong either
- Often this is mitigated by using ids on critical elements:
- This approach abstracts semantic meaning IMO but I haven't seen great alternatives
- If you have, please tweet it out and share your knowledge :)(a.k.a. the tool's primary aim)
- We've seen that we can test non-angular apps and that can be useful, but - This is what we're really meant to do with the toolLess likely to change than CSS selectors
// from test-prizeotron/main.po.js
this.apiKeyInput = element(by.model('api.key'));
this.remainingBadge = element(by.binding('rsvps.length'));
this.attendeeList = element(by.repeater('rsvps'))
- Since we're binding directly to our variable names, we can separate any CSS styling / element layout concerns from our testing bindings
- We even have projects like Ramon Victor's gulp-protractor-qa
- That project will do static analysis on all your element selectors and warn you early which are bustedCan get missed. Try this
afterEach(function () {
browser.manage().logs().get('browser').then(function (browserLog) {
expect(browserLog.length).toEqual(0);
});
});
- Helps catch errors your tests can be missingTry by.partialButtonText
this.importButton = element(by.partialButtonText('Import')); // Iffy
or by.css with the ng-click attribute
this.importButton = element(by.css('[ng-click="importNames()"]'))
// note that it might be data-ng-click
- Pick a strategy and stick to it, be clear across your team
- Prefer the users perspective (text) or prgrammers (ng-click)protractor --elementExplorer
# Then browser.get('http://mywebsite.com')
# Then element(by.css('div#mySelector')).getText() or whatever you want to do with the element
npm install protractor # do this globally ONCE if you have control ./node_modules/protractor/bin/webdriver-manager update ./node_modules/protractor/bin/protractor snapci.conf.js --suite midwestjs- If you DO have control, having protractor
onPrepare: function(){
jasmine.getEnv().addReporter(new HtmlReporter({
baseDirectory: './target/test-results/screenshots'
}));
},
"devDependencies": {
"protractor": "^2.1.0",
"protractor-html-screenshot-reporter": "0.0.20"
}
I used snapci.com
- Keep this brief, watch the clockBrowser options you don't have to manage!
- Tons of browsers supported - Means you don't have to manage the browser runtime envs (good bye Windows server / fleet of mobile devices?) - Useful if you're like us, have to support IE8, and don't want to deal with keeping an IE8 capable machine alive - (We don't actually use them, but I think it'd help us)DO YOU EVEN LIFT??
- For MACRO level benchmarking / performance testing - I don't know a ton about it, but I do have a folder in this repo capable of tinkering with it - Use case: getting an idea of where your site is at & then setting build thresholds that you don't make it worse - And now for a bit of a thriller ending to the talk...I've only been doing this for two months
- Hopefully you weren't expecting expertise - Now some of you might think...I hope this provided some value to someone
If it did, I'm cool
Please let there be some, you can have a sticker for asking one
- If you want to be 10 years old like me and collect super cool stickers