Working with the TestFramework for extenstions

Documentation •
In this article


This walkthrough provides step-by-step guidance for creating a simple test case example that uses Extensions Test Framework to run unit tests of Extensions.

The steps in order to experiment with Extensions Test Framework are the following:

  1. Download and use the Banana Experimental version
  2. Create a Extension to be tested
  3. Create a test case
  4. Run the test
  5. Verify the test results

 Create an Extension to be tested

A test case is related to a working Extension.
For this example we use a modified version of "Hello World!" Extension example (see Build your first Extension).

  1. Copy the code below, paste it on your text editor and save the file as helloworld2.js

    // @id =
    // @api = 1.0
    // @pubdate = 2018-10-23
    // @publisher = SA
    // @description = Example Hello world 2
    // @task = app.command
    // @doctype = *.*
    // @docproperties =
    // @outputformat = none
    // @inputdataform = none
    // @timeout = -1
    function exec() {
       //Call the function to create the report
       var report = createReport();
       //Print the report
       var stylesheet = Banana.Report.newStyleSheet();
       Banana.Report.preview(report, stylesheet);
    function createReport() {
        //Create the report
        var report = Banana.Report.newReport("Report title");
        //Add a paragraph with the "hello world" text
        report.addParagraph("Hello World!");
        //Return the report
        return report;

 Create a test case

Follow the instructions below to create a working test case:

  1. Create a folder test in the same folder where the Extension  helloworld2.js is located.
  2. Copy the following JavaScript code and paste it into a text editor.

    // @id =
    // @api = 1.0
    // @pubdate = 2018-10-30
    // @publisher = SA
    // @description = [Test] Example Hello world 2
    // @task = app.command
    // @doctype = *.*
    // @docproperties =
    // @outputformat = none
    // @inputdataform = none
    // @timeout = -1
    // @includejs = ../helloworld2.js
    // Register this test case to be executed
    Test.registerTestCase(new TestFrameworkExample());
    // Define the test class, the name of the class is not important
    function TestFrameworkExample() {
    // This method will be called at the beginning of the test case
    TestFrameworkExample.prototype.initTestCase = function() {
       this.progressBar = Banana.application.progressBar;
    // This method will be called at the end of the test case
    TestFrameworkExample.prototype.cleanupTestCase = function() {
    // This method will be called before every test method is executed
    TestFrameworkExample.prototype.init = function() {
    // This method will be called after every test method is executed
    TestFrameworkExample.prototype.cleanup = function() {
    // Every method with the prefix 'test' are executed automatically as test method
    // You can defiend as many test methods as you need
    TestFrameworkExample.prototype.testVerifyMethods = function() {
       Test.logger.addText("The object Test defines methods to verify conditions.");
       // This method verify that the condition is true
       Test.assert(true, "message"); // You can specify a message to be logged in case of failure
       // This method verify that the two parameters are equals
       Test.assertIsEqual("Same text", "Same text");
    TestFrameworkExample.prototype.testBananaApps = function() {
       Test.logger.addText("This test will tests the BananaApp helloworld.js");
       var document = Banana.application.openDocument("file:script/../test/testcases/accounting_file.ac2");
       Test.assert(document, "File ac2 not found");
       // Add the report content text to the result txt file
       var report = createReport();
       Test.logger.addReport("ReportName", report);
  3. Modify the script: find the row "var document = Banana.application.openDocument("file:script/../test/testcases/accounting_file.ac2")" and replace "accounting_file.ac2" with the name of your Banana accounting file.
  4. Save the file into test folder as helloworld2.test.js (the file name must always be <same_name_bananaapp>.test.js).
  5. Create a folder test/testcases and copy there your file .ac2.
  6. Now you should have something like this:

    • helloworld2.js: the BananaApp
    • test: the test folder
    • helloworld2.test.js: the test script for the Extension
    • testcases: the folder for test ac2 files
    • xxx.ac2: your Banana accounting file

 Run the test case

Finally, now it is possible to run the test case and see the results.

To run the test:

  1. In Banana select from the menu Extensions the command Manage Extensions...

  2. Select from the Installed element the “Example Hello World 2” Extension
  3. Click on the button Run tests

 Test case results

The test compare the current results with the expected results and checks if there are differences.
If differences are found a dialog message warn you. All the details can be found inside the .test.diff.txt file.

The first time you run a test probably you will see the following "Test failed" dialog message:

In your test folder you can see two new auto generated folders:

  • test/testresults:
    contains the helloworld2.test folder with a helloworld2.test.txt file with the results of the test.
    When the test is run, the folder and the file are automatically generated.
  • test/testexpected:
    contains the helloworld2.test folder that should contain a helloworld2.test.txt file with the expected results.
    When the test is run, the folder is automatically generated, but the file NOT. The first time you run the test the folder is empty. This is why the test fails.

You now should have something like that:

Inside the test/testresults/helloworld2.test folder there is the helloworld2.test.txt file with all the results of the test, like the following one:

The file helloworld2.test.diff.txt is a resume of the results, with all the differences the test has found.

The image below shows an example of test summary with differences:

  • with the sign "+" are indicated the rows added to the .txt file of the test/testresults folder (compared with the testexpected folder)
  • with the sign "-" are indicated the rows removed from the .txt file of the test/testresults folder (compared with the testexpected folder)

As mentioned above, the folder test/testexpected is empty. This is why we can see a lot of added rows to the .txt file of the test/testresults folder.

If you have differences and and you know these differences are correct (like in this case):

  • copy the test results .txt file from the folder test/testresults to the folder test/testexpected.

You should have a structure like this:

Note that the helloworld2.test.txt file is now located in both folders, in the test/testresults/helloworld2.test folder and in the test/testexpected/helloworld2.test folder.

If you run again the test, this time the result is different. You now should see a positive message from the dialog:

This means that the results .txt file generated from the test, is perfectly identical of the expected .txt file. So, the test is successfully passed.

You can also check the helloworld2.test.diff.txt file of the test/testresults/helloworld2.test folder to see the differences results, and there should not be differences found.


From that point, every time you do changes to the Extension you can test it and see if the changes you made works as you expected.

Remember: if you have differences and you know these differences are correct, you have to replace the expected .txt file.

Test case report with an example 

For creation a complete report you should begin with some operation that integrate in your extension code.

This is a repository to begin your report example.

The operation are:

  • Create a function that contains all tests that you want doing.
  • Save the content of your file about test case.
  • Configure parameters user.
  • Create a structure of report (balance, profit-loss).
  • Validate the groups of the accounting.
  • Loads your values of report from the Balance Sheet.
  • Calculate the totals of the amounts.
  • Format values of the reports.
  • Print the results of your report.

After these operations on the code side you can run your test as explained on this page.

Create a function for testing a report

In the folder you can see an example of how do you create a test for reporting.

In this part of the file you adds the functions you can add the operation that explain in the next chapters (save the content of your file, configure parameter of user,...etc).

Save the content of your file about test case

var bananaDocument = Banana.application.openDocument("file:script/../test/testcases/nameFileTestCases.ac2");

In this variable you save the content of your file that is the test case. 

To learn more about the method openDocument.

Configure parameter of user

You can initialize the parameter for define the period of begining and ending your report, the title of your document, if is necessary print logo or not and others. It is very important define the parameter of column, because this paramter define where bring the information about the Report Structure. In this example is Gr1, that meaning in the Banana Plus, you define in the column Gr1 the list of IDs of your account.

Create structure of your report - Balance

For creation a base report, you can create an array that contain all information that you need.

The information are: 

  • the group IDs.
  • Description of account.
  • Sum of the group of accounts.
  • Type of account (asset, liabilitie , cost, revenue).

Parameter explanation

  • id
    Is the unique parameter of column in Banana, the column name of id corresponds to Gr1, you can decide what to put as the id, as long as the id is the same as what you configure in the Gr1 column of Banana.
  • type
    Define what type of data is. The are three options: title, group and total.
    • Title: Normally used when a title or a description text without amount must be displayed.

      The "id" group starts with a "d" (description).


      {"id":"dABI", "type":"title", "indent":"1", "description":"I - Intangible assets"}

    • Group: Used when a group with text and amount must be displayed.


      {"id":"ABI1", "type":"group", "indent":"2", "bclass":"1", "description":"1) Installation and expansion costs"}
      {"id":"ABI2", "type":"group", "indent":"2", "bclass":"1", "description":"2) Development costs"}

    • Total: Used for the total of a group with and amount. The amount is the sum groups amounts. Use the property "sum" to indicate the list of all "id" groups that must be summed together, separated by a semicolon ";". To subtract amounts use the minus sign "-" before the group "id".


      {"id":"TC", "type":"total", "indent":"1", "description":"Total Costs", "sum":"C1;C2"}  →  sum = C1 + C2
      {"id":"AS", "type":"total", "indent":"1", "description":"Total Assets", "sum":"AS1;-C3"} →  sum = AS1 - C3

  • bclass 
    Corresponding of what is this account. In Banana bclass 1 is Assets, 2 is Liabilities, 3 Costs, 4 Revenues.
  • description
    Used to define the description text used for the print.
  • note
    This is used to provide more details in the report.
  • sum
    This is used to define how to calculate the total.

In this example, you create a simply configuration for creation a report of Balance Sheet, where contains the assets and the liabilities of short term:

function createReportStructure(){
//create an array where do you pass your parameter for creation your structure of Balance
var reportStructureBalance = [];

reportStructureBalance.push({ "id": "CashId", "type": "group", "note": "", "bclass": "1", "description": "Cash" });
reportStructureBalance.push({ "id": "BankId", "type": "group", "note": "", "bclass": "1", "description": "Bank" });
reportStructureBalance.push({ "id": "TotalLiquidityId", "type": "total", "note": "", "bclass": "1", "description": "Total liquidity", "sum":"CashId;BankId" });

reportStructureBalance.push({ "id": "SuppliersId", "type": "group", "note": "", "bclass": "2", "description": "Suppliers" });
reportStructureBalance.push({ "id": "DueBanksShortTermId", "type": "group", "note": "", "bclass": "2", "description": "Due to banks short/term" });
reportStructureBalance.push({ "id": "ShortTermOnorousDebtsId", "type": "total", "note": "", "bclass": "1", "description": "Short-term onorous debts", "sum":"SuppliersId;DueBanksShortTermId" });

Loads your values of report from the Balance Sheet

Before load your values of report, you have to invoke the next functions as indicate in this repository:

  1. validateGroupsBalance.
  2. loadBalances.
  3. calculateTotals.
  4. formatValues.
  5. excludeEntries.
  6. printBalanceSheet.
  7. addReport.



The input of this function grColumn: is a prameter of id group of column (Example: Gr1).

This function have to check if the groups defined by user is valid or not.


This function load and calculate the current and previous balances of the report structure.


Calculates all totals of the reportStructure for the given list of fields.


Converts all the amounts to local format for the given list of field.


Entries preceded by Arabic numbers or lower case letters with zero amounts for two consecutive exercises, can be excluded from the print.

printprofitlossstatement(banDoc, userParam, bReport, stylesheet)

Defines the data and print layout for the report. Returns the report with data and layout.

banDoc is the document open that use in Banana.

userParam is the array data of period of begin, periodo of the end, title of document, column of id.

bReport is object of the class BReport who contain the proprieties: Banana document, the user parameter, the report structure, the version.

stylesheet is object that define the layout of your report.

More about Extensions Test



Tell us how we can help you better
If the information on this page is not what you're looking for, is not clear enough, or is not up-to-date, let us know.

Share this article: Twitter | Facebook | LinkedIn | Email