KEMBAR78
UI Testing Best Practices - An Expected Journey | PDF
UI Testing
An unexpected Journey
Oren Farhi
JS Engineer (2006)
JS Group Leader @Tikal
Speaker (Israel & World Wide)
github.com/orizens
orizens.com
JSes6
B
Outline
1. What is UI testing
2. Why Should I Test UI
3. Hands On & Best Practices Patterns
a. Unit Testing
b. End To End Tests (E2E)
Demo App: Echoes Player
http://echotu.be (available as a chrome app)
github.com/orizens/echoes/tree/angular
What is UI Testing
perspective
UI Testing - Who Should Give a $#%&?
developer product end user qa / testers
Why Should I Test UI?
Why ?
In The Past...
1. Getting Requirements
2. Started writing code
3. now the cycle begins:
Save Code
Go To Browser & Refresh
Open Debugger
Automating The Debug Process
1. Add some “watches”
2. Add some “truthy” watches
3. Refresh
4. Try some other input
5. Repeat the “clicks”, “enter”, “keys” in
input
6. Refresh...
debugging, checking and repeating this process each time makes me go: ‘ahhhh’
I Should Write Test For UI
Because:
4 reasons
We’ve been doing that from the
beginning (maybe not with code)
Absence of Human Testers For Every Step
Automate the Dev & Tests Process
“Can You Make Sure Everything works?”
A UI Test = expecting something to be
What do we check anyway?
1. I expect something to be with a value
2. I expect something to be visible on the
DOM
3. I expect that click will change the search
4. I expect that a right click will show a
context menu, with user permissions
visible
5. I expect “<grid model=”items”>” to
render a data table in the DOM
Tools For Testing JS
Jasmine, Karma, phantom
What Is Jasmine.js
bdd js testing framework for testing js
Jasmine.js
by Pivotal
it’s a Standalone
BDD framework
for testing JS code
available on
github
1. Suites - describe()
2. Specs - it()
3. Expectations - expect()
4. Matchers - .not/.toBe()
● Spies
● Stubs
● Async
● skip tests - xit, xdescribe
Jasmine Syntax - BDD Style
describe('Gandalf the Gray', function () {
it("should stop balrog passing the bridge", function() {});
it("should save the hobbits when in danger", function() {});
})
What Is Karma Test Runner
automate: running tests, ci (jenkins, teamcity..),
multiple browsers, by angularjs team
Phantom.js - Headless Webkit
scriptable browser: includes js, DOM, routing etc..
Showtime 1 - Dropdown
testing dropdown directive in angular
Testing a Bootstrap Dropdown
<e-dropdown label="Preset"
items="presets"
on-select="onPresetChange(item)"
icon="tag"
></e-dropdown>
HTML - container rendered
it('should render a dropdown element', function () {
expect(element.hasClass('dropdown')).toBeTruthy();
});
<e-dropdown label="Preset"
items="presets"
on-select="onPresetChange(item)"
icon="tag"
></e-dropdown>
HTML - items rendered
it("should render items if given presets", function() {
expect(
element.find('ul li').length)
.toBe(
scope.presets.length
);
});
<e-dropdown label="Preset"
items="presets"
on-select="onPresetChange(item)"
icon="tag"
></e-dropdown>
HTML - Content is rendered
it("should render the label according to the 'label' attribute",
function() {
expect(
element.find('.dropdown-toggle').text().trim())
.toBe('Preset')
});
<e-dropdown label="Preset"
items="presets"
on-select="onPresetChange(item)"
icon="tag"
></e-dropdown>
Functionality - function called on clicked
it("should call a function when select has changed",function() {
spyOn(scope, 'onPresetChange');
element.isolateScope().handleClick(scope.presets[0]);
expect(scope.onPresetChange).toHaveBeenCalled();
});
<e-dropdown label="Preset"
items="presets"
on-select="onPresetChange(item)"
icon="tag"
></e-dropdown>
Functionality using Spy - click
it("should call a function with the selected item when select
has changed", function() {
spyOn(scope, 'onPresetChange');
element.isolateScope().handleClick(scope.presets[0]);
expect(scope.onPresetChange).toHaveBeenCalledWith(scope.presets
[0]);
});
<e-dropdown label="Preset"
items="presets"
on-select="onPresetChange(item)"
icon="tag"
></e-dropdown>
Showtime #2 - Testing Ajax
mocks and stubs using angularjs services
Preparing Mocks
var mockData = window.mocks[‘video.items.mock’];
var url = /.+search.*/
karma-json-fixtures-preprocessor
add to json paths to configuration of:
files: [ '../tests/mocks/**/*mock.json' ]
preprocessor: {
'../tests/mocks/**/*mock.json': ['json_fixtures']
}
Functionality using Spy and Fake
it("set the feed type when changed in YoutubeSearch and perform
search", function(){
httpBackend.whenGET(url).respond(mockData);
spyOn(scope, 'searchYoutube').and.returnValue('done')
spyOn(YoutubeSearchSrv, 'setType').and.callFake(function(){
return 'set';
});
rootScope.$broadcast('feed-type-changed', 'playlist');
scope.$digest();
expect(YoutubeSearchSrv.setType).toHaveBeenCalled();
expect(YoutubeSearchSrv.setType.calls.count()).toEqual(1);
expect(scope.searchYoutube).toHaveBeenCalled();
expect(scope.searchYoutube.calls.count()).toEqual(1);
})
Testing Ajax
stubs & mocks
Mocking Ajax Call
describe("Media Info :", function() {...})
it("should update the video's title when video has changed",
function() {
var video = mockMediaInfoItems.items[0];
httpBackend.whenGET(/.+videos.*/).respond(mockMediaInfo);
YoutubePlayerSettings.playVideoId(video);
scope.$apply();
expect(scope.vm.video.title).toEqual(video.snippet.title);
});
End to End Testing (E2E)
towards the rest of the world
What is E2E
tests few pieces together
regarding ui:
web ui = > rest of the world
E2E for JS
for angular.js
JS syntax
all browsers
for any js app
Gherkin syntax
all browsers
E2E with Pioneer.js
Feature: Simple Feature
Background:
Given I visit Echoes Player
Scenario: Entering Information
When I search for "alice in chains live"
Then I should see 50 results
PioneerJS “When” Example
this.When(/^I search for "([^"]*)"$/, function(value){
var MediaSearch = this.Widget.extend({
root: "#media-search",
setSearchQuery: function (val) {
return this.fill(val);
}
})
var search = new MediaSearch();
return this.driver.sleep(10000).then(function(){
search.sendKeys('', Driver.Key.ENTER).then(function(){
search.setSearchQuery(value);
return search.sendKeys(Driver.Key.ENTER);
});
});
});
So - What are the benefits?
Show me the money
What is Good with UI Unit Testing
● Adding Features won’t break code’s
behaviour
● promotes writing modular logics
● Forces writing high quality code -
decoupling
● documentation - code intention &
functional behavior
The End
Q & A

UI Testing Best Practices - An Expected Journey

  • 1.
  • 2.
    Oren Farhi JS Engineer(2006) JS Group Leader @Tikal Speaker (Israel & World Wide) github.com/orizens orizens.com JSes6 B
  • 3.
    Outline 1. What isUI testing 2. Why Should I Test UI 3. Hands On & Best Practices Patterns a. Unit Testing b. End To End Tests (E2E)
  • 4.
    Demo App: EchoesPlayer http://echotu.be (available as a chrome app) github.com/orizens/echoes/tree/angular
  • 5.
    What is UITesting perspective
  • 6.
    UI Testing -Who Should Give a $#%&? developer product end user qa / testers
  • 7.
    Why Should ITest UI? Why ?
  • 8.
    In The Past... 1.Getting Requirements 2. Started writing code 3. now the cycle begins:
  • 9.
  • 10.
    Go To Browser& Refresh
  • 11.
  • 12.
    Automating The DebugProcess 1. Add some “watches” 2. Add some “truthy” watches 3. Refresh 4. Try some other input 5. Repeat the “clicks”, “enter”, “keys” in input 6. Refresh...
  • 13.
    debugging, checking andrepeating this process each time makes me go: ‘ahhhh’
  • 14.
    I Should WriteTest For UI Because: 4 reasons
  • 15.
    We’ve been doingthat from the beginning (maybe not with code)
  • 16.
    Absence of HumanTesters For Every Step
  • 17.
    Automate the Dev& Tests Process
  • 18.
    “Can You MakeSure Everything works?”
  • 19.
    A UI Test= expecting something to be What do we check anyway? 1. I expect something to be with a value 2. I expect something to be visible on the DOM 3. I expect that click will change the search 4. I expect that a right click will show a context menu, with user permissions visible 5. I expect “<grid model=”items”>” to render a data table in the DOM
  • 20.
    Tools For TestingJS Jasmine, Karma, phantom
  • 21.
    What Is Jasmine.js bddjs testing framework for testing js
  • 22.
    Jasmine.js by Pivotal it’s aStandalone BDD framework for testing JS code available on github 1. Suites - describe() 2. Specs - it() 3. Expectations - expect() 4. Matchers - .not/.toBe() ● Spies ● Stubs ● Async ● skip tests - xit, xdescribe
  • 23.
    Jasmine Syntax -BDD Style describe('Gandalf the Gray', function () { it("should stop balrog passing the bridge", function() {}); it("should save the hobbits when in danger", function() {}); })
  • 24.
    What Is KarmaTest Runner automate: running tests, ci (jenkins, teamcity..), multiple browsers, by angularjs team
  • 25.
    Phantom.js - HeadlessWebkit scriptable browser: includes js, DOM, routing etc..
  • 26.
    Showtime 1 -Dropdown testing dropdown directive in angular
  • 27.
    Testing a BootstrapDropdown <e-dropdown label="Preset" items="presets" on-select="onPresetChange(item)" icon="tag" ></e-dropdown>
  • 28.
    HTML - containerrendered it('should render a dropdown element', function () { expect(element.hasClass('dropdown')).toBeTruthy(); }); <e-dropdown label="Preset" items="presets" on-select="onPresetChange(item)" icon="tag" ></e-dropdown>
  • 29.
    HTML - itemsrendered it("should render items if given presets", function() { expect( element.find('ul li').length) .toBe( scope.presets.length ); }); <e-dropdown label="Preset" items="presets" on-select="onPresetChange(item)" icon="tag" ></e-dropdown>
  • 30.
    HTML - Contentis rendered it("should render the label according to the 'label' attribute", function() { expect( element.find('.dropdown-toggle').text().trim()) .toBe('Preset') }); <e-dropdown label="Preset" items="presets" on-select="onPresetChange(item)" icon="tag" ></e-dropdown>
  • 31.
    Functionality - functioncalled on clicked it("should call a function when select has changed",function() { spyOn(scope, 'onPresetChange'); element.isolateScope().handleClick(scope.presets[0]); expect(scope.onPresetChange).toHaveBeenCalled(); }); <e-dropdown label="Preset" items="presets" on-select="onPresetChange(item)" icon="tag" ></e-dropdown>
  • 32.
    Functionality using Spy- click it("should call a function with the selected item when select has changed", function() { spyOn(scope, 'onPresetChange'); element.isolateScope().handleClick(scope.presets[0]); expect(scope.onPresetChange).toHaveBeenCalledWith(scope.presets [0]); }); <e-dropdown label="Preset" items="presets" on-select="onPresetChange(item)" icon="tag" ></e-dropdown>
  • 33.
    Showtime #2 -Testing Ajax mocks and stubs using angularjs services
  • 34.
    Preparing Mocks var mockData= window.mocks[‘video.items.mock’]; var url = /.+search.*/ karma-json-fixtures-preprocessor add to json paths to configuration of: files: [ '../tests/mocks/**/*mock.json' ] preprocessor: { '../tests/mocks/**/*mock.json': ['json_fixtures'] }
  • 35.
    Functionality using Spyand Fake it("set the feed type when changed in YoutubeSearch and perform search", function(){ httpBackend.whenGET(url).respond(mockData); spyOn(scope, 'searchYoutube').and.returnValue('done') spyOn(YoutubeSearchSrv, 'setType').and.callFake(function(){ return 'set'; }); rootScope.$broadcast('feed-type-changed', 'playlist'); scope.$digest(); expect(YoutubeSearchSrv.setType).toHaveBeenCalled(); expect(YoutubeSearchSrv.setType.calls.count()).toEqual(1); expect(scope.searchYoutube).toHaveBeenCalled(); expect(scope.searchYoutube.calls.count()).toEqual(1); })
  • 36.
  • 37.
    Mocking Ajax Call describe("MediaInfo :", function() {...}) it("should update the video's title when video has changed", function() { var video = mockMediaInfoItems.items[0]; httpBackend.whenGET(/.+videos.*/).respond(mockMediaInfo); YoutubePlayerSettings.playVideoId(video); scope.$apply(); expect(scope.vm.video.title).toEqual(video.snippet.title); });
  • 38.
    End to EndTesting (E2E) towards the rest of the world
  • 39.
    What is E2E testsfew pieces together regarding ui: web ui = > rest of the world
  • 40.
    E2E for JS forangular.js JS syntax all browsers for any js app Gherkin syntax all browsers
  • 41.
    E2E with Pioneer.js Feature:Simple Feature Background: Given I visit Echoes Player Scenario: Entering Information When I search for "alice in chains live" Then I should see 50 results
  • 42.
    PioneerJS “When” Example this.When(/^Isearch for "([^"]*)"$/, function(value){ var MediaSearch = this.Widget.extend({ root: "#media-search", setSearchQuery: function (val) { return this.fill(val); } }) var search = new MediaSearch(); return this.driver.sleep(10000).then(function(){ search.sendKeys('', Driver.Key.ENTER).then(function(){ search.setSearchQuery(value); return search.sendKeys(Driver.Key.ENTER); }); }); });
  • 43.
    So - Whatare the benefits? Show me the money
  • 44.
    What is Goodwith UI Unit Testing ● Adding Features won’t break code’s behaviour ● promotes writing modular logics ● Forces writing high quality code - decoupling ● documentation - code intention & functional behavior
  • 45.