Basically, Component Testing for C++ interacts with your source code through a scripting language called C++ Test Script Language. You use the Test RealTime GUI or command line tools to set up your test campaign, write your test scripts, run your tests and view the test results. Object Testing’s mode of operation is twofold:
- C++ Contract Check scripts, which instrument the code under test, verifying behavioral assertions during execution of the code.
- C++ Test Driver scripts describe a test harness that stimulates and checks basic I/O of the code under test.
When the test is executed, Component Testing for C++ compiles both the test scripts and the source under test, then instruments the source code and generates a test driver. Both the instrumented application and the test driver provide output data which is displayed within Test RealTime
How component testing for C++ works?
When a test node is executed, the Component Testing Test Compiler (atoprepro) compiles both the test scripts and the source under test. This preprocessing creates an .ots file (for each scripts file in C++ test node). The resulting source code generates a test driver.
If any Runtime Analysis tools (Code coverage, Memory profiling, Runtime Tracing) are associated with the test node, then the source code is also instrumented with the Instrumentor (attolcpp) tool.
The test driver, TDP, stubs and dependency files all make up the test harness.
The test harness interacts with the source code under test and produces test results. Test execution creates a .tdf file.
The .ots and .tdf files are processed together the Component Testing Report Generator (atopospro). The output is the .xrd report file, which can be viewed and controlled in the Test RealTime GUI.
Of course, these steps are mostly transparent to the user when the test node is executed in the Test RealTime GUI.
The process of testing will be shown as below model
C++ Test Nodes
The project structure of the Rational Test RealTime GUI uses test nodes to represent your Component Testing test harness.
Test nodes created for Component Testing for C++ use the following structure
- C++ Test Node: represents the Component Testing for C++ test harness
- <script>.otc: is the Contract-Check test script
- <script>.otd: is the test driver script
- <script>.stb: is the stub file
- <script>.dcl: is the declaration file
- <source>.cpp: is the source file under test
- <source>.cpp: is an additional source file
C++ Contract Check Script
The C++ Contract Check script allows you to test invariants and state charts as well as wraps for each method of the class.
The Contract Check script is contained in an .otc file, whose name matches the name of the file containing the class definition.
C++ Contract Check scripts are written in C++ Contract Check Language, which is part of the C++ Test Script language designed for Component Testing for C++.
C++ Test Driver Script
The C++ Test Driver Script stimulates the source code under test to test assertions on a cluster of classes.
The test driver script itself is contained in an .otd file and may call two optional files:
- A declaration file (.dcl) that contains C++ code that ensures the types, class, variables and functions needed by your test script will be available in your code.
- A stub file (.stb) whose purpose is to define variables, functions and methods which are to be stubbed.
Using a separate declaration and stub files is optional. It is possible to include all or certain declarations and stubs directly within the test driver script file.
See the section 2.2 for the semantics of the C++ test driver language.
NOTE: An .otc contract-check script must be executed before an .otd Test Driver script, therefore the order in which both script types appear in the Test node is critical. This is important if you are manually creating a test node.
The Source under test are source files containing the code you want to test. These files must contain either the definition of the classes targeted by the test, or method implementations of those classes.
NOTE: Source files can be either body files (.c, .cpp, etc.) or header files (.h), but it is usually recommended to select the body file. Specifying both header and body files as Source under test is unnecessary.
Additional source files are source files that are required by the test script, but not actually tested. For example, with Component Testing for C++, Visual C++ resource files can be compiled inside a test node by specifying them as additional files.
Additional header files (.h) are not handled in the same way as additional body files (.cc, .C, or .cpp):
- Body files: With a body file, the Test Generation Wizard considers that the compiled file will be linked with your test program. This means that all defined variables and routines are considered as defined, and therefore not stubbed.
- Header files: With a header file (a file containing only declarations), the Test Generation Wizard considers that all the entities declared in the source file itself (not in included files) are defined. Typically, you would use additional header files if you only have a .h file under test and a matching object file (.o or .obj), but not the actual source file (.cc, .C, or .cpp).
You can toggle a source file from under test to additional by changing the Instrumentation property in the Properties Window dialog box.
Component Testing for C++ supports assertions only for fully generic and fully specialized template classes. Partial specializations are not supported.
A contract referring to a generic template class is applied to every instance of this template class, unless a specific contract has been defined for an instance of this template class.
There may be a state machine description associated with the template class, and another with a template specialization. In such a case, the latter applies to the specific template instance, and the first applies to any other instance.
Same mechanism for invariant definition (There may be invariants associated with the template class, and other invariants with a template specialization. In such a case, the latter ones apply to the specific template instance, while the first one apply to any other instance.)
A wrap defined within a generic template class contract does not apply to specialization of the associated method. If you want to test a method specialization, you must define a WRAP into the contract associated to the class instance the method specialization belongs to.
It is not possible to define WRAP for template methods within a non-template class.