Skip to main content
Version: 2023

Unit tests

Introduction to unit tests

A unit test is a way of testing one single unit of software. A unit is the smallest piece of code that can be logically isolated in a system. The purpose is to validate that each unit of the software performs as designed. In most programming languages, it is a function, a subroutine, or a method. In the Software Factory, you can write unit tests for the following logic concepts:

  • Defaults
  • Layouts
  • Contexts
  • Badges
  • Tasks
  • Processes
  • Subroutines (of type Procedure or Scalar Function only)
  • Triggers.

The image below shows the unit test screen. This is the place to create, maintain and execute unit tests.

This image shows the unit test screen Unit tests

Create a unit test

note

Tab Object overview shows all the objects for which you can create unit tests. For each object, a suffix indicates the number of active unit tests.

To create a unit test:

menu Quality > Unit tests > tab List or Form

  1. Execute the Add new unit test Add task.
  2. Enter a name for the test in the field Unit test.
  3. Select a Unit test type.
  4. Fill in at least the other mandatory fields. Which fields are requested or mandatory depends on the selected unit test type and object type.
  5. Click Execute.
  6. In tab Form, click Edit Edit.
  7. If the unit test should abort if it does not succeed, select the Should abort checkbox.
  8. If the code should do a rollback if an error occurs, select the Should rollback checkbox.
  9. A preparation query can be used, for example, to influence parameter values. In tab Preparation, check the Use prepare query box to enable the query field.
  10. You can test the outcome of a unit test with parameters. See Add parameters to a unit test. If no output is available, you can verify the outcome with an assertion query, for example, for specific tasks and triggers. The output parameters for a unit test are also available in the assertion query. In tab Assertion, select the Use assertion query checkbox to enable the assertion query field. This field is filled with an example query by default, showing how the assertion result can be thrown when certain conditions are met.
  11. Test your unit test with task Execute selected unit tests execute selected.

assertion query in the unit test screen Example of an assertion query

Add parameters to a unit test

menu Quality > Unit tests > tab Form

It is possible to add parameters to a unit test. A distinction is made between input parameters, output parameters, and row filters.

  • The row filters are used in the 'where' clause when testing update or delete triggers. The same filter conditions are available as when filtering in the GUI or adding a prefilter with type Columns in the Software Factory. See Filter condition.
  • The output parameters will be checked after the unit test has been executed.
  • You can also specify the expected messages. These will also be checked after performing a unit test.

When specific data is needed to meet certain conditions in the code, the best practice is not to rely on live data. Instead, you should use data sets as mock data. In this way, the necessary data is available for the test.

row filter Row filter in a unit test

Add mock data to a unit test

Data sets are collections of data that can be used for testing purposes. The data in a data set only exists in the context of your unit test. Every time you run a unit test, the data from your defined data set is added to a transaction. This transaction is rolled back at the end, which means the data will never actually be added to your database.

First, you need to create a data set, then you can add it to one or more unit tests.

menu Quality > Unit tests > tab Mock data

  1. Add add a Data set and enter a name.

  2. In tab Content, add add one or more tables.

  3. In tab Data rows, add add multiple rows as data for each table. When no rows are specified, the table will contain 0 records. It is not necessary to take foreign key constraints into account.

  4. In tab Data values, add the input values for the unit test. They don't need to exist in the data set, it depends on what you want to test. For example, if you wish to test a business rule to prevent a user from adding a duplicate value, you can add an input value that is already in the data set.

    It is possible to use Identity insert for your data set. If you leave the Id column empty, an identity value is added automatically. If you define a static value for the Id column, Identity insert is turned off, and your static value is added instead.

    data sets screen Data sets

    Now a data set is available, you can add it to a unit test:

  5. In tab Unit tests, select a unit test.

  6. Navigate to tab Form > tab Mock data.

  7. Select the created data set.

mock data selection as detail of the unit test Mock data in a unit test

Run a unit test

The Unit tests tab shows an overview of all the unit tests for the selected branch.

menu Quality > Unit tests > tab List or Form

  1. Select one or multiple unit tests.

  2. Run the tests:

    • Run Execute all unit tests - Runs all active unit tests.
    • Run selected Execute selected unit tests - Runs all selected active unit tests.

(De)activate a unit test

menu Quality > Unit tests > tab List or Form

Sometimes, a unit test is temporarily not necessary and should not be executed.

  • To deactivate a unit test, select the unit test and execute the deactivate Deactivate unit test task.
  • Use prefilter Hide inactive unit tests hide to hide or display the deactivated unit tests.
  • To reactivate an inactive unit test, select the unit test and execute the Activate unit test activate task.

Deactivate Deactivate a unit test

Unit tests in the Functionality modeler

Unit tests can also be created, maintained, or executed from the Functionality modeler.

menu Business logic > Functionality > tab Unit tests

The list shows all the unit tests directly connected with the program objects on the result page. For example, when a default procedure is created for Employee to combine the first and last name to display a name, the written unit test that validates the email address is also shown in the list.

Also, all unit tests are shown that have the selected control procedure linked as primarily.

unit tests as a tab in functionality Unit tests in the Functionality modeler

Unit test analyses

The Analysis menu group in the Software Factory provides three cubes to monitor the unit test runs and coverage.

note

The cubes for unit test coverage rely on the presence of program objects in the model, so ensure that the model definition is generated.

Unit test runs

menu Analysis > Unit test runs

This cube shows the number of runs for each unit test and their duration.

Unit test control procedure coverage

menu Analysis > Unit test control procedure coverage

This cube shows the ratio of control procedures covered by a unit test. Only control procedures of code groups that allow for unit tests are measured.

Three cube views are available:

  • Coverage per code group
  • Coverage per developer
  • General coverage

Coverage per code group Coverage per code group

The coverage status is determined as follows. A control procedure can be either:

  • Covered - A program object item created by the control procedure is present in a program object involved directly in any active unit test.
  • Covered (linked only) - The control procedure is linked to an active unit test, but the program object items of this control procedure are not in any program object directly involved in an active unit test.
  • Not covered - The program object items created by this control procedure are part of program objects that are not directly involved in any unit test, nor is the control procedure linked to an active unit test.

Unit test program object coverage

menu Analysis > Unit test program object coverage

This cube is similar to the control procedure coverage cube but measures the number of program objects instead. Only program objects of code groups that can have unit tests are measured.

Two cube views are available:

  • Coverage per code group
  • General coverage.
note

The coverage for program objects is generally lower than the coverage for control procedures, as a dynamically assigned control procedure might not have a unit test on every program object where it is assigned.