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 options
protractor.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 fail
NOT 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 busted
Can 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 missing
Try 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