
This blog post covers test driven development (TDD) for SAPUI5 Controls by means of QUnit. It focuses on testing of animated UI control with interaction build with third party library.
For more details concerning TDD please see following blog post engineering-in-javascript.
A SAPUI5 Control is “… an object that defines the appearance and behavior of a screen area” (wiki). In general SAPUI5 provides a lot of controls for building an application.
You can create your own control in case of standard controls cannot meet your requirements. You can extend an existing standard control or you create your own. This blog post focuses on creating a new control.
The main challenge in our example is animation. Each time our donut chart is drawed an animation is triggered that takes about one second until the chart is rendered completely. This happens during startup but also when an update is triggered. What if we need to check the total number of wedges rendered in the
Document Object Model (DOM) but the animation takes some time to come to an end? One short-term solution is to start the test until everything is rendered
(Listing 1). In the following code snippet our donut chart is initialized outside the QUnit module.
Listing 1 (Delayed test unit):
var oDonutChart = new sap.hpa.grcaud.chart.DonutChart({
id: "donut"
});
oDonutChart.placeAt("content");
module("Donut Chart is initialized", {
setup : function() {
},
teardown : function() {
}
});
test("shall create one wedge", function() {
var iNumberOfWedge = oDonutChart.getNumberOfWedge();
equal(iNumberOfWedge, 1, "wedge number is wrong");
});
Unfortunately all furthermore tests need to work with same donut chart instance. Moreover global variables should be avoided. Therefore a better solution is to setup and teardown the donut chart in the module.
In listing 2 the instantiation and destruction of the donut chart moved to the module. In addition we need to make sure there is some timeout logic to draw the wedges (including animation) otherwise our test will fail. Without delay donut chart is not rendered completely.
Listing 2 (Timeout during module setup):
File: DonutChart.qunit.html
module("Donut Chart is initialized", {
setup : function() {
this.oDonutChart = new sap.hpa.grcaud.chart.DonutChart();
this.oDonutChart.placeAt("content");
stop();
setTimeout(function() {
start();
}, 1000);
},
teardown : function() {
this.oDonutChart.destroy();
this.oDonutChart = null;
}
});
test("shall create one wedge", function() {
var iNumberOfWedge = this.oDonutChart.getNumberOfWedge();
equal(iNumberOfWedge, 1, "wedge number is wrong");
});
. . .
File: DonutChart.js
getNumberOfWedge : function() {
var iWedge = jQuery(".sapHpaGrcaudFindingTileChart-part").length;
return iWedge;
}
Unfortunately this delay is inaccurate and could break when animation duration changes. As a consequence our test needs to wait until the donut chart rendering has finished. Listing 3 enforces an immediate update of the donut chart (SAPUI5 Wiki) by means of SAPUI5 sap.ui.getCore().applyChanges() function. It will cause the donut chart to render completely without any animation.
Please see attachments for final source code of DonutChart.js and DonutChart.qunit.html.
Listing 3 (Usage of apply changes):
File: DonutChart.qunit.html
module("Donut Chart is initialized", {
setup : function() {
this.oDonutChart = new sap.hpa.grcaud.chart.DonutChart();
this.oDonutChart.placeAt("content");
sap.ui.getCore().applyChanges();
},
teardown : function() {
this.oDonutChart.destroy();
this.oDonutChart = null;
}
});
test("shall create one wedge", function() {
var iNumberOfWedge = this.oDonutChart.getNumberOfWedge();
equal(iNumberOfWedge, 1, "wedge number is wrong");
});
A secondary challenge is interaction. Our donut chart does support following interactions:
When clicking or moving the mouse over a wedge the corresponding text (e.g. Wedge 1) and count (e.g. 1) is received via event (listing 4). Before we can test the result it is necessary to trigger the appropriate event. Due to the fact that we are using Scalable Vector Graphics (SVG) with D3.js this is done by means of a native browser event e.g. click. The corresponding SAPUI5 event trigger function sap.ui.test.qunit.triggerEvent() cannot be used because “there is no event handler attached using jQuery´s event system that corresponds to these events” (jQuery). Instead we create a new native event and dispatch it on the corresponding wedge. This also applies to move mouse over wedge and move mouse out of wedge tests.
Listing 4 (Interaction):
module("Donut Chart is created with five wedges", {
setup : function() {
this.sWedge1Text = "";
this.sWedge1Count = "";
. . .
this.oDonutChart = new sap.hpa.grcaud.chart.DonutChart({
wedges : [new sap.hpa.grcaud.chart.DonutChartWedge({
text : "Wedge 1",
count : 1
}), …
. . .
selected : [function(oEvent) {
this.sWedge1Text = oEvent.getParameter("text");
this.sWedge1Count = oEvent.getParameter("count");
}, this]
. . .
});
. . .
},
clickOnWedge1 : function() {
this.triggerEventOnWedge1("click");
},
. . .
triggerEventOnWedge1: function(sEventType){
var oEvent = new Event(sEventType);
var oWedge1 = this.getWedge1();
oWedge1.dispatchEvent(oEvent);
},
getWedge1: function(){
return jQuery(".sapHpaGrcaudFindingTileChart-part")[0];
}
});
. . .
test("when user clicks on wedge 1 then receive information for wedge 1",
function() {
this.clickOnWedge1();
equal(this.sWedge1Text, "Wedge 1", "wedge 1 text wrong");
equal(this.sWedge1Count, "1", "wedge 1 count wrong");
});
. . .
});
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
16 | |
12 | |
11 | |
9 | |
8 | |
8 | |
8 | |
8 | |
7 | |
6 |