Skip to main content

Implementing a single test POU

Creating a framework for the test case

A test case is a function block which follows a specific scheme. To make it easier to follow the scheme, we recommend using the wizard. If you manually create a test case, then it should always derive from TM.Testcase. (Obsolete Test POU Implementations).

Procedure. Inserting a unit test object
  1. Add the test case function block below an application or in the POU pool. To do this, click Add ObjectUnit Test in the context menu.

    The Add Unit Test dialog opens.

  2. Specify the following parameters:

    Name of the POU: TestCase_1

    Type: Extend TM.Testcase (recommended)

    _cds_icon_checked.png Add optional methods

    _cds_icon_checked.png Add implementation template

    _cds_icon_checked.png Add explanatory comments

    Test Case Category: BasicTests

  3. Click Add to confirm the dialog and save the project.

    A new function block is created with the Execute, Setup, Teardown, and Abort methods.

For more information, see: Add Unit Test

Implementing the test logic

This section uses simples examples to describe how to add test logic to the generated test case template. For this purpose, a simple CTU (counter up) is used as the testee.

Note

The test case function block is to be understood as a sandbox for the testee. This means, for example, that the test case function block contains a dedicated instance of the testee and needs to prepare and post-process the environment which is necessary to call the testee. Therefore, the testee should be as context-free as possible in the sense of a unit test. As a result, the unit test cannot be used for system test scenarios.

  1. In the declaration part of the test POU, declare an instance of the testee. For example, test a CTU standard POU here.

    {attribute 'test'}
    {attribute 'testcasename':='TC01'}
    {attribute 'testcasetimeout':='15000'}
    FUNCTION_BLOCK TestCase EXTENDS TM.Testcase
    VAR_INPUT
    END_VAR
    VAR_OUTPUT
    END_VAR
    VAR
    	counter : CTU;	// testee instance
    	cycleCounter : INT; // independant test control variable
    END_VAR
  2. In the implementation part of the Setup method, add the initialization of the testee. The example initializes the CTU by reset and sets the counter limit to 5. The setup method is called one time before Execute.

    // Initialize the testee
    counter(CU:=FALSE, RESET:=TRUE, PV:=5);	// reset the counter, set expected upper limit
    
    // Initialize the test itself
    cycleCounter := 0;	// we'll count cycles
  3. Call the testee in the Execute method and check its result. During this time, the Execute method is called until it returns TRUE. As a result, the testee can be called over multiple PLC cycles.

    cycleCounter := cycleCounter + 1;	// count cycles
    
    IF (cycleCounter <= 10) THEN // stimulate testee as long as we expect: 5 rising edges to count to 5 equals minimum 10 cycles
         
        // stimulate testee
        counter(CU:= (NOT counter.CU), RESET:=FALSE);	// Trigger counter with rising edges
    	
        Execute := FALSE;   // signal test still running
    ELSE
        // check result with suitable assertions for any occasion
        TM.Assert_Bool_IsTrue(THIS^, counter.Q, "CTU did not signal that it's limit was reached");
        TM.Assert_Word_Equal(THIS^, 5, counter.CV, "CTU did not reach expected limit");
         
        Execute := TRUE;    // mandatory: signal test completed
    END_IF
  4. You could uninitialize the testee in the Teardown method. However, this is not necessary in this example. You can delete the method.

  5. Likewise, no special code needs to be executed if the test times out. You can delete the Abort method.

Configuring the IEC Unit Test test element

  1. In Title, specify a test case name.

    Example: N_001_Test

    When the test is executed, the title is displayed as the test case name.

  2. In Device read timeout (ms), specify a time. Example: 5000

    Note

    For each test case, the system waits at least for the test status and test result to be read. Moreover, the system waits when the application status is read when logging in.

    Before reading variables, the system waits until the timeout has elapsed.

  3. In Login retries, specify the maximum number of attempts to establish online mode. Example: 3

  4. Click in the upper left of the Selected categories table.

    An input field is displayed.

  5. Specify all categories which are called in this test case.

    Example: BasicTests

    All test function blocks decorated with the 'testcategory' := 'BasicTests' attribute called in this test case.

Executing a test script

Requirement: The test environment is prepared. The test project is open in the CODESYS Development System and the device settings and communication settings are configured. These required instructions are made by a preparatory test case in the test script.

  1. The contents of the Generated unit tests folder are deleted in order to remove the generated POUs of a previous IEC unit test.

  2. The project and the Libraries to test are searched for test tables. Then the function blocks for executing the test tables are generated in the Generated unit tests folder.

  3. The project and the libraries that are listed on Libraries to test are searched for function blocks and programs that are marked as test.

    Then, of the detected programs and function blocks, those are removed which are excluded by the test categories or the name.

    The remaining programs and function blocks are used in the test.

  4. A backup of the original application is created.

  5. The test cases are inserted as IEC code in PLC_PRG. In the declaration and implementation, the added lines of code are marked with Generated by IEC Unit Test.

  6. If the application is too large for the controller, then the tests are subdivided automatically into several smaller applications. One or more executable applications are generated.

  7. The test is executed with the generated application(s).

    The following steps are processed:

    • A test application is downloaded to the controller.

    • The test application is started.

    • The test cases are executed. If the string variable sInfo or wsInfo is used in the test function blocks, then its contents are included in the test report.

    • The timeout is monitored.

    • The test result is checked and then sent to the test report.

    • The application is removed from the controller.

  8. A test report is generated containing all test results.

Tip

Pay attention to the test repository Default-Test-Repository. The test script Examples.IecUnitTest is located there. In this test script, you can reconstruct an IEC unit test by loading the prepared steps to the project, updating the device, and configuring the communication settings. This is followed by an IEC unit test. The test cases that are processed originate from the Example_IecUnitTest project. The project is included in the installation directory: C:\ProgramData\CODESYS Test Manager.

The sample scripts are created for a CODESYS Control Win controller (32 bit). If you use a different controller, then you need to adapt the parameters of the UpdateDevice script action.