-
Notifications
You must be signed in to change notification settings - Fork 0
Using control flow statements
Flow control tags are what allow the DTF XML scripting language to be as expressive as it is. There are quite a few flow control tags but the basic ones will be listed below along with a small example:
The for tag executes the underlying children tags as many times as the range specified has elements and only requires that you get the hang of ranges before you're able to use it to its full potential, here are a few simple examples of how to use the for loop:
<?xml version="1.0" encoding="UTF-8"?>
<script xmlns="http://dtf.org/v1" name="for_loop_usage">
<info>
<author>
<name>Rodney Gomes</name>
<email>rlgomes@yahoo-inc.com</email>
</author>
<description>
</description>
</info>
<for property="i" range="[0..5]">
<log>${i}</log>
</for>
<for property="i" range="[a,b,c,d]">
<log>${i}</log>
</for>
<for property="i" range="[0..1][0..1][0..1]">
<log>${i}</log>
</for>
<for property="i" range="[0..3][a,b,c,d,e]">
<log>${i}</log>
</for>
<for property="i" range="random([0..10])">
<log>${i}</log>
</for>
</script>
The parallelloop tag is executes the underlying children tags in parallel s many times as the range specified has elements. This has to be used carefully because you shouldn't really execute thousands of parallels since your system will spend more time doing context switching than actually getting work done. Here is a sample of using the parallelloop tag:
<?xml version="1.0" encoding="UTF-8"?>
<script xmlns="http://dtf.org/v1" name="parallelloop_usage">
<info>
<author>
<name>Rodney Gomes</name>
<email>rlgomes@yahoo-inc.com</email>
</author>
<description>
</description>
</info>
<parallelloop property="t" range="1..5">
<log>from thread ${t}</log>
</parallelloop>
<parallelloop property="i" range="1..3">
<parallelloop property="j" range="1..3">
<log>from thread ${i}.${j}</log>
</parallelloop>
</parallelloop>
</script>
The if tag will allow you to check various things including if a property is a set or if a string matches a certain regular expression. Here are a few examples of using the if tag and the available conditional tags:
<?xml version="1.0" encoding="UTF-8"?>
<script xmlns="http://dtf.org/v1" name="for">
<info>
<author>
<name>Rodney Gomes</name>
<email>rlgomes@yahoo-inc.com</email>
</author>
<description>Unit test for the for tag.</description>
</info>
<local>
<createstorage id="OUTPUT" path="${dtf.xml.path}/output"/>
<createstorage id="INPUT" path="${dtf.xml.path}/input"/>
<createstorage id="TINPUT" path="${dtf.xml.path}"/>
<import uri="storage://TINPUT/util.xml" loadFuncs="true" loadRefs="true"/>
<loadproperties uri="storage://INPUT/ut.properties"/>
<echo>Loop from [0..5]</echo>
<lockcomponent id="AGENT"/>
</local>
<record uri="storage://OUTPUT/for.results" type="txt" append="false">
<for property="index" range="[0..5]">
<event name="for.loop">
<attribute name="iteration" value="${index}" type="string" length="64"/>
</event>
</for>
</record>
<call function="checkRecordCount">
<property name="recorder.location" value="storage://OUTPUT/for.results"/>
<property name="recorder.type" value="txt"/>
<property name="event.name" value="for.loop"/>
<property name="record.count" value="6"/>
</call>
<local>
<echo>Loop from [a,b,c,d]</echo>
</local>
<record uri="storage://OUTPUT/for.results" type="txt" append="false">
<for property="index" range="[a,b,c,d]">
<event name="for.loop">
<attribute name="iteration" value="${index}" type="string" length="64"/>
</event>
</for>
</record>
<call function="checkRecordCount">
<property name="recorder.location" value="storage://OUTPUT/for.results"/>
<property name="recorder.type" value="txt"/>
<property name="event.name" value="for.loop"/> <property name="record.count" value="4"/> </call>
<local>
<echo>Loop from [0..1][0..1][0..1]</echo>
</local>
<record uri="storage://OUTPUT/for.results" type="txt" append="false">
<for property="index" range="[0..1][0..1][0..1]">
<event name="for.loop">
<attribute name="iteration" value="${index}" type="string" length="64"/>
</event>
</for>
</record>
<call function="checkRecordCount">
<property name="recorder.location" value="storage://OUTPUT/for.results"/>
<property name="recorder.type" value="txt"/>
<property name="event.name" value="for.loop"/>
<property name="record.count" value="8"/>
</call>
<local>
<echo>Loop from [0..3][a,b,c,d,e]</echo>
</local>
<record uri="storage://OUTPUT/for.results" type="txt" append="false">
<for property="index" range="[0..3][a,b,c,d,e]">
<event name="for.loop">
<attribute name="iteration" value="${index}" type="string" length="64"/>
</event>
</for>
</record>
<call function="checkRecordCount">
<property name="recorder.location" value="storage://OUTPUT/for.results"/>
<property name="recorder.type" value="txt"/>
<property name="event.name" value="for.loop"/>
<property name="record.count" value="20"/>
</call>
<!-- This is used to catch the issue of a property created only for the
tag for scope that persists afterwards. looking below since J exists
in the first for loop done in the main test and then we call some
actions on a component. If J is still defined (which shoudnl't be the
case) then the loops on the components do not have the desired
behavior. -->
<for property="j" range="1..3">
<log>${j}</log>
</for>
<component id="AGENT">
<createrange name="i" value="1..3"/>
<for property="j" range="1..3">
<if>
<neq op2="${i}" op1="${j}"/>
<then>
<fail message="property mismatch probably because j was already defined."/>
</then>
</if>
</for>
</component>
</script>
Try/catch and finally tags are available within DTF and they allow you to basically catch failures and do something about it as well as the ability to always execute a specific amount of XML language no matter what happens within a block using the finally tag. This feature is very useful when you don't want to terminate the test execution till you've cleaned up some resources or terminated some running element before you can proceed with the rest of the testing. With these tags you're able to do the following:
<?xml version="1.0" encoding="UTF-8"?>
<script xmlns="http://dtf.org/v1" name="try_catch_finally">
<info>
<author>
<name>Rodney Gomes</name>
<email>rlgomes@yahoo-inc.com</email>
</author>
<description>
</description>
</info>
<local>
<createstorage id="INPUT" path="${dtf.xml.path}/input"/>
<loadproperties uri="storage://INPUT/test.properties"/>
</local>
<try>
<sequence>
<fail message="failing from here!"/>
</sequence>
<catch exception="${dtf.FailException}">
<sequence>
<local>
<echo>The previous statement has failed correctly.</echo>
</local>
</sequence>
</catch>
<finally>
<log>This line will appear no matter what</log>
</finally>
</try>
</script> There are plenty of other flow control tags and more information can be found in the generated documentation here