Test Specification Language

Overview

The language for specifying tests contains the following main constructs:

  • message_publish - build and send a message (messages can be built using a template and XPath, a Java class, a system executable or a BSH script)
  • message_subscribe - subscribe for messages (matching a specification)
  • message_receive - receive one or more messages (blocking until a message is received unless otherwise specified)
  • message_respond - send a response to a received message (requiered for request-reply protocols)
  • action - perform an action (such as executing a system executable, a Java class, a BSH script or SQL)
  • value - extract data into a named variable (from a sequence, or using a system executable, a Java class, a BSH script or SQL)
  • loop - create a loop around the contained nodes
  • condition - execute the contained nodes only if the execute-condition evaluates to 'true'

Semantics

The nodes in a test specification are executed sequentially as they are encountered.

Tag substitution is performed before the node is evaluated. Tag substitution refers to the substitution of ##{<value name>} with the content of the named value. The named value can come from two sources:

  • value nodes (as described later)
  • value supplidaed as parameters to the tests (typically )

message_publish

  <message_publish name="[<name>]" channel="[<channel name>]"> 
    <message_builder command="[java|shell]:[<command id>]" template_path="[<path to a template>]"> 
      <param>[<command parameter 1>]</param>
      <param>[<command parameter 2>]</param>
      ...
    </message_builder> 
  </message_publish>
  • name - the name of the message_publish node
  • channel - the name of a channel defined in the message broker file
  • command (message_builder) - the command to that will build the message. Command types:
    • java:[java class implementing the org.mactor.framework.extensioninterface.MessageBuilder interface]
    • shell:[a shell script or executable that will produce the message to std out]
  • param - the parameters to the command. The number of parameters and syntax used in the paramters is a contract defined by command implementation. Tag substitution is performed before passing the parameters to the command implementation.

Examples

Build a message from a template and publish it to the «OutgoingOrder» channel:

  <message_publish name="PublishOrder" channel="OutgoingOrder"> 
    <message_builder command="java:org.mactor.extensions.xml.XPathTemplateMessageBuilder" template_path="templates/order.xml"> 
      <param>Header/MessageId=##{MessageId}</param> 
      <param>Data/OrderId=##{OrderId}</param> 
    </message_builder> 
  </message_publish>

Similar using the template without modifications:

  <message_publish name="PublishOrder" channel="OutgoingOrder"> 
    <message_builder command="java:org.mactor.extensions.xml.XPathTemplateMessageBuilder" template_path="templates/order.xml"/> 
  </message_publish>

Using a system executable to build a message:

  <message_publish name="PublishOrder" channel="OutgoingOrder"> 
    <message_builder command="shell:my_message_producer.sh" /> 
  </message_publish>

message_subscribe

  <message_subscribe name="[<name>]" channel="[<channel name>]"> 
    <message_selector  command="[java]:[<command id>]"> 
      <param>[<command parameter 1>]</param>
      <param>[<command parameter 2>]</param>
      ...
    </message_selector> 
  </message_subscribe> 
  • name - the name of the message_subscribe node
  • channel - the name of a channel defined in the message broker file
  • command (message_selector) - the command used to check if a message is accepted by the subscriber node. Command types:
    • java:[java class implementing the org.mactor.framework.extensioninterface.MessageBuilder interface]
  • param - the parameters to the command. The number of parameters and syntax used in the paramters is a contract defined by command implementation. Tag substitution is performed before passing the parameters to the command implementation.

Examples

Subscribe to messages coming in on the «IncomingOrderStatus» channel. Only messages acceptet by the message_selector command is passed on:

  <message_subscribe name="OrderStatus" channel="IncomingOrderStatus"> 
    <message_selector command="java:org.mactor.extensions.xml.BasicMessageSelector"> 
      <param>Header/CorrelationId=##{MessageId}</param> 
    </message_selector> 
  </message_subscribe> 

message_receive

  <message_receive name="[<name>]" 
    message_subscribe_node_name="[<name if the subscribe node>]"  
    max_message_count="[<count>]" 
    min_message_count="[<count>]" 
    max_timeout_seconds="[<seconds>]" 
    block_until_timeout="true|false"/>
  • name - the name of the message_receive node
  • message_subscribe_node_name - name of the message subscribe node this node will receive messages from
  • max_message_count - the maximum number of message to receive. If more messages is received the test fails (only possible when block_until_timeout=true).
  • min_message_count - the minimum number of messages to receive. The node block until this number of messages has been received (or until the timeout has been reached)
  • max_timeout_seconds - the maximum number of seconds to wait for messages
  • block_until_timeout - specifies if the node should block until timeout even if the minimum number of messages has been reached

Examples

Receive exactly one message using a previously defined message subscribe node named «SubscribeForOrderStatus»:

  <message_receive name="ReceiveOrderStatus" message_subscribe_node_name="SubscribeForOrderStatus" 
    max_message_count="1" min_message_count="1" max_timeout_seconds="600" block_until_timeout="false"/>

Receive 10 messages, perform an action (described later) and send a response message (also described later) for each for the received messages :

  <message_receive name="ReceiveOrder" message_subscribe_node_name="SubscribeForOrder" 
    max_message_count="10" min_message_count="10" max_timeout_seconds="600" block_until_timeout="false">
      <action name="ValidateOrder" command="java:org.mactor.extensions.xml.XPathIgnoreNsValidator">
          <param>//StatsId==1</param>
          <param>//ProductId==##{ExpectedProductId}</param>
      </action>
    <message_respond name="SendOrderResponse" > 
      <message_builder command="java:org.mactor.extensions.xml.XPathTemplateMessageBuilder" template_path="templates/order_soap_reponse_envelope.xml"> 
        <param>Data/OrderId=##{OrderId}</param> 
      </message_builder> 
    </message_publish>
  </message_receive>

message_respond

A message_respond node enables the sending of a synchronous response to a received message. A message_respond node can only be used within a message_receive node. The message_respond node must typically be used while dealing with synchronous message transfer protocols (i.e. such as SOAP)

  <message_respond name="[<name>]" > 
    <message_builder command="[java|shell]:[<command id>]" template_path="[<path to a template>]"> 
      <param>[<command parameter 1>]</param>
      <param>[<command parameter 2>]</param>
      ...
    </message_builder> 
  </message_respond>
  • name - the name of the message_respond node
  • command (message_builder) - the command to that will build the message. Command types:
    • java:[java class implementing the org.mactor.framework.extensioninterface.MessageBuilder interface]
    • shell:[a shell script or executable that will produce the message to std out]
  • param - the parameters to the command. The number of parameters and syntax used in the parameters is a contract defined by command implementation. Tag substitution is performed before passing the parameters to the command implementation.

Examples

Build a message from a template and publish it to the «OutgoingOrder» channel:

  <message_respond name="SendOrderResponse" > 
    <message_builder command="java:org.mactor.extensions.xml.XPathTemplateMessageBuilder" template_path="templates/order_soap_reponse_envelope.xml"> 
      <param>Data/OrderId=##{OrderId}</param> 
    </message_builder> 
  </message_publish>

action

  <action name="[<name>]" command="[java|shell|sql]:[<command id>]">
    <param>[<command parameter 1>]</param>
    <param>[<command parameter 2>]</param>
    ...
  </action>
  • name - the name of the action node
  • command - the command to execute. Command types:
    • java:[java class implementing the org.mactor.framework.extensioninterface.ActionCommand interface]
    • shell:[a shell script or executable] (considered as failed if the executable can not be executed or reports exit value other than 0)
    • sql:[name of config group in global config]:[sql expression | sql script file with the ending '.sql']
  • param - the parameters to the command. The number of parameters and syntax used in the paramters is a contract defined by command implementation. Tag substitution is performed before passing the parameters to the command implementation.

Examples

Assert that the parameter is not null (if the value named «OrderId» is null, the command will throw an exeption and the test will fail):

  <action name="ValidateOrderExist" command="java:org.mactor.extensions.AssertNotNullValidator">
    <param>##{OrderId}</param>
  </action>

Assert that the internet connection is up (ping will give an exit value other than 0 if the destination cannot be reached and the test will fail):

  <action name="CheckInternetConnection" command="shell:ping -n 1 -w 200 vg.no"/>

Run a sql expression:

  <action name="DeleteOrder" command="sql:order_db:delete order where id=##{OrderId}"/>

  Assuming that the global config file contains definition of order_db. I.e:
  
  <global_config xmlns="http://schemas.mactor.org/framework" max_test_threads="15"> 
    <group name="order_db"> 
      <value name="driver">oracle.jdbc.driver.OracleDriver</value> 
      <value name="url">jdbc:oracle:thin:@12.12.12.12:2121</value> 
      <value name="username">lars</value> 
      <value name="password">abc</value> 
    </group> 
  </global_config>

Run a sql expression:

  <action name="InitDb" command="sql:order_db:init_db.sql"/>

value

  <value name="[<name>]" command="[java|shell|sql]:[<command id>]">
    <param>[<command parameter 1>]</param>
    <param>[<command parameter 2>]</param>
    ...
  </value>
  • name - the name of the action node
  • command - the command to execute. Command types:
    • java:[java class implementing the org.mactor.framework.extensioninterface.ValueCommand interface]
    • shell:[a shell script or executable] (the value is the output from std out)
    • sql:[name of config group in global config]:[sql expression | sql script file with the ending '.sql'] ( the value is read from the first column in the first row)
  • param - the parameters to the command. The number of parameters and syntax used in the paramters is a contract defined by command implementation. Tag substitution is performed before passing the parameters to the command implementation.

Examples

Initialize the varible named «CurrentTime» with the current time:

  <value name="CurrentTime" command="java:org.mactor.extensions.CurrentTimeExtractor"/>

Initialize the varible named «MessageId1» with the next value in the sequence named «msgid» (starting at 200):

  <value name="MessageId1" command="sequence:msgid">
    <param>200</param>
  </value>

Initialize the varible named «MessageId2» with the next value in the sequence named «msgid»:

  <value name="MessageId2" command="sequence:msgid"/>

Initialize the varible named «DbOrderStatus» with the result of the database query:

  <value name="DbOrderStatus" command="sql:order_db:=select status from order where id='##{OrderId}'"/>
  
  Assuming that a config group named «order_db» is defined in the global config file, and that the «OrderId» value is defined 

Initialize the variable named «OrderId» with field from the last received message:

  <value name="OrderId" command="java:org.mactor.extensions.xml.XPathIgnoreNsValueExtractor">
    <param>//OrderId</param>
  </value>
  
  Assuming that the last received message contains an element matching the //OrderId XPath

loop

  <loop name="[<name>]" count="[<the number for times to loop>]">
      ...
  </loop>
  • name - the name of the loop node
  • count - the number of times to loop (infinite if not specified)

Examples

Publish 100 orders:

  <loop name="MainLoop" count="100">
    <message_publish name="PublishOrderStatus" channel="OutgoingOrderStatus">
      <message_builder command="java:org.mactor.extensions.xml.XPathTemplateMessageBuilder" template_path="templates/order_status.xml"/>
    </message_publish>
  </loop> 

Receive 1000 orders, and publish an OrderStatus for each of the:

  <message_subscribe name="SubscribeForOrder" channel="IncomingOrder">
    <message_selector command="java:org.mactor.extensions.xml.XPathIgnoreNsMessageSelector"></message_selector>
  </message_subscribe>
  <loop name="MainLoop" count="10000">
    <message_receive name="ReceiveOrder" message_subscribe_node_name="SubscribeForOrder" max_message_count="1" min_message_count="1" max_timeout_seconds="10000" block_until_timeout="true"></message_receive>
    <value name="MessageId" command="sequence:msgid">
      <param>999000</param>
    </value>
    <value name="CorrelationId" command="java:org.mactor.extensions.xml.XPathIgnoreNsValueExtractor">
      <param>//Header/MessageId</param>
    </value>
    <message_publish name="PublishOrderStatus" channel="OutgoingOrderStatus">
      <message_builder command="java:org.mactor.extensions.xml.XPathTemplateMessageBuilder" template_path="templates/order_status.xml">
        <param>//Header/MessageId==##{MessageId}</param>
        <param>//Header/CorrelationId==##{CorrelationId}</param>
        <param>//Status==0</param>
      </message_builder>
    </message_publish>
  </loop>