Today, we are going to talk about how we do tests at FancyGrid. We have decided not to start from Unit Tests as there are myriad of articles available online which elaborate Unit Testing.
There are numerous approaches out there in Testing world but most and widely used technique is called UI Testing as it is most efficient and useful approach in web development world. Most of us are aware with UI testing, User interface testing, a testing technique used to identify the presence of defects is a product/software under test by using Graphical user interface [GUI].
UI Testing: An Overview
UI Tests are bit different then Unit Tests. UI Tests attempt to subjectively verify that elements on the screen behave (and often look) as expected, both statically (i.e. the flat render) and also dynamically (i.e. as users perform given actions). Unit Tests attempt to isolate small pieces of code and objectively verify application logic.
Selecting the Right Tool
Before you start with UI Testing you need to choose a right tool and there are only few efficient tools out there. Amongst those tools, the most famous is Selenium(WebDriver). Selenium is number one solution for this area. But to be honest it does not suit for us on 100%. We mark this solution on 45% from what we need.
Here is our view of right UI Testing tool:
1 – Variety of DOM events. And sorely Selenium lacks at this point.
2 – The way of automation work. It means recording events automatic.
Selenium is a best way to do the testing, as you need to write hundreds of tests and without this feature you will waste lot’s of precious time.
3 – Elegant API and documentation. Maybe we are too picky but when we worked with Selenium we often viewed sources of tool to get the stuff which we need and how to do it. We are sure that such kind of tool must be good documented.
And accidentally we came across on Siesta.
Siesta
Siesta is product of Bryntum(Swedish IT start-up). Let us quote from official site.
“Siesta is a JavaScript unit testing tool that can help you test any JavaScript code and also perform testing of the DOM and simulate user interactions. The tool can be used together with any type of JavaScript codebase – jQuery, Ext JS, React, Angular etc. Using the API, you can choose from many types of assertions ranging from simple logical JS object comparisons to verifying that an HTML element is visible in the DOM.”
It’s Key Features are exactly what we were searching for.
Features:
* Short learning curve.
* Completely web based, no need to install any extra software.
* Write unit tests in plain JavaScript.
* Record and generate UI test scripts
* Code coverage reports.
* Improves your confidence in your codebase.
* Siesta can be automated using Selenium or PhantomJS.
On the code below usual test for CRUD. Siesta helps to get such code tests in 5 minutes.
```js StartTest(function(t){ t.diag('Testing CRUD'); var grid = new FancyGrid({ renderTo: 'container', title: 'CRUD', width: 700, height: 400, theme: 'blue', trackOver: true, selModel: 'rows', data: { proxy: { api: { create: '/siesta/server/new.php', read: '/siesta/server/load.php', update: '/siesta/server/update.php', destroy: '/siesta/server/destroy_action.php' } } }, defaults: { type: 'string', width: 100, editable: true, sortable: true, resizable: true, ellipsis: true }, paging: true, tbar: [{ type: 'button', text: 'Add', action: 'add' },{ type: 'button', text: 'Delete', action: 'remove' }], columns: [{ index: 'id', locked: true, title: 'ID', type: 'number', width: 40, editable: false, resizable: false },{ index: 'company', locked: true, title: 'Company' },{ index: 'name', title: 'Name' },{ index: 'surname', title: 'Sur Name' },{ index: 'age', width: 60, title: 'Age', type: 'number' },{ type: 'action', width: 65, items: [{ text: 'Delete', cls: 'action-column-remove', action: 'remove' }] },{ index: 'position', locked: true, title: 'Position', width: 150 }], events: [{ init: function(){ t.diag('Grid Rendered'); var data = grid.get(0).data; t.ok(data.id === 1, 'First item id is 1'); t.describe("Sort DESC by id", function(t){ t.chain( { click : "#fancy-grid-1 .fancy-grid-header-cell-text:textEquals(ID)" }, { click : "#fancy-grid-1 .fancy-grid-column-sort-ASC .fancy-grid-header-cell-text" }, {waitFor: 1000}, function(){ var data = grid.get(0).data; t.ok(data.id === 22, 'First item id is 22'); } ); }); t.describe("Edit company at id 21", function(t){ t.chain( { dblclick : "#fancy-grid-1 .fancy-grid-left .fancy-grid-column[index=1] .fancy-grid-cell[index=1]" }, { type : "[BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE][BACKSPACE]", target : "#fancy-gen-30 .fancy-field-text-input" }, { type : "I", target : "#fancy-gen-30 .fancy-field-text-input", options : { shiftKey : true } }, { type : "ntel[RETURN]", target : "#fancy-gen-30 .fancy-field-text-input" }, {waitFor: 1000}, function(){ var data2 = grid.get(1).data; t.ok(data2.company === 'Intel', 'Second item company is Intel'); } ); }); t.describe("Go to last and sort ASC by id", function(t){ t.chain( { click : "#fancy-gen-13 .fancy-paging-next" }, { click : "#fancy-grid-1 .fancy-grid-column-sort-DESC .fancy-grid-header-cell-text" }, function(){ var dataId21 = grid.getById('21').data; t.ok(dataId21.company === 'Intel', 'Company value with id 21 is Intel'); t.ok( grid.el.select('.fancy-grid-cell-dirty').length === 0, 'Dirty cells number is 0'); } ); }); t.describe("Edit age of item with id 17", function(t){ t.chain( { dblclick : "#fancy-grid-1 .fancy-grid-center .fancy-grid-column[index=2] .fancy-grid-cell[index=3]" }, { type : "[BACKSPACE]0[RETURN]", target : "#fancy-gen-31 .fancy-field-text-input" }, {waitFor: 1000} ); }); t.describe("Go to first page and sort by age", function(t){ t.chain( { click : "#fancy-gen-13 .fancy-paging-first" }, { click : "#fancy-grid-1 .fancy-grid-center .fancy-grid-header-cell[index=2]", offset : [23, 8] }, {waitFor: 1000}, function(){ var dataId16 = grid.getById('16').data; t.ok(dataId16.age === 20, 'Age value of item with id 16 is 20'); } ); }); t.describe("Delete item with id 4", function(t){ t.chain( { click : "#fancy-grid-1 .fancy-grid-center .fancy-grid-column[index=3] .fancy-grid-cell[index=0] .action-column-remove" }, { click : "#fancy-grid-1 .fancy-grid-left .fancy-grid-header-cell[index=0]" }, {waitFor: 1000}, function(){ var data4 = grid.get(3).data; t.ok(data4.id === 7, 'Item id on 4-th position is 7'); } ); }); t.describe("Delete item with id 9", function(t){ t.chain( { click : "#fancy-grid-1 .fancy-grid-cell-inner:textEquals(Pro bugs)" }, { click : "#fancy-gen-13 .fancy-button-text:textEquals(Delete)" }, {waitFor: 500}, { click : "#fancy-gen-13 .fancy-paging-last" }, { click : "#fancy-grid-1 .fancy-grid-column-sort-ASC .fancy-grid-header-cell-container", offset : [6, 6] }, {waitFor: 1000}, function(){ var data4 = grid.get(3).data; t.ok(data4.id === 8, 'Item id on 4-th position is 8'); } ); }); t.describe("Delete item with id 11", function(t){ t.chain( { click : "#fancy-grid-1 .fancy-grid-column:nth-of-type(2) :nth-of-type(2)", offset : [49, 3] }, { click : "#fancy-gen-13 .fancy-button-text:textEquals(Delete)" }, {waitFor: 500}, { click : "#fancy-gen-13 .fancy-paging-first" }, { click : "#fancy-grid-1 .fancy-grid-column-sort-DESC .fancy-grid-header-cell-text" }, {waitFor: 1000}, function(){ var data7 = grid.get(6).data; t.ok(data7.id === 12, 'Item id on 7-th position is 12'); } ); }); t.describe("Add new at last page and fill in", function(t){ t.chain( { click : "#fancy-gen-13 .fancy-paging-last" }, { click : "#fancy-gen-13 .fancy-button-text:textEquals(Add)" }, {waitFor: 1000}, { dblclick : "#fancy-grid-1 .fancy-grid-column:nth-of-type(2) .fancy-grid-cell:nth-of-type(1) .fancy-grid-cell-inner" }, { type : "F", target : "#fancy-gen-30 .fancy-field-text-input", options : { shiftKey : true } }, { type : "ancy", target : "#fancy-gen-30 .fancy-field-text-input" }, { type : "G", target : "#fancy-gen-30 .fancy-field-text-input", options : { shiftKey : true } }, { type : "rid[RETURN]", target : "#fancy-gen-30 .fancy-field-text-input" }, { mousedown : "#fancy-grid-1 .fancy-grid-column:nth-of-type(3) .fancy-grid-cell:nth-of-type(1) .fancy-grid-cell-inner", offset : [7,2] }, { dblclick : [194,132] }, { type : "O", target : "#fancy-gen-33 .fancy-field-text-input", options : { shiftKey : true } }, { type : "wner", target : "#fancy-gen-33 .fancy-field-text-input" }, { mousedown : "#fancy-grid-1 .fancy-grid-column:nth-of-type(4) .fancy-grid-cell:nth-of-type(1)", offset : [18,7] }, { dblclick : [346,128] }, { type : "N", target : "#fancy-gen-34 .fancy-field-text-input", options : { shiftKey : true } }, { type : "ick", target : "#fancy-gen-34 .fancy-field-text-input" }, { dblclick : "#fancy-grid-1 .fancy-grid-column:nth-of-type(5) .fancy-grid-cell:nth-of-type(1) .fancy-grid-cell-inner" }, { type : "T", target : "#fancy-gen-35 .fancy-field-text-input", options : { shiftKey : true } }, { type : "homson", target : "#fancy-gen-35 .fancy-field-text-input" }, { mousedown : "#fancy-grid-1 .fancy-grid-column:nth-of-type(6) .fancy-grid-cell:nth-of-type(1) .fancy-grid-cell-inner", offset : [28,8] }, { dblclick : [565,138] }, { type : "38[BACKSPACE][BACKSPACE]41[RETURN]", target : "#fancy-gen-31 .fancy-field-text-input" }, { mousedown : "#fancy-gen-13 .fancy-paging-first", offset : [17,4] }, { mouseup : [70,385] }, { mousedown : "#fancy-grid-1 .fancy-grid-column-sort-ASC .fancy-grid-header-cell-text", offset : [3,0] }, { mouseup : [49,101] }, {waitFor: 1000}, function(){ var data = grid.get(0).data; t.ok(data.id == 23 && data.company === 'FancyGrid' && data.position === 'Owner' && data.name === 'Nick' && data.surname === 'Thomson' && data.age == 41, 'Item added right - Nick Thomson at FancyGrid as Owner, age - 41'); } ); }); } }] }); t.waitFor(1000); }); ```
Summary:
This article is fast overview on UI Testing issue. UI Testing is very efficient approach that helps to increase stability on product in several times. This is the main motto to share this article with audience. And the best tool for Enterprise both UI and Unit Tests is Siesta of Bryntum. Read More about UI Testing here.