1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
|
#######################################################################################################################
Tango Test Suite
#######################################################################################################################
This is a guide to the Tango Test Suite use and development. The guide is split in 2 main sections addressed to the
user and developer respectively. Please acquaint yourself with the contents of this file before the use of the framework.
Outline:
--------
1. ======== User
1.1. ~~~~~~ Compilation
1.1.1. ---- Create a profile file
1.1.2. ---- Execute `make profile=myprofile`
1.2. ~~~~~~ Execution
1.2.1. ---- Preconditions
1.2.1. ---- Control System configuration
1.2.2. ---- Test Suites execution
2. ======== Developer
2.1. ~~~~~~ Create a new test suite
2.2. ~~~~~~ Command line arguments
2.2.1. ---- Argument types
2.2.2. ---- Declaring arguments
2.2.3. ---- Predefined arguments
2.3. ~~~~~~ Create a test case
2.3.1. ---- Assertions
2.3.2. ---- Loops
2.3.3. ---- Restore mechanism
2.4. ~~~~~~ Tango specific files in CxxTest framework
=======================================================================================================================
1. User
=======================================================================================================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1.1. Compilation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Test Suite currently comprises a set of independent executables examining different Tango features and one
executable utilising CxxTest framework, which consists of test suites conforming to unit test standard.
The source code of the independent executables is located in the following directories:
- asyn
- event
- old_tests
The source code of the CxxTest test suites resides in:
- new_tests
!! -- NB -- !!
The source files are required to have '.cpp' extension and unique names. The files being a part of the CxxTest
framework must have a 'cxx_' prefix.
!! -- NB -- !!
Store all files prefixed with 'cxx_' in one directory.
To compile the binaries you need to:
- create a profile file
- execute `make profile=myprofile`
-----------------------------------------------------------------------------------------------------------------------
1.1.1. Create a profile file
-----------------------------------------------------------------------------------------------------------------------
Go to 'makeprofiles' directory, copy the 'default.profile' file and rename it (to e.g. 'myprofile.profile').
Open 'makeprofiles/myprofile.profile' file and define parameters. In this file you indicate paths to 'include' and 'lib'
directories required to run the test suite. There are two sets of parameters: mandatory and optional. Acquaint yourself
with the comments section in 'makeprofiles/default.profile' file to fully understand the meaning of the parameters.
Below there is a brief tutorial on how to set the parameters:
Define TANGO_BASE, TANGO_OMNI_BASE, LOG4TANGO_BASE, TANGO_ZMQ_BASE indicating the directories which contain 'include' and 'lib'
folders for Tango, omniORB, log4tango and ZMQ libraries.
If your Tango 'include' or 'lib' directories are different then TANGO_BASE/include or TANGO_BASE/lib define
TANGO_INCLUDE_DIR or TANGO_LIB_DIR which will take precedence over TANGO_BASE/include or TANGO_BASE/lib respectively.
Defining TANGO_INCLUDE_DIR you can provide more than one directory.
By default all files from the following directories will be compiled:
- asyn
- event
- old_tests
- new_tests
The '*.o' object files will be stored in 'obj' directory and the binaries in the 'bin' directory.
If you want to:
- modify the output directories - define OBJ_DIR and BIN_DIR parameters;
- add a directory containing extra files to compile - define TEST_DIRS_EXTRA;
- compile files only from the selected directories - define TEST_DIRS;
All files prefixed with 'cxx_' will be compiled into one executable named 'runner' in the alphabetical order.
If you wish to compile only the runner, define TEST_DIRS indicating only the folder containing the 'cxx_' files.
You can also compile exclusive files of your choice by listing them in COMPILE_FILES parameter (both the independent
ones and the 'cxx_' files). In such case, the 'cxx_' files will be compiled into the 'runner' executable in the
provided order. To bring back the alphabetical order, set 'SORT_ALPHABETICALLY_CXX = true'.
If there are any files you want to exclude from compilation list them in EXCLUDE_FILES property.
By default 'c++' compiler is used. To choose a different one, redefine the CC property.
If you need to add some extra compiler parameters on top of the default ones (-g -Wall -Wextra -DVALGRIND -D_PTHREADS
-D_REENTRANT) list them in CXXFLAGS_EXTRA property. To totally redefine the compiler parameters set CXXFLAGS.
To add extra linker options use LFLAGS_EXTRA.
-----------------------------------------------------------------------------------------------------------------------
1.1.2. Execute `make profile=myprofile`
-----------------------------------------------------------------------------------------------------------------------
After configuring the 'myprofile.profile' file, to compile the test suite binaries it is enough to execute:
- `make profile=myprofile`
The profile name 'myprofile' is the name of the '.profile' file created in the previous step.
Executing mere `make` will load the 'default.profile' settings.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1.2. Execution
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-----------------------------------------------------------------------------------------------------------------------
1.2.1. Preconditions
-----------------------------------------------------------------------------------------------------------------------
Before running the test suite make sure that Tango Starter process is not running.
To check if the process is running type in command line:
- `ps -ef | grep -i starter`
In your control system there has to be a test device server set up (e.g. 'devTest'), consisting of at least 3 devices
(e.g. 'dev/test/1', 'dev/test/2' and 'dev/test/3') from the 'DevTest' class.
-----------------------------------------------------------------------------------------------------------------------
1.2.1. Control System configuration
-----------------------------------------------------------------------------------------------------------------------
Go to the 'bin' directory and execute 'conf_devtest' which will configure the 'devTest' device server properties in the database. These
properties will then be tested in the test suite. Skipping this step will cause the test suites to fail.
!! -- NB -- !!
Upon execution of 'conf_devtest' a new pseudo device server is registered in the database, namely: 'DsCache/test'.
Make sure no server of such name exists, otherwise refrain from executing 'conf_devtest'.
-----------------------------------------------------------------------------------------------------------------------
1.2.2. Test Suites execution
-----------------------------------------------------------------------------------------------------------------------
Use 'runtest' script to execute all test suites.
You can also call each executable independently. Remember - the 'cxx' test suites are all embedded in one executable:
'runner'.
=======================================================================================================================
2. Developer
=======================================================================================================================
This part is a guide to test suites development with the use of the CxxTest framework.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.1. Create a new test suite
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To create a new test suite simply copy and rename the 'cxx_template.cpp' file which can be found in the 'new_tests'
directory.
Modify the header guard 'TemplateTestSuite_h' (lines 1, 2 and the last one) by providing your test suite name. Follow
the convention: if you name your file 'cxx_my_test.cpp' the header guard should take this form - 'MyTestTestSuite_h'.
Define the test suite class name replacing 'TemplateTestSuite' (lines 15 and 17). Follow the convention (above example
case: 'MyTestTestSuite').
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.2. Command line arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In the 'Arguments check' section define what command line arguments should be provided if your test suites are dependent
on user configuration (like device names or loop repetitions).
-----------------------------------------------------------------------------------------------------------------------
2.2.1. Argument types
-----------------------------------------------------------------------------------------------------------------------
Some test suites require arguments which are common for all (e.g. the device on which to execute the test suite or the
database server name), for this reason they have been predefined (just the definition of the argument, not its value);
however some other test suites need custom arguments (which make sense only locally in the test suite);
hence there are 3 types of arguments distinguished:
- params (predefined parameters) - commonly used in all test suites, like device1, device2 and device3 on which the
test suite will be executed or database server name, full device server name, etc.;
they are provided in the command line as follows: '--' + parameter name + '=' + parameter value, e.g.:
`./runner --device1=dev/test/1 --fulldsname=devTest/myname --dbserver=sys/database/2`
- params_opt (optional parameters) - same as params but not required by the test suite (like a loop parameter); they
are provided in the command line the same way as params but processed by the test suite in a different (optional) way
`./runner --loop=5`
- params_loc (local parameters) - these are the test suite custom parameters which are not predefined within the CxxTest
framework as they have a meaning only locally in the test suite;
they are read from the command line the same way as params:
`./runner --my_param_loc=my_param_loc_value`
-----------------------------------------------------------------------------------------------------------------------
2.2.2. Declaring arguments
-----------------------------------------------------------------------------------------------------------------------
To declare an argument and obtain its value use the following methods, e.g.:
- std::string my_param_value = CxxTest::TangoPrinter::get_param("my_param");
this will declare a mandatory, predefined parameter (see the list below); predefined parameters are those which are
common for different test suites and therefore have been defined in the Test Framework itself (namely in TangoPrinter.h);
the params in the code are defined by the 'param_name' and provided by the user in the command line as
'--param_name=param_value';
calling:
std::string full_ds_name_value = CxxTest::TangoPrinter::get_param("fulldsname");
and executing:
`./runner --fulldsname=devTest/myname`
will assign 'full_ds_name_value = "devTest/myname"'; if the user does not provide all mandatory parameters, the 'runner'
will terminate and print out all expected mandatory parameters along with their descriptions;
- std::string my_param_opt_value = CxxTest::TangoPrinter::get_param_opt("my_param_opt");
this will declare an optional parameter; optional parameters have the same definition, meaning and use as the
mandatory parameters apart from that they are not obligatory. If the user does not provide some/any optional
parameters the 'runner' will execute normally.
- std::string my_param_loc_value = CxxTest::TangoPrinter::get_param_loc("my_param_loc","description of what 'my_param_loc' is"); or
std::string my_param_loc_value = CxxTest::TangoPrinter::get_param_loc("my_param_loc");
this will declare a mandatory local parameter named 'my_param_loc' description of which is optional; their use in the
command line is the same as the use of 'params' with the only difference that their definitions (names) are not
registered in the global (Test Framework) scope.
!! -- NB -- !!
Note that 'params', 'params_opt' and 'params_loc' are order-independent and can be mixed up in the command line.
!! -- NB -- !!
There are parameters acting as toggles to which you do not assign any value (e.g. verbose: '--v'). To check if
a parameter has been set by the user (provided in the command line) simply add in your code:
'bool param_set = CxxTest::TangoPrinter::is_param_set("param_name");'
e.g.:
'bool verbose_on = CxxTest::TangoPrinter::is_param_set("verbose");'.
!! -- NB -- !!
Note that 'params' are the commonly recognised and defined parameters like 'device1' - device nr 1 on which the test
suite will be run or 'fulldsname' - Tango fully qualified name of the device server.
On the contrary 'params_loc' are these parameters which have a meaning only locally in the Test Suite therefore they
are not defined on the global (Test Framework) scope thus their description has to be provided, e.g.:
- std::string my_param_loc_value = CxxTest::TangoPrinter::get_param_loc("my_param_loc","description of what 'my_param_loc' is");
All of the following calls are logically equivalent:
`./runner --device1=dev/test/1 --fulldsname=devTest/myname --dbserver=sys/database/2 --loop=5`
`./runner --fulldsname=devTest/myname --dbserver=sys/database/2 --loop=5 --device1=dev/test/1`
`./runner --loop=5 --device1=dev/test/1 --dbserver=sys/database/2 --fulldsname=devTest/myname`
-----------------------------------------------------------------------------------------------------------------------
2.2.3. Predefined arguments
-----------------------------------------------------------------------------------------------------------------------
Below is the list of predefined parameters along with their descriptions:
DEFINITION COMMAND LINE DESCRIPTION
---------- ------------ -----------
? --? help, lists all possible parameters
-? -? help, lists all possible parameters
help --help help, lists all possible parameters
-help -help help, lists all possible parameters
loop --loop= execute test cases marked with '__loop' suffix the indicated number of times
suiteloop --suiteloop= execute test suites marked with '__loop' suffix the indicated number of times
device1 --device1= device1 name, e.g. test/device/1
device2 --device2= device2 name, e.g. test/device/2
device3 --device3= device3 name, e.g. test/device/3
fulldsname --fulldsname= full device server name, e.g. devTest/myserver
clienthost --clienthost= client host's fully qualified domain name, e.g. mypc.myinstitute.com (small caps)
serverhost --serverhost= fully qualified domain name of the host on which the server is running, e.g. myserver.myinstitute.com (small caps)
serverversion --serverversion= IDL version, e.g. 4
dbserver --dbserver= database server name, e.g. sys/database/2
loglevel --loglevel= default device logging level, e.g. 0
dsloglevel --dsloglevel= default device server logging level, e.g. 3
devtype --devtype= device type, e.g. TestDevice
docurl --docurl= current documentation URL, e.g. http://www.tango-controls.org
outpath --outpath= device server logging target directory, e.g. /tmp/
refpath --refpath= directory where the 'compare test' reference files (*.out) are stored
devicealias --devicealias= device1 alias
attributealias --attributealias= Short_attr alias
!! -- NB -- !!
To the developers of the test suite. If you find a parameter fequently apparing in different test suites which is not
on the list above, please append it to the list which can be found in the body of 'create_params()' method in the
'TangoPrinter.h' file in 'cxxtest/include/cxxtest' directory.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.3. Create a test case
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To create your test case write a void function with empty arguments. Add prefix 'test_' to the name of the function, e.g.:
- 'void test_MyTestCase() { /* your code here */ }'
All functions with the 'test_' prefix are interpreted by the CxxTest framework as test cases. Other functions are
ignored by the framework (but can be called from within the test case code).
The test cases are executed in the order of their definition in the 'cpp' file.
!! -- NB -- !!
By convention use CAPITAL letters for each word in the name of your test case as the CxxTest framework will parse the
name truncating the 'test_' prefix (and optionally '__loop' suffix) and print out the words separated by space, e.g.:
'test_MyTestCase' --> 'my test case'.
-----------------------------------------------------------------------------------------------------------------------
2.3.1. Assertions
-----------------------------------------------------------------------------------------------------------------------
To perform assertions in your test cases, use one of the CxxTest macros:
- TS_ASSERT(condition) - verifies the condition, if false - the test case fails
- TS_ASSERT_THROWS_NOTHING(instruction) - fails if instruction throws any exception
- TS_ASSERT_THROWS(instruction, exception) - succeeds if instruction throws the exception, otherwise fails
- TS_ASSERT_THROWS_ASSERT(instruction, exception, TS_ASSERT(exception dependent condition)) - succeeds if instruction
throws the exception and if the condition (which can use the thrown exception) is true, otherwise fails
- TS_FAIL(message) - fails unconditionally printing out the message
For more information on assertions see:
http://cxxtest.com/cxxtest/doc/guide.html
!! -- NB -- !!
The 'runner' terminates on the first test case failure.
-----------------------------------------------------------------------------------------------------------------------
2.3.2. Loops
-----------------------------------------------------------------------------------------------------------------------
To execute a test suite in a loop, append '__loop' suffix to the test suite name (lines 15 and 17 in cxx_template.cpp),
e.g. 'MyTestTestSuite__loop'. The test suite will execute in a loop only if the 'suiteloop' parameter is defined.
If the user executes:
- `./runner --suiteloop=10`
the test suite will be run 10 times.
To execute a test case in a loop, append '__loop' suffix to the test case name, e.g. 'test_MyTestCase__loop()'. The
test case will execute in a loop only if the 'loop' parameter is defined.
If the test case fails, there is a piece of information printed out to indicate the test case and test suite iteration
in which it happened.
-----------------------------------------------------------------------------------------------------------------------
2.3.3. Restore mechanism
-----------------------------------------------------------------------------------------------------------------------
If your test case modifies some default (device) configuration, use restore points to ensure the default configuration
will always be recovered.
Imagine you modify the default configuration in your test case then check if some feature works as expected and it fails
before you bring back the old configuration. Setting restore points guarantees that the default configuration will be
recovered by executing the corresponding code located in the test suite TearDown() method which is called always before
the test suite terminates, even if a test case fails.
To set the restore point, give it a name. e.g. 'my_restore_point' and use:
- CxxTest::TangoPrinter::restore_set("my_restore_point");
To remove the restore point call:
- CxxTest::TangoPrinter::restore_unset("my_restore_point");
In the 'Clean up' section write the code recovering the default configuration:
- if(CxxTest::TangoPrinter::is_restore_set("my_restore_point")) { /* restore the defaults here */ }
Example:
virtual ~SUITE_NAME()
{
// Clean up --------------------------------------------------------
if(CxxTest::TangoPrinter::is_restore_set("my_restore_point"))
{
/* recover the default configuration */
}
}
void test_MyTestCase()
{
/* modify the default configuration */
CxxTest::TangoPrinter::restore_set("my_restore_point");
// your code here, e.g. assertion which may fail
// if it fails, the next line will not be executed, but thanks to the restore mechanism,
// the code from the 'Clean up' section will be called
/* recover the default configuration */
CxxTest::TangoPrinter::restore_unset("my_restore_point");
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.4. Tango specific files in CxxTest framework
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To support Tango, the CxxTest framework requires 2 extra files:
- 'cxxtest/template/tango_template.tpl' and
- 'cxxtest/include/cxxtest/TangoPrinter.h'.
If you wish to add some extra functionality to the testing framework, these are the only files you can modify. They are
not shipped with the CxxTest and have to be manually added in case a new, plain version of CxxTest is downloaded.
|