yauhen kavaliou andrei palchys “we don’t need qa anymore” or protractor
TRANSCRIPT
Yauhen Kavaliou
Andrei Palchys
“We don’t need QA anymore”or
Protractor
Sencha Touch 2
Cordova
5+ products (phone/tablet & ios/android)
+3 years and 150k LoC
Project
2 small teams
7 developers
5 manual QA
4 automation testers
Team
Many changes every release
Developers produces more code than QA (Manual and Auto) can test in 2 week sprint.
There is a misbalance in maturity between Devs and QA
Experiment
One dev team will develop and cover features with automation tests
Automation tests will be written based on QA tests cases.
Selenium WebDriver
Test WebDriver BrowserAPI
JSON wire protocol
POST /session/12345567890/url{ "url" : "http://rollingscopes.com/" }
ChromeDriver
FirefoxDriver
InternetExplorerDriver
SafariDriver
GhostDriver
Appium
Protractor is an end-to-end test framework for AngularJS JavaScript applications.
describe('rollingscopes.com', function () { it('check meetup name', function () { browser.get('http://rollingscopes.com'); var text = element(by.css('.banner h1')).getText(); expect(text).toEqual('The Rolling Scopes #19'); });});
Protractor provides nice abstraction on top of WebDriver API and uses Jasmine as a test
framework
The WebDriver Control Flow
var text = element(by.css('.banner h1')).getText();expect(text).toEqual('The Rolling Scopes #19');
You write async code in sync way
Google Chrome and ChromeDriver
Jasmine
Suits and Specs
describe( 'Suit Name' , function(){ /*specs*/ })it( 'Spec Name' , function(){ /*expect*/ }, timeout)expect(a).toBe(b)
.not.toBe(b)
.toBeGreaterThan(b)
.toBeLessThan(b)
.toEqual(b)
.toBeDefined()
.toMatch(/\d+/g)…
Approaches
- “Smart” automated tests- User as a config
{login: 'user' ,password: 'password' ,preferences: {
hasAccessToFeatures: false,isAdmin: true,hasAnalytics: false
},navigation: [ 'home' , ‘settings' ]
}
var specs = {
setup: './Base/spec/Setup.js',
…
complete: './Base/spec/Complete.js'
};
module.exports = {
specs: specs,
mandatory: [specs.setup, specs.login],
full: [
specs.setup,
{ name: specs.home, allowed: '*', disabled: ['multipleDeals'] },
specs.settings,
specs.complete
]
}
Page Object
Before
describe(‘angularjs homepage', function() { it('should greet the named user', function() { browser.get('http://www.angularjs.org'); element(by.model('yourName')).sendKeys('Julie'); var greeting = element(by.binding('yourName')); expect(greeting.getText()).toEqual('Hello Julie!'); });});
Afterdescribe('angularjs homepage', function() { it('should greet the named user', function() {
var angularHomepage = new AngularHomepage(); angularHomepage.get(); angularHomepage.setName('Julie');
expect(angularHomepage.getGreeting()).toEqual('Hello Julie!');
Promises
Basecomponentsviewsutilspec
Project1componentsconfigspecviews
Project2componentsconfigspecviews
browser.executeScript(string|Function, args)
browser.executeScriptAsync(string|Function, args)
Utils- WaitFor method based on ExpectedConditions
- Touch interactions and scrolling based on mouseEvents и scriptExecute
- Specific methods for Sencha Touch, for example - scroll to selected Record and e.t.c.
var EC = protractor.ExpectedConditions;
exports.waitFor = function (selector, time) {
return browser.wait(EC.presenceOf(element(by.css(selector))), time || 10000);
}
exports.waitForVisibility = function (selector, time) {
return browser.wait(EC.visibilityOf(element(by.css(selector))), time || 10000);
}
exports.waitForHidden = function (selector, time) {
return browser.wait(EC.invisibilityOf(element(by.css(selector))), time || 10000);
}}
11:06:19.472 INFO - Executing: [find elements: By.cssSelector: .main-container])11:06:19.479 INFO - Done: [find elements: By.cssSelector: .main-container]11:06:19.484 INFO - Executing: [is enabled: 17 [[ChromeDriver: chrome on XP (fb89e8300a09af71aa37b0b5041c8052)] -> css selector: .main-container]])11:06:19.490 INFO - Done: [is enabled: 17 [[ChromeDriver: chrome on XP (fb89e8300a09af71aa37b0b5041c8052)] -> css selector: .main-container]]
...it('App is ready' , function() { //Util.waitFor(this.CSS.container) mainView.waitForLoading();
//browser.isElementPresent(by.css(this.CSS.container)) expect(mainView.isPresent()).toBe(true);
});...
xtype supportby.xtype = function (xtype) {
return {
findElementsOverride: function (driver, using, rootSelector) {
return driver.findElements( by.xpath( '//div[contains(@id,"' + xtype + '")] | //form[contains(@id,"' + xtype + '")]' ), rootSelector);
},
toString: function toString() {
return 'by.xtype("' + xtype + '")';
}
};
};
Timeouts
• { allScriptTimeout : timeout }
• browser.manage().timeouts().implicitlyWait(timeout)
• jasmineNodeOpts.defaultTimeoutInterval = timeout it ('Spec Name', function(){ /*expect*/ }, timeout)
browser.sleep(timeout)
Plugins
- Screenshot reporter - Console- Report…
Issues- Different speed of executing on different environments
- Tough to debug- Why did my test fail?-WebDriver crashes
-DOM manipulations in real-time
- Invisible items
Debug
Node-inspector
Conclusions