after a while developing my first Servoy application I thought it may be a good idea to include some unit testing. Unfortunately I found nearly no documentation about this in the forum/web. So I have a few question about the issue of unit tests in Servoy.
First I want to explain what I’ve done so far.
I created a new Solution and included the solution which has to be tested as a module (found this at this thread viewtopic.php?f=22&t=13962)
in the testing solution I created a few dummy forms to structure my test and added to each form a script file in which i wrote my tests
the script files of each form contains methods like function setUp() {…} and function testAddProduct() { …}
i was already able to test the login & authentication methods.
So now my problems:
As an example for the testAddProduct function I want do something like:
//safe record count before
var before = databaseManager.getFoundSetCount(forms.frmProducts.foundset);
forms.frmMain.onClickbtnAdd();
//check if it is really editable
jsunit.assertTrue(forms.frmProducts.elements.fld_product.editable == true)
jsunit.assertTrue(forms.frmProducts.elements.fld_product.readOnly == false)
//add new record
// not working !!!
forms.frmProducts.elements.fld_product= "Test_Inventar";
//working
forms.frmProducts.product= "Test_Inventar";
// not working !!!
forms.frmProducts.elements.fld_product_categorie= "DVD";
//working
forms.frmProducts.product_categorie = 1
//press save button
forms.frmProducts.onClickbtnSave()
jsunit.assertEquals(before + 1, databaseManager.getFoundSetCount(forms.frmProducts.foundset))
So I want to directly fill the field (all having a name starting fld_) instead of using the direct datavalues of the form - but I didn’t find a solution how to do this. At the first moment the difference between filling the dataprovider and filling the field seems to be needless. But first of all I want to ensure the correct association of each field with the corresponding dataprovider and second I also want to test the assigned Valuelist of each field if they are correct. As shown in the example above I want to simulate the entering of DVD instead of using the releated value 1.
Another problem is that i didn’t find an opportunity to handle events like plugins.dialogs.showErrorDialog (…) or plugins.dialogs.showInputDialog (…) inside the unit tests.
schoby:
Another problem is that i didn’t find an opportunity to handle events like plugins.dialogs.showErrorDialog (…) or plugins.dialogs.showInputDialog (…) inside the unit tests.
Unit test are ran by kind of headless client, and therefore it doesn’t support UI stuff.
(...)
the last thing I want to ask if there is a possibility/workaound/utility to collect data like some code coverage tools do (e.g. <a class="postlink" href="http://www.eclemma.org">http://www.eclemma.org</a> or <a class="postlink" href="http://cobertura.sourceforge.net/">http://cobertura.sourceforge.net/</a> )
You can’t currently get such code coverage data.
About forms.frmProducts.elements.fld_product: it refers to the field object (with methods/properties - see auto complete/solution explorer for that field), not to the field content. So you cannot change content this way. On some field types (such as text field) you can do something like this:
mboegem:
Unit test are ran by kind of headless client, and therefore it doesn’t support UI stuff.
The tests are run in a kind of smart client actually, but you still can’t do things like opening modal dialogs that expect user interaction to close (in fact you can, but I don’t think you want you unit tests to require user interaction). What you can do is open/close dialogs/windows that you are able to close afterwards from code. For example you can open a named non-modal user dialog, do things in it then close it via script, or even a modal one if before you open it you schedule a task that will eventually close it. The main idea is to avoid getting the tests hanged by operations such as opening a modal input window that will never close.
You can use controller.setDataProviderValue(dataProviderID, value) and elements.elementName.getDataProviderID() in your unit tests as well and solution model stuff for valuelists, but that wont exactly help simulating UI interaction. There is also a java AWT class called Robot that can be used to simulate a number of UI inputs that you could use in a Servoy plugin and inside unit tests, but still it will only get you so far… For UI interaction there are other dedicated testing tools.
schoby:
So I want to directly fill the field (all having a name starting fld_) instead of using the direct datavalues of the form - but I didn’t find a solution how to do this. At the first moment the difference between filling the dataprovider and filling the field seems to be needless. But first of all I want to ensure the correct association of each field with the corresponding dataprovider and second I also want to test the assigned Valuelist of each field if they are correct. As shown in the example above I want to simulate the entering of DVD instead of using the releated value 1.
for everybody who is interested. I was able to solve the problems with the valuelist by using the following global function:
function getValueList(listname, viewvalue) {
var ds = application.getValueListItems(listname);
for (var i = 1; i <= ds.getMaxRowIndex(); i++) {
if (ds.getValue(i, 1) == viewvalue)
return ds.getValue(i, 2);
}
//at this point we didn't find the value in the list - fail test
jsunit.fail("Didn't find " + viewvalue + " in Valuelist " + listname);
}
And in my test cases I use it in the following way:
By the way, has anybody ever tried to get a code coverage? I have seen a tool called JSCoverage (JSCoverage - code coverage for JavaScript), but till now I was not able to use it with servoy…