Banana.Test
The Banana.Test class is used to run unit tests of Banana Extensions.
See also working with the Banana Extensions Test Framework.
Banana Extensiong TestFramework
The Banana Extensions Test Framework is like an usual Unit Test Framework.
Two methodologies are available:
- Verify results
Through assert methods the user can verify some conditions, in case that a condition didn't meet the test fail and it is interrupted.
For example you verify that a method returns a determined value.
Ex.: Test.assertIsEqual(totalVatAmount(), "5000.00");
- Log results and compare them with previous results (expected results)
Through the Banana.Test.Logger methods, you can log test results. Test results are stored under the test/testresults folder. They will be compared at the end of the test with the expected results stored under the folder test/testexpected (results form previous tests), if any difference is found, the test is marked as failed and the differences showed to the user.
In this case you don't care about the exact value returned by a method, but you verify that the method returns the same value across different versions of the BananaApp or Banana Accounting.
Ex.: Test.logger.addKeyValue("Total VAT amount", totalVatAmount());
Create a test case
To create a test case look at the example SampleExtensions/TestFramework.
Run a test case
You can run a test case in two ways (both available starting at Banana Accounting 9.0.4):
- Through the Manage Apps dialog
- Open the Manage Apps dialog
- Select the Banana Extension to test
- Click over 'Show details'
- Click on the button 'Run test case'
- Through the Command line
- banana90.exe -cmd=runtestsapps -p1=path_to_testcase.js|folder
- As parameter p1 you can specify the path to a test case file, or the path of a folder
- In case of a folder all files in the folder and subfolders ending with test.js are run
Test case folder structure
This is the default test structure of a test case. All the files used for the test case are stored in a folder named test.
In the dialog Manage apps the button 'Run test case' button is showed only if the application find a file named test/<same_name_bananaextemsopm>.test.js.
ch.banana.script.bananaapp.js # BananaApps
ch.banana.script.bananaapp2.js
...
test/
ch.banana.script.bananaapp.test.js # BananaApps Test Cases
ch.banana.script.bananaapp2.test.js
...
testcases/
*.ac2 # ac2 files for the test cases
...
testexpected/ # Expected test results used for verifying the current results
ch.banana.script.bananaapp.test/
*.txt
ch.banana.script.bananaapp2.test/
*.txt
...
testresults/ # Current test results
ch.banana.script.bananaapp.test/
*.txt
ch.banana.script.bananaapp2.test/
*.txt
...
Logger output format
The results are saved in .txt with the Latex format. Yes, it means that you can convert the output files in pdf, and look at the results without the log structure commands.
Short example
For a complete example look a SampleExtensions/TestFramework.
// @id = ch.banana.script.bananaapp.test
// @api = 1.0
// @pubdate = 2018-03-30
// @publisher = Banana.ch SA
// @description = Simple test case
// @task = app.command
// @doctype = *.*
// @docproperties =
// @outputformat = none
// @inputdataform = none
// @timeout = -1
// Register test case to be executed
Test.registerTestCase(new TestLoggerSimpleExample());
// Here we define the class, the name of the class is not important
function TestLoggerSimpleExample() {
}
// Test method, every method starting with 'test' will be automatically executed
TestLoggerSimpleExample.prototype.testOk = function() {
Test.logger.addText("This test will pass :-)");
Test.assert(true);
}
The Test object
When a script is run as a test case, a global object named Test is exposed to the script. This object defines properties and methods for executing the test case.
Test.logger.addKeyValue("count", 4);
Test.assert(true);
Properties
logger
The property logger returns an object of type Banana.Test.Logger that permits to log test results. If the script is not run though the Banana Apps functionality this object is null.
var testLogger = Test.logger;
testLogger.addKeyValue("count", 4);
Methods
assert(condition, message)
This method verifies if the condition is true. If the condition is true the test continues, else an exception is thrown and the message message is inserted in the test results.
Test.assert(true, "This test will pass");
assertEndsWidth(string, endString)
This method verifies if text string ends with the text endString. If the condition is true the test continues, else an exception is thrown and a fatal error is inserted in the test results.
Test.assertEndsWith("This string ends with the text", "the text");
assertIsEqual(actual, expected)
This method verifies if actual equal to expected. If the condition is true the test continues, else an exception is thrown and a fatal error is inserted in the test results.
Test.assertIsEqual("Those strings are equal", "Those strings are equal");
assertGreaterThan(actual, expected)
This method verifies if actual is greather than expected. If the condition is true the test continues, else an exception is thrown and a fatal error is inserted in the test results.
Test.assertGreaterThan(10, 8);
assertGreaterThanOrEqual(actual, expected)
This method verifies if actual is greather than or equal to expected. If the condition is true the test continues, else an exception is thrown and a fatal error is inserted in the test results.
Test.assertGreaterThanOrEqual(8, 8);
assertLessThan(actual, expected)
This method verifies if actual less than expected. If the condition is true the test continues, else an exception is thrown and a fatal error is inserted in the test results.
Test.assertLessThan(8, 10);
assertLessThanOrEqual(actual, expected)
This method verifies if actual less than or equal to expected. If the condition is true the test continues, else an exception is thrown and a fatal error is inserted in the test results.
Test.assertLessThanOrEqual(10, 10);
assertMatchRegExp(string, pattern)
This method verifies if string math the regula expression defined by pattern. If the condition is true the test continues, else an exception is thrown and a fatal error is inserted in the test results.
Test.assertMatchRegExp("This string match the regual expression", /match/);
assertStartsWith(string, startString)
This method verifies if text string starts with the text startString. If the condition is true the test continues, else an exception is thrown and a fatal error is inserted in the test results.
Test.assertStartsWith("This string start with the text", "This string");
closeDocument(document)
Close a document previously opened for testing. Only documents opened via Banana.application.openDocument can be closed. Document opened during tests have to be closed before the test ends.
let testDoc = Banana.application.openDocument("testfile.ac2");
// Do some tests on testDoc
Test.closeDocument(testDoc);
registerTestCase(testCase)
This method register a testCase (an object) to be run as test.
// Register test case to be executed
Test.registerTestCase(new TestLoggerSimpleExample());
setDocument(document)
Set the current document returned by Banana.document.
let testDoc = Banana.application.openDocument("testfile.ac2");
// Do some tests on testDoc
Test.setDocument(testDoc);
Test.closeDocument(testDoc);
setTableValue(tableName, rowNr, columnName, value)
Set the value in table tableName, row rowNr and column columnName. The value is a string, and follow the internal format for numbers, dates, times and boolean.
let testDoc = Banana.application.openDocument("testfile.ac2");
Test.setDocument(testDoc);
Test.setTableValue("Invoices", 3, "Description", "Test Invoice 3");
Test.setTableValue("Invoices", 3, "Date", "2023-09-26");
Test.setTableValue("Items", 12, "UnitPrice", "1200.50");
Test.closeDocument(testDoc);
Banana.Test.Logger
The class Banana.Test.Logger contains methods to log test results.
Methods
addSection(key)
This method inserts a new section named key in the test results. A section is like a chapter 1. A section ends at the end of the test or when the method addSection is called again.
addSubSection(key)
This method inserts a new subsection named key in the test results. A section is like a chapter 1.1. A subsection ends at the end of the test or when the methods addSection or addSubSection are called again.
addSubSubSection(key)
This method inserts a new subsubsection named key in the test results. A section is like a chapter 1.1.1. A subsubsection ends at the end of the test or when the methods addSection, addSubSection or addSubSubSection are called again.
addComment(key)
This method inserts a comment in the test results. Test comments are discarded when comparing with the expected test results.
addCsv(key, table [, columns, separator, comment])
This method inserts the content of a csv text (comma separated values) in the test results.
The optional argument columns let you specify the subset of columns to output and in which order.
The optional argument separator if defined is used as the value's separator. If it is not defined the programm automatically determines the separator from one of '\t' (tabulator), ',' (comma) and ';' (semicolon).
// This output all columns
Test.logger.addTable("This is a table", Banana.document, columns);
// This output only the columns Date, Description and Amount
Test.logger.addTable("This is a table", Banana.document, ["Date", "Description", "Amount"]);
addInfo(key, value)
This method inserts an information in the test results. Test informations are discarded when comparing with the expected test results. Compared to addComment' the key/value information is printed in case you publish the latex result as a pdf.
Test.logger.addInfo("Current date", new Date().toLocaleDateString());
addFatalError(key)
This method inserts a fatal error in the test. If a fatal error is inserted, event in case the results are identical to the expected results, the test fails, and the error message reported to the test differences.
Test.logger.addFatalError("This is a fatal error message");
addJson(key, jsonString [, comment])
This method inserts a json string in the test results. The json string is formatted with identation and the formatted string outputted line by line. If the jsonString contains 'carriage return' characters, then it will be outputted as it is. If the string is not a valid json, the string is outputted as it is.
var obj = {
'count': 100,
'color': "yellow"
};
Test.logger.addJsonValue("Param", JSON.stringify(obj));
addKeyValue(key, value [, comment])
This method inserts a test value in form of key and value. The parameter value is of type string.
Test.logger.addKeyValue("Row count", Banana.document.table("Transactions").rowCount);
addPageBreak()
This method inserts a page break. Page Breaks are discarded when comparing with the expected test results. They are just useful when the output is converted to a pdf file for inspecting visually the results.
Since Banana 9.0.4
addRawText(text [, insertEndl])
This method inserts a raw string in the test results without any modification or cleaning.
The optional parameter insertEndl defaults to true. If true an endl in inserted after the text.
addReport(key, report [, comment])
This method inserts the content of a Banana.Report object in the test results. Only the text elements are inserted, not the element's styles.
var report = Banana.Report.newReport("Report title");
report.addParagraph("Hello World !!!", "styleHelloWorld");
Test.logger.addReport("This is a report", report);
addTable(key, table [, columns, comment])
This method inserts the content of a Banana.Table object in the test results.
The optional argument columns let you specify the subset of columns to output and in whitch order.
// This output all columns
Test.logger.addTable("This is a table", Banana.document, columns);
// This output only the columns Date, Description and Amount
Test.logger.addTable("This is a table", Banana.document, ["Date", "Description", "Amount"]);
addText(key)
This method inserts a simple string in the test results.
addXml(key, xmlString [, comment])
This method inserts an xml string in the test results. The xml string will be formatted with identation and the formatted string outputted line by line. If the xmlString contains 'carriage return' characters, then it will be outputted as it is. If the string is not a valid xml, the string is outputted as it is.
var xml =
"<note>" +
"<to>Pinco</to>" +
"<from>Pallino</from>" +
"<heading>Reminder</heading>" +
"<body>Don't forget me this weekend!</body>" +
"</note>";
Test.logger.addXmlValue("This is a xml value", xml);
getElapsedTime()
This method returns the elapsed test execution time in milliseconds.
newLogger(logname)
This method returns a new logger, results are written in a separated log file named logname. With this methods you can split test results over several files.
If you have a lot of test results it is advised to split the results over more folder and files. This makes it easy to verify the differences between tests.
As a generale rule, if you feed the test with two or more *.ac2 files, split the results in separate files.
Test.logger.addText("This test split the results over more files and folder");
// Write results in a new file called testresults
var testLogger = Test.logger.newLogger("testresults");
testLogger.addText("This text will be written in file testresults.txt");
testLogger.close();
// Write results in a new folder called testgroup
var groupLogger = Test.logger.newGroupLogger("testgroup");
// Write results in a new file called testgroup/testresults1
var test1Logger = groupLogger.newLogger("testresults1");
test1Logger.addText("This text will be written in file testgroup/testresults1.txt");
test1Logger.close();
// Write results in a new file called testgroup/testresults2
var test2Logger = groupLogger.newLogger("testresults2");
test1Logger.addText("This text will be written in file testgroup/testresults2.txt")
test2Logger.close();
groupLogger.close();
newGoupLogger(groupname)
This method returns a new logger, results are written in a separated folder named groupname. With this methods you can split test results over several folders.
If you have a lot of test resutls it is advised to split the results over more folder and files. This makes it easy to verify the differences between tests.
close()
Close the logger for writting and free the reserved system resources (handle, ,memory, ...). This method shold be called for every new logger created with the methods newLogger and newGroupLogger.
Reserved methods
Those methods are used by the BananaApps Test Framework, and should not be directly used.
addTestInfo(key, value)
This method is called automatically by the framework to insert in a test info value like the test name, the running date and time, ...
addTestBegin(key [, comment])
This method is called automatically by the framework to insert in the log file an indication when a test method is started.
addTestEnd()
This method is called automatically by the framework to insert in the log file an indication when a test method is finished. The framework will also automatically insert information about the elapsed time.
addTestCaseBegin(key [, comment])
This method is called automatically by the framework to insert in the log file an indication when a test case is started.
addTestCaseEnd()
This method is called automatically by the framework to insert in the log file an indication when a test case is finished. The framework will also automatically insert an information about the elapsed time.