A post about promises, web-testing and far too much indentation.
This post covers the tests defined in https://github.com/britishlibrary/UniversalViewerTests
Recently, I have been writing browser tests for a Javascript application. The tests were invoked via Protractor running under Node.js locally on a Windows laptop. The Automate service from BrowserStack was used for cross-browser capability checking, and to be honest I can't recommend that service enough. It's *very* clever and straightforward.
The tests use Cucumber to enable BDD-style spec statements for features and scenarios. This differs from the usual uses of Protractor tests which generally use Jasmine - a library that represents test scenarios programmatically. A lack of documentation surrounding the use of Cucumber in Protractor has been a major headache during the project.
The tests as received originally used Selenium's webdriverjs to drive the browser session. Before the previous developer left, we converted many of the test features over to using a Page Object which offers an abstracted set of functions that allow access to elements on the page whilst hiding the details of how the elements are found; the concerns of the test functionality are therefore separated from the concerns of how to locate an element.
Further, since we are using Protractor to test a website that does not use AngularJS, the synchronisation that Protractor will do under the hood is not available. This means that communication with Selenium webdriver must be done using a Promise - a callback-like way of scheduling functionality to occur after a call into a sub-system with handling for success and failure of operations. Although ostensibly a means to cut-down on code, using Promises has the same effect as callbacks in that *everything* becomes a callback and you can end up very far across your screen for even minor functionality.
A Page Object doesn't have to be very smart. All it has to do is hide the implementation of locating elements for the tests that call it.
I generalised three methods - find, findAll and sleep:
Almost all the abstracted functions for accessing elements in the Page Object use these methods. This was done primarily so that I could centralise the logging for what was going on. Here are some example element abstractions:
This makes the code that uses the Page Object a lot clearer, as it can refer to an abstraction of the element(s) it is considering instead of dealing with calls to the webdriver which are now hidden away.
So far, so good. The tests work really well in Chrome and Firefox. Problems occur, as ever, when Internet Explorer gets involved. The general advice you should heed when testing with Internet Explorer is to NOT TOUCH ANYTHING while the test is running. IE is effectively an embedded component of Windows and it really doesn't let you forget it. Changing focus to another window could be enough for it to lose its place and invalidate your test run. Further, when the thing being tested uses an HTML IFrame, IE will lose its place after EVERY SINGLE TIME you try to find anything in the DOM. This led to a complete re-write of the browser tests in order to maintain cross-browser compatibility whilst also trying to be robust enough for IE's behaviour.
The test rig HTML IFrame we use for the viewer is the only one on the page. Even with that fact, the following code is necessary to reset which frame Internet Explorer is considering before it attempts to locate an element:
This is utilised by the test code itself before it performs a locate operation:
As you can see from that gist, an element locator function from the Page Object returns something which offers a 'then' function - this is the implementation of the Promise functionality. The 'then' function can take two arguments; the first is a function that will be called if the operation was a success, and the (optional) other will be called in the event of a failure. In this case, there are two functions defined that handle failed operations - one for if the element cannot be located, and the other if the element's 'click' function fails in some way. The success route through the callbacks is indicated by the main flow from left to right - success in locating the element flows to a click which then flows to success in clicking followed by executing the Protractor/Cucumber callback that will announce a pass for this part of the testing scenario.
If I decide to do a refactoring job on this again, I would probably wrap the resetFrame call into the find/findAll functionality. This would mean passing the behaviour needed by the test into a callback function and passing it into the element locator function, frankly a bit like how the calls to resetFrame work now, but transparent to the feature files.
Okay, that's all for now. I wanted to record how to make these tests cross-browser compatible with the use of resetting the frame - this is just in case someone out there finds it useful in the future ... (HI, FUTURE ME!)
Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts
Sunday, 1 February 2015
Monday, 29 July 2013
Bookmarks for 20130729
Well this just pulled me out of a terrible hole ... the dreaded "case folding error" in Mercurial. The following advice worked:
http://mercurial.selenic.com/wiki/FixingCaseCollisions
And this seemed useful...
Failing over from CDN to local storage:
http://www.hanselman.com/blog/CDNsFailButYourScriptsDontHaveToFallbackFromCDNToLocalJQuery.aspx
Twitter Bootstrap has a release candidate for version 3. Not sure how I feel about this yet. On the one hand the new stuff looks amazing, on the other, I'm not sure I like the new grid classes. But, worth a look and it is admirable that they are going for "mobile-first", so rolling the responsive stuff into the main build as default:
http://twitter.github.io/bootstrap
http://mercurial.selenic.com/wiki/FixingCaseCollisions
And this seemed useful...
Failing over from CDN to local storage:
http://www.hanselman.com/blog/CDNsFailButYourScriptsDontHaveToFallbackFromCDNToLocalJQuery.aspx
Twitter Bootstrap has a release candidate for version 3. Not sure how I feel about this yet. On the one hand the new stuff looks amazing, on the other, I'm not sure I like the new grid classes. But, worth a look and it is admirable that they are going for "mobile-first", so rolling the responsive stuff into the main build as default:
http://twitter.github.io/bootstrap
Friday, 24 May 2013
Bookmarks for 20130524
Not dead, merely dreaming.
Some useful stuff from today, which allowed me to make a monitor page showing me all the job processors across 12 different platforms. CSS to scale an iframe:
http://stackoverflow.com/questions/4660659/javascript-css-set-firefox-zoom-level-of-iframe
(bearing in mind that the width and height on the iframe will be scaled as well so it must be multiplied accordingly)
A really bloody simple and non-fussy lightbox for Javascript/JQuery - EasyBox:
https://code.google.com/p/easybox/
A great article from Fleet Street Fox on the Woolwich murder and the EDL. Yes, I know it's on The Mirror's site, but it's truly a good article:
http://www.mirror.co.uk/news/uk-news/edl-dont-defend-england-says-1908599
Some useful stuff from today, which allowed me to make a monitor page showing me all the job processors across 12 different platforms. CSS to scale an iframe:
http://stackoverflow.com/questions/4660659/javascript-css-set-firefox-zoom-level-of-iframe
(bearing in mind that the width and height on the iframe will be scaled as well so it must be multiplied accordingly)
A really bloody simple and non-fussy lightbox for Javascript/JQuery - EasyBox:
https://code.google.com/p/easybox/
A great article from Fleet Street Fox on the Woolwich murder and the EDL. Yes, I know it's on The Mirror's site, but it's truly a good article:
http://www.mirror.co.uk/news/uk-news/edl-dont-defend-england-says-1908599
Labels:
bookmarks,
css,
easybox,
edl,
fleet street fox,
iframe,
javascript,
jquery,
lightbox,
ui,
woolwich
Subscribe to:
Posts (Atom)