Fixed schema, added template XML. Existing test suites to be updated.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14588 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2021-07-05 16:50:52 +00:00
parent 7d06369a82
commit b5e021a48f
7 changed files with 722 additions and 1 deletions

131
os/test/ftl/libs/libutils.ftl Executable file
View File

@ -0,0 +1,131 @@
[#ftl]
[#--
ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012,2013,2014,2015,2016,2017,2018,
2019,2020 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
--]
[#--
-- Returns the trimmed text "s" making sure it is terminated by a dot.
-- The empty string is always returned as an empty string, the dot is not
-- added.
--]
[#function WithDot s]
[#local s = s?trim /]
[#if s == ""]
[#return s /]
[/#if]
[#if s?ends_with(".")]
[#return s /]
[/#if]
[#return s + "." /]
[/#function]
[#--
-- Returns the trimmed text "s" making sure it is not terminated by a dot.
--]
[#function WithoutDot s]
[#local s = s?trim /]
[#if s?ends_with(".")]
[#return s?substring(0, s?length - 1) /]
[/#if]
[#return s /]
[/#function]
[#--
-- Returns the trimmed text "s" making sure it is terminated by a dot if the
-- text is composed of multiple phrases, if the text is composed of a single
-- phrase then makes sure it is *not* terminated by a dot.
-- A phrase is recognized by the pattern ". " into the text.
-- The empty string is always returned as an empty string, the dot is never
-- added.
--]
[#function IntelligentDot s]
[#local s = s?trim /]
[#if s?contains(". ")]
[#return WithDot(s) /]
[/#if]
[#return WithoutDot(s) /]
[/#function]
[#--
-- Formats a text string in a sequence of strings no longer than "len" (first
-- line) or "lenn" (subsequent lines).
-- White spaces are normalized between words, sequences of white spaces become
-- a single space.
--]
[#function StringToText len1 lenn s]
[#local words=s?word_list /]
[#local line="" /]
[#local lines=[] /]
[#list words as word]
[#if lines?size == 0]
[#local len = len1 /]
[#else]
[#local len = lenn /]
[/#if]
[#if (line?length + word?length + 1 > len)]
[#local lines = lines + [line?trim] /]
[#local line = word + " " /]
[#else]
[#local line = line + word + " " /]
[/#if]
[/#list]
[#if line != ""]
[#local lines = lines + [line?trim] /]
[/#if]
[#return lines /]
[/#function]
[#--
-- Emits a string "s" as a formatted text, the first line is prefixed by the
-- "p1" parameter, subsequent lines are prefixed by the "pn" paramenter.
-- Emitted lines are no longer than the "len" parameter.
-- White spaces are normalized between words.
--]
[#macro FormatStringAsText p1 pn s len]
[#local lines = StringToText(len - p1?length, len - pn?length, s) /]
[#list lines as line]
[#if line_index == 0]
${p1}${line}
[#else]
${pn}${line}
[/#if]
[/#list]
[/#macro]
[#--
-- Emits a C function body code reformatting the indentation using the
-- specified tab size and line prefix.
--]
[#macro EmitIndentedCCode start tab ccode]
[#assign lines = ccode?string?split("^", "rm") /]
[#list lines as line]
[#if (line_index > 0) || (line?trim?length > 0)]
[#if line?trim?length > 0]
[#if line[0] == "#"]
${line?chop_linebreak}
[#else]
${start + line?chop_linebreak}
[/#if]
[#else]
[/#if]
[/#if]
[/#list]
[/#macro]

View File

@ -0,0 +1,103 @@
[#ftl]
[#--
ChibiOS/RT - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--]
[#import "/@ftllibs/libutils.ftl" as utils /]
[#if xml.instance[0]??]
[#assign instance = xml.instance /]
[#else]
[#list xml.*.application.instances.instance as inst]
[#if inst.@id?string == "org.chibios.spc5.components.portable.chibios_unitary_tests_engine"]
[#assign instance = inst /]
[#break]
[/#if]
[/#list]
[/#if]
[#assign conf = {"instance":instance} /]
[#assign prefix_lower = conf.instance.global_data_and_code.code_prefix.value[0]?trim?lower_case /]
[#assign prefix_upper = conf.instance.global_data_and_code.code_prefix.value[0]?trim?upper_case /]
[@pp.dropOutputFile /]
[@pp.changeOutputFile name=prefix_lower+"test_root.c" /]
[@utils.EmitIndentedCCode "" 2 conf.instance.description.copyright.value[0] /]
/**
* @mainpage Test Suite Specification
[#if conf.instance.description.introduction.value[0]?trim != ""]
[@utils.FormatStringAsText " * "
" * "
utils.WithDot(conf.instance.description.introduction.value[0]?trim?cap_first)
72 /]
[#else]
* No introduction.
[/#if]
*
* <h2>Test Sequences</h2>
[#if conf.instance.sequences.sequence?size > 0]
[#list conf.instance.sequences.sequence as sequence]
* - @subpage ${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")}
[/#list]
* .
[#else]
* No test sequences defined in the test suite.
[/#if]
*/
/**
* @file ${prefix_lower}test_root.c
* @brief Test Suite root structures code.
*/
#include "hal.h"
#include "${prefix_lower}test_root.h"
#if !defined(__DOXYGEN__)
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/**
* @brief Array of test sequences.
*/
const testsequence_t * const ${prefix_lower}test_suite_array[] = {
[#list conf.instance.sequences.sequence as sequence]
[#if sequence.condition.value[0]?trim?length > 0]
#if (${sequence.condition.value[0]}) || defined(__DOXYGEN__)
[/#if]
&${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")},
[#if sequence.condition.value[0]?trim?length > 0]
#endif
[/#if]
[/#list]
NULL
};
/**
* @brief Test suite root structure.
*/
const testsuite_t ${prefix_lower}test_suite = {
"${utils.WithoutDot(conf.instance.description.brief.value[0]?trim)}",
${prefix_lower}test_suite_array
};
/*===========================================================================*/
/* Shared code. */
/*===========================================================================*/
[#if conf.instance.global_data_and_code.global_code.value[0]?trim?length > 0]
[@utils.EmitIndentedCCode "" 2 conf.instance.global_data_and_code.global_code.value[0] /]
[/#if]
#endif /* !defined(__DOXYGEN__) */

View File

@ -0,0 +1,74 @@
[#ftl]
[#--
ChibiOS/RT - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--]
[#import "/@ftllibs/libutils.ftl" as utils /]
[#if xml.instance[0]??]
[#assign instance = xml.instance /]
[#else]
[#list xml.*.application.instances.instance as inst]
[#if inst.@id?string == "org.chibios.spc5.components.portable.chibios_unitary_tests_engine"]
[#assign instance = inst /]
[#break]
[/#if]
[/#list]
[/#if]
[#assign conf = {"instance":instance} /]
[#assign prefix_lower = conf.instance.global_data_and_code.code_prefix.value[0]?trim?lower_case /]
[#assign prefix_upper = conf.instance.global_data_and_code.code_prefix.value[0]?trim?upper_case /]
[@pp.dropOutputFile /]
[@pp.changeOutputFile name=prefix_lower+"test_root.h" /]
[@utils.EmitIndentedCCode "" 2 conf.instance.description.copyright.value[0] /]
/**
* @file ${prefix_lower}test_root.h
* @brief Test Suite root structures header.
*/
#ifndef ${prefix_upper}TEST_ROOT_H
#define ${prefix_upper}TEST_ROOT_H
#include "ch_test.h"
[#list conf.instance.sequences.sequence as sequence]
#include "${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")}.h"
[/#list]
#if !defined(__DOXYGEN__)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
extern const testsuite_t ${prefix_lower}test_suite;
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Shared definitions. */
/*===========================================================================*/
[#if conf.instance.global_data_and_code.global_definitions.value[0]?trim?length > 0]
[@utils.EmitIndentedCCode "" 2 conf.instance.global_data_and_code.global_definitions.value[0] /]
[/#if]
#endif /* !defined(__DOXYGEN__) */
#endif /* ${prefix_upper}TEST_ROOT_H */

View File

@ -0,0 +1,240 @@
[#ftl]
[#--
ChibiOS/RT - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--]
[#import "/@ftllibs/libutils.ftl" as utils /]
[@pp.dropOutputFile /]
[#if xml.instance[0]??]
[#assign instance = xml.instance /]
[#else]
[#list xml.*.application.instances.instance as inst]
[#if inst.@id?string == "org.chibios.spc5.components.portable.chibios_unitary_tests_engine"]
[#assign instance = inst /]
[#break]
[/#if]
[/#list]
[/#if]
[#assign conf = {"instance":instance} /]
[#assign prefix_lower = conf.instance.global_data_and_code.code_prefix.value[0]?trim?lower_case /]
[#assign prefix_upper = conf.instance.global_data_and_code.code_prefix.value[0]?trim?upper_case /]
[#list conf.instance.sequences.sequence as sequence]
[@pp.changeOutputFile name=prefix_lower+"test_sequence_" + (sequence_index + 1)?string("000") + ".c" /]
[@utils.EmitIndentedCCode "" 2 conf.instance.description.copyright.value[0] /]
#include "hal.h"
#include "${prefix_lower}test_root.h"
/**
* @file ${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")}.c
* @brief Test Sequence ${(sequence_index + 1)?string("000")} code.
*
* @page ${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")} [${(sequence_index + 1)?string}] ${utils.WithoutDot(sequence.brief.value[0]?string)}
*
* File: @ref ${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")}.c
*
* <h2>Description</h2>
[@utils.FormatStringAsText " * "
" * "
utils.WithDot(sequence.description.value[0]?string)
72 /]
*
[#if sequence.condition.value[0]?trim?length > 0]
* <h2>Conditions</h2>
* This sequence is only executed if the following preprocessor condition
* evaluates to true:
* - ${sequence.condition.value[0]}
* .
*
[/#if]
* <h2>Test Cases</h2>
[#if sequence.cases.case?size > 0]
[#list sequence.cases.case as case]
* - @subpage ${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_index + 1)?string("000")}
[/#list]
* .
[#else]
* No test cases defined in the test sequence.
[/#if]
*/
[#if sequence.condition.value[0]?trim?length > 0]
#if (${sequence.condition.value[0]}) || defined(__DOXYGEN__)
[/#if]
/****************************************************************************
* Shared code.
****************************************************************************/
[#if sequence.shared_code.value[0]?trim?length > 0]
[@utils.EmitIndentedCCode "" 2 sequence.shared_code.value[0] /]
[/#if]
/****************************************************************************
* Test cases.
****************************************************************************/
[#list sequence.cases.case as case]
[#-- Building the sequence of the requirements covered by
this test case.--]
[#assign reqseq = [] /]
[#list case.steps.step as step]
[#assign reqseq = reqseq + step.tags.value[0]?string?trim?word_list /]
[/#list]
[#assign reqseq = reqseq?sort /]
[#-- Checking if a condition should be generated.--]
[#if case.condition.value[0]?trim?length > 0]
#if (${case.condition.value[0]?trim}) || defined(__DOXYGEN__)
[/#if]
[#-- Header generation.--]
/**
* @page ${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_index + 1)?string("000")} [${(sequence_index + 1)?string}.${(case_index + 1)?string}] ${utils.WithoutDot(case.brief.value[0])}
*
* <h2>Description</h2>
[@utils.FormatStringAsText " * "
" * "
utils.WithDot(case.description.value[0]?string)
72 /]
*
[#if case.condition.value[0]?trim?length > 0]
* <h2>Conditions</h2>
* This test is only executed if the following preprocessor condition
* evaluates to true:
* - ${case.condition.value[0]}
* .
*
[/#if]
* <h2>Test Steps</h2>
[#list case.steps.step as step]
[@utils.FormatStringAsText " * - "
" * "
utils.WithDot("[" + (sequence_index + 1)?string + "." + (case_index + 1)?string + "." + (step_index + 1)?string + "] " + step.description.value[0]?string)
72 /]
[/#list]
[#if case.steps.step?size > 0]
* .
[/#if]
[#if reqseq?size > 0]
* <h2>Covered Requirements</h2>
[#assign reqs = "" /]
[#list reqseq as r]
[#assign reqs = reqs + r /]
[#if r_has_next]
[#assign reqs = reqs + ", " /]
[/#if]
[/#list]
[@utils.FormatStringAsText " * "
" * "
utils.WithDot(reqs)
72 /]
[/#if]
*/
[#if case.various_code.setup_code.value[0]?trim?length > 0]
static void ${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_index + 1)?string("000")}_setup(void) {
[@utils.EmitIndentedCCode " " 2 case.various_code.setup_code.value[0] /]
}
[/#if]
[#if case.various_code.teardown_code.value[0]?trim?length > 0]
static void ${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_index + 1)?string("000")}_teardown(void) {
[@utils.EmitIndentedCCode " " 2 case.various_code.teardown_code.value[0] /]
}
[/#if]
static void ${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_index + 1)?string("000")}_execute(void) {
[#if case.various_code.local_variables.value[0]?trim?length > 0]
[@utils.EmitIndentedCCode " " 2 case.various_code.local_variables.value[0] /]
[/#if]
[#list case.steps.step as step]
[@utils.FormatStringAsText " /* "
" "
utils.WithDot("[" + (sequence_index + 1)?string + "." + (case_index + 1)?string + "." + (step_index + 1)?string + "] " + step.description.value[0]?string) + "*/"
72 /]
test_set_step(${(step_index + 1)?string});
{
[#if step.tags.value[0]?string?trim != ""]
[#assign reqseq = step.tags.value[0]?string?trim?word_list?sort /]
[#assign reqs = "" /]
[#list reqseq as r]
[#assign reqs = reqs + r /]
[#if r_has_next]
[#assign reqs = reqs + ", " /]
[/#if]
[/#list]
[@utils.FormatStringAsText " /* @covers "
" "
utils.WithDot(reqs) + "*/"
72 /]
[/#if]
[#if step.code.value[0]?trim?length > 0]
[@utils.EmitIndentedCCode " " 2 step.code.value[0] /]
[/#if]
}
test_end_step(${(step_index + 1)?string});
[/#list]
}
static const testcase_t ${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_index + 1)?string("000")} = {
"${utils.WithoutDot(case.brief.value[0]?string)}",
[#if case.various_code.setup_code.value[0]?trim?length > 0]
${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_index + 1)?string("000")}_setup,
[#else]
NULL,
[/#if]
[#if case.various_code.teardown_code.value[0]?trim?length > 0]
${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_index + 1)?string("000")}_teardown,
[#else]
NULL,
[/#if]
${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_index + 1)?string("000")}_execute
};
[#if case.condition.value[0]?trim?length > 0]
#endif /* ${case.condition.value[0]?trim} */
[/#if]
[/#list]
/****************************************************************************
* Exported data.
****************************************************************************/
/**
* @brief Array of test cases.
*/
const testcase_t * const ${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")}_array[] = {
[#list sequence.cases.case as case]
[#if case.condition.value[0]?trim?length > 0]
#if (${case.condition.value[0]?trim}) || defined(__DOXYGEN__)
[/#if]
&${prefix_lower}test_${(sequence_index + 1)?string("000")}_${(case_index + 1)?string("000")},
[#if case.condition.value[0]?trim?length > 0]
#endif
[/#if]
[/#list]
NULL
};
/**
* @brief ${utils.WithDot(sequence.brief.value[0]?string)}
*/
const testsequence_t ${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")} = {
"${utils.WithoutDot(sequence.brief.value[0]?string)}",
${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")}_array
};
[#if sequence.condition.value[0]?trim?length > 0]
#endif /* ${sequence.condition.value[0]} */
[/#if]
[/#list]

View File

@ -0,0 +1,47 @@
[#ftl]
[#--
ChibiOS/RT - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--]
[#import "/@ftllibs/libutils.ftl" as utils /]
[@pp.dropOutputFile /]
[#if xml.instance[0]??]
[#assign instance = xml.instance /]
[#else]
[#list xml.*.application.instances.instance as inst]
[#if inst.@id?string == "org.chibios.spc5.components.portable.chibios_unitary_tests_engine"]
[#assign instance = inst /]
[#break]
[/#if]
[/#list]
[/#if]
[#assign conf = {"instance":instance} /]
[#assign prefix_lower = conf.instance.global_data_and_code.code_prefix.value[0]?trim?lower_case /]
[#assign prefix_upper =conf. instance.global_data_and_code.code_prefix.value[0]?trim?upper_case /]
[#list conf.instance.sequences.sequence as sequence]
[@pp.changeOutputFile name=prefix_lower+"test_sequence_" + (sequence_index + 1)?string("000") + ".h" /]
[@utils.EmitIndentedCCode "" 2 conf.instance.description.copyright.value[0] /]
/**
* @file ${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")}.h
* @brief Test Sequence ${(sequence_index + 1)?string("000")} header.
*/
#ifndef ${prefix_upper}TEST_SEQUENCE_${(sequence_index + 1)?string("000")}_H
#define ${prefix_upper}TEST_SEQUENCE_${(sequence_index + 1)?string("000")}_H
extern const testsequence_t ${prefix_lower}test_sequence_${(sequence_index + 1)?string("000")};
#endif /* ${prefix_upper}TEST_SEQUENCE_${(sequence_index + 1)?string("000")}_H */
[/#list]

View File

@ -59,7 +59,7 @@
<xs:element name="condition" type="conditionType" maxOccurs="1"
minOccurs="1">
</xs:element>
<xs:element name="shared_code" type="global_data_and_codeType"
<xs:element name="shared_code" type="codeWrapperType"
maxOccurs="1" minOccurs="1">
</xs:element>
<xs:element name="cases" type="casesType" maxOccurs="1"
@ -187,4 +187,6 @@
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="instance" type="instanceType"></xs:element>
</xs:schema>

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<instance
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.chibios.org/xml/schema/unittest/unittest.xsd">
<description>
<brief>
<value>Example Test Suite.</value>
</brief>
<copyright>
<value><![CDATA[/*
ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 3 of the License.
ChibiOS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/]]></value>
</copyright>
<introduction>
<value>Test suite for EXAMPLE. The purpose of this suite is to
perform unit tests on the EXAMPLE modules.</value>
</introduction>
</description>
<global_data_and_code>
<code_prefix>
<value>example_</value>
</code_prefix>
<global_definitions>
<value><![CDATA[
#define EXAMPLE_GLOBAL_DEFINITIONS_HERE 1
]]></value>
</global_definitions>
<global_code>
<value><![CDATA[
#define EXAMPLE_GLOBAL_CODE_HERE 1
]]></value>
</global_code>
</global_data_and_code>
<sequences>
<sequence>
<type>
<value>Internal Tests</value>
</type>
<brief>
<value>This is a sequence.</value>
</brief>
<details>
<value>A sequence is a collection of test cases executed in sequence
sharing static code and data.</value>
</details>
<condition>
<value />
</condition>
<shared_code>
<value><![CDATA[
#include "example.h"
]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>This is a test case.</value>
</brief>
<details>
<value>A test case is a small program testing a specific feature
of the system under test. Test cases should not depend on things done in
previous test cases because those could have failed leaving an unexpected
state.</value>
</details>
<condition>
<value />
</condition>
<wrappers>
<setup_code>
<value><![CDATA[
/* Put here code that prepares for the test case execution, this code is
executed before the test case.*/
]]></value>
</setup_code>
<teardown_code>
<value><![CDATA[
/* Put here code undoes what the test cases did, as a good practice this code
should be able to undo things regardles of how the test case succeeded or
failed.*/
]]></value>
</teardown_code>
<local_variables>
<value><![CDATA[
/* Declare here automatic variables used in the test case, it is good practice
to not initialize values here.*/
]]></value>
</local_variables>
</wrappers>
<steps>
<step>
<details>
<value>This is a test case step. A step is an elementary
piece of code part of a test case.</value>
</details>
<tags>
<value />
</tags>
<code>
<value><![CDATA[
/* Put here the step code.*/
]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
</sequences>
</instance>