Test Case Templates

Test Case Templates provide features to help make Test Cases more easily re-usable after copying from a Library or another Draft.

Template Syntax

Test Case Templates use the popular Python Jinja2 template syntax, particularly if conditions and expressions

See also

For more information about Jinja2 syntax

Note

If template control structures such as ‘if’ or ‘for’ are used in a Test Case then, if there are errors in the Test Case, TrialGrid cannot determine on which line the error has occurred. The errors will be displayed underneath the Test Case but the line(s) will not be highlighted. This is because template control structures might change the number of lines in the final Test Case and its not possible to accurately highlight the line in the original source.

Optional Fields

It is common for Forms in Libraries to contain all Fields which might ever be needed with the expectation that some Fields will be removed or inactivated after copying into a study Draft because those Fields are not relevant for that study.

For example a Library Inclusion/Exclusion Form might contain 5 Inclusion Fields, INC01, INC02, etc but in a study the Field INC04 is not relevant and is removed from the Form. The Library contains an Edit Check to raise a query if any Inclusion Criteria have not been met:

SCR.IE.INC01.CodedValue == "N"
or SCR.IE.INC02.CodedValue == "N"
or SCR.IE.INC03.CodedValue == "N"
or SCR.IE.INC04.CodedValue == "N"
or SCR.IE.INC05.CodedValue == "N"

The study version of the Edit Check will not include the INC04 Field:

SCR.IE.INC01.CodedValue == "N"
or SCR.IE.INC02.CodedValue == "N"
or SCR.IE.INC03.CodedValue == "N"
or SCR.IE.INC05.CodedValue == "N"

The Library contains a Test Case for this Edit Check, with a test scenario to verify the query has been raised:

Scenario: Check Actions are run
  When I enter and save data
    | DataPoint          | Value |
    | SCR.IE.INC01[0]    | YES   |
    | SCR.IE.INC02[0]    | YES   |
    | SCR.IE.INC03[0]    | NO    |
    | SCR.IE.INC04[0]    | NO    |
    | SCR.IE.INC05[0]    | NO    |
    | SCR.IE.IE[0] | YES   |

  Then I should see the following query on "SCR.IE.INC_EXCL[0]"
    """
    One or more of the Inclusion/Exclusion criteria was not met, yet subject was checked as eligible for the study. Please reconcile, else clarify.
    """

This Test Case can be copied into the study Draft but cannot be run as-is because the INC04 field does not exist in the draft. One option is to manually remove the data entry line for INC04 but this requires effort and will make the study version different from the library version for standards compliance. Instead the Library Test Case can use an ‘if’ template condition:

Scenario: Check Actions are run
  When I enter and save data
    | DataPoint          | Value |
    | SCR.IE.INC01[0]    | YES   |
    | SCR.IE.INC02[0]    | YES   |
    | SCR.IE.INC03[0]    | NO    |
    {% if draft.has_form_field("IE", "INC04") %}
    | SCR.IE.INC04[0]    | NO    |
    {% endif %}
    | SCR.IE.INC05[0]    | NO    |
    | SCR.IE.INC_EXCL[0] | YES   |

  Then I should see the following query on "SCR.IE.INC_EXCL[0]"
    """
    One or more of the Inclusion/Exclusion criteria was not met, yet subject was checked as eligible for the study. Please reconcile, else clarify.
    """

When the library test case is copied into the study draft it does not need to be manually changed. TrialGrid will check if the draft has an active Field with OID ‘INC04’ on an active Form with OID ‘IE’ and if not then it will not attempt to enter that data into Rave when running the Test Case.

The definition of the Test Case does not have to be modified and it will be standards compliant with the library.

Optional Forms

Test Case Templates can test if a Form with the specified OID is present and active in the draft:

Scenario: Forms are added
  When I enter and save data
    | DataPoint          | Value |
    | SCR.IE.INC_EXCL[0] | YES   |

  {% if draft.has_form("EX1A") %}
  Then I should see form "EX1A" in folder "V1"
  {% endif %}

  {% if draft.has_form("EX1B") %}
  And I should see form "EX1B" in folder "V1"
  {% endif %}

  And I should see form "VT" in folder "V1"

Optional Folders

Test Case Templates can test if a Folder with the specified OID is present and active in the draft:

Scenario: Forms are added
  When I enter and save data
    | DataPoint          | Value |
    | SCR.IE.INC_EXCL[0] | YES   |

  {% if draft.has_folder("V2") %}
  Then I should see form "EX1A" in folder "V2"
  {% endif %}

  And I should see form "VT" in folder "V1"

Custom Properties

Test Case Templates can use Draft and Project Custom Properties:

Scenario: Forms are added
  When I enter and save data
    | DataPoint          | Value |
    | SCR.IE.INC_EXCL[0] | YES   |

  {% if draft.property("TA") == "Oncology" %}
  Then I should see form "EX1A" in folder "V1"
  {% endif %}

  {% if project.property("US") %}
  And I should see form "EX1B" in folder "V1"
  {% endif %}

  {% if draft.property("Version")|int > 2  %}
  And I should see form "VT" in folder "V1"
  {% endif %}

In the above example the Project property “US” is a boolean property. “TA” is a text property which can be compared against string values. To do a numeric comparison the custom property must be converted into an integer as in the “Version” example above.

Custom Property values can be inserted into the Test Case using expressions:

Scenario: Scenario 1
  When I enter and save data
    | DataPoint              | Value                                |
    | AE_FOLDER.AE.AETERM[1] | {{ project.property("Study Drug") }} |

When TrialGrid runs the Test Case it will use the value of the Project’s Custom Property to enter data into the AETERM Field.

Folder placeholders

To avoid having to specify a Folder in a Test Case a Folder placeholder can be used:

@EditCheck: AE001
Scenario: Folder placeholder
  Given folder "{{ folder }}" exists

The Test Case must have an Edit Check reference. If more than one Edit Check reference is present then the one which occurs first in the Test Case will be used.

TrialGrid will analyze the Edit Check and find a Folder to insert into the Test Case. If the Edit Check contains steps where the Folder is not specified (‘wild-carded’) then TrialGrid will insert an appropriate Folder. If the Edit Check contains more than one Folder then an error will be raised since TrialGrid does not know which one to choose.

Action datapoint placeholders

To avoid having to specify the datapoint on which a Check Action will operate a placeholder can be used:

@EditCheck: AE001
Scenario: Folder placeholder
  Then I should see "{{ action_datapoint }}" is empty

The Test Case must have an Edit Check reference. If more than one Edit Check reference is present then the one which occurs first in the Test Case will be used.

TrialGrid will analyze the Edit Check and find a Check Action target datapoint to insert into the Test Case. ‘IsPresent’ Check Actions will be ignored, unless no other Check Actions are present as will ‘Custom Function’ Check Actions which reference a Custom Function which has code ‘return true;’ (an ‘Always True’ Custom Function). If the Edit Check contains more than one Check Action (other than IsPresent and Always True Custom Functions) it will be marked as an error.

Using For loops to avoid repetition

To avoid having to repeat similar steps a template For loop can be used.

For example several scenarios can be created for different folders like this:

{% for oid in ['V1', 'V2', 'V3'] %}
Scenario: Test Folder {{ OID }}
  Given folder "{{ oid }}" exists
  When I enter and save data
    | DataPoint              | Value    |
    | {{oid}.AE.AETERM[1]    | HEADACHE |
{% endfor %}

This will be expanded automatically into:

Scenario: Test Folder V1
  Given folder "V1" exists
  When I enter and save data
    | DataPoint          | Value    |
    | V1.AE.AETERM[1]    | HEADACHE |

Scenario: Test Folder V2
  Given folder "V2" exists
  When I enter and save data
    | DataPoint          | Value    |
    | V2.AE.AETERM[1]    | HEADACHE |

Scenario: Test Folder V3
  Given folder "V3" exists
  When I enter and save data
    | DataPoint          | Value    |
    | V3.AE.AETERM[1]    | HEADACHE |