How To Use
|
Overview
Within a typical test environment the system under test (SUT) usually needs some communication partners within its runtime environment. These communication partners are often simulated, e.g. instead of using the real components simple fake objects are used, which enable the following testing possibilities:
This page gives a short overview about the possibility to implement a simulated object using base class RegisteredSimulatedObject / SimulatedObjectBase and about controlling behaviour by setting appropriate Options.
A more detailed description can be found within Info about Simulated Objects.
Example:
Available implementation macros | Purpose |
---|---|
TTB_METHOD_CALL() | automatically deduces method name and name of your simulated object; if not specified otherwise within options then writes entry to TestEvents which has to be verified via a call to macro TTB_EXP(). Sample entry within TestEvents: "DoSomething (SimObjectA)" |
TTB_METHOD_CALL1(stringStreamExpression) | same as TTB_METHOD_CALL, allows output of additional information (e.g. param values) Sample entry within TestEvents: "DoSomething in_val=42 (SimObjectA)" |
TTB_METHOD_CALL2(stringStreamExpression, stringFuncBody) | same as TTB_METHOD_CALL1, additionally allows call of a user defined lambda expression making arbitrary manipulations and finally returning a string which is used for output. With active option oBLOCKING the lambda expression is called with delay at the time when the blocked function is continued! |
TTB_METHOD_CALL_RET1(ReturnType) | same as TTB_METHOD_CALL, but returns an error when option oERROR is active. To allow a generic creation of an error you have to supply the following function within namespace TestToolBox:std::string MakeReturnValue( ReturnType& out_retVal, bool in_simulateFailure, std::string const & in_methodName, SimulatedObjectBase const * in_pObject);This function willl be called by macro TTB_METHOD_CALL_RET1 to return an appropriate error. More details are available within C++ sample: Implementation of a simulated object. |
TTB_METHOD_CALL_RET2(ReturnType, stringStreamExpression) | same as TTB_METHOD_CALL_RET1, allows output of additional information (e.g. param values) |
TTB_METHOD_CALL_RET3(ReturnType, stringStreamExpression, stringFuncBody) | same as TTB_METHOD_CALL_RET2, additionally allows call of a user defined lambda expression making arbitrary manipulations and finally returning a string which is used for output. With active option oBLOCKING the lambda expression is called with delay at the time when the blocked function is continued! |
Possible customization:
If you have requirements exceeding the possibilities of the predefined macros you can instead use the underlying method implementation _MethodCall() or build your own variation of it.
You can set an arbitrary instance specific option by calling
or you can set a global option by calling
The general parameter list of both methods is
You can define your own boolean option (e.g. "ChooseAlgorithm_X") by simply writing:
SimObject("MySimObjectB")->_SetOption("ChooseAlgorithm_X");
Within some method implementation of your simulated object you can check whether this option is set:
... if (_IsOptionSet("ChooseAlgorithm_X")) { ... } ...
As the options are defined within the text based maps built into SimulatedObject framework no other definitions are needed. The match between location of definition and location of usage is found by a simple string match. There is no need to define any interfaces to reach the internals of your simulated object.
There is a list of predefined options which are automatically used within TTB_METHOD_CALL macros.
Predefined Option | Purpose |
---|---|
Option::oBLOCKING | halt execution until explicit trigger for continue |
Option::oERROR | return error; works for macros TTB_METHOD_CALL_RET1-3 |
Option::oOBJECT_NAME | use object name when writing to TestEvents |
Option::oSILENT | suppress generation of TestEvent; when set to false you have to verify the call within your test script (e.g. via TTB_EXP("DoSomething ") |
Option::oSYNC | generate sync event for which you can wait within test case code |
Examples with often used predefined options:
The macro TTB_METHOD_CALL and all of its variants check for the value of an option by calling SimulatedObjectBase::_IsOptionSet (someOption, "MyMethodName"). The search for an option entry is performed according to the following sequence:
The search stops when the first entry is found. If no entry is found the option is not set, i.e. the option value is false.
Knowing this search algorithm you can choose an appropriate scope to address the reaction you need.
Option types | Purpose |
---|---|
NOT_ACTIVE | the option is explicitly switched off; the search within other scopes (see above) stops here. |
PERMANENTLY_ACTIVE | the option is simply switched on and remains active until explicitly being switched off. |
ACTIVE_ONCE | The option is active for the next call to Options::IsSet("someOption") and then automatically is switched off for all further calls. Within the context of a SimulatedObject this means that the TTB_METHOD_CALL macro which checks some option (e.g. whether to return an error) or the explicit call to SimulatedObjectBase::_IsOptionSet("someOption") will detect the option only for the next call. |
AFTER_N_CALLS_PERMANENTLY_ACTIVE | the option is switched on when from now on the N-th call to Options::IsSet("someOption") occurs. |
AFTER_N_CALLS_ACTIVE_ONCE | the option is switched on when from now on the N-th call to Options::IsSet("someOption") occurs. From (N+1)-th call on the option is automatically switched off |
WAS_ACTIVE | this option is internally used to be able to ask via Option::WasSet() for the last status of Options::IsSet("someOption"); technically Options::IsSet() may change the status of the option and Options::WasSet() does not. |
VALUE | this option is internally used to mark a value option, which is set via Options::SetValue() or SimulatedObjectsBase::_SetOptionValue(). For more details see next section. |
Besides boolean options as described above your simulated object may have to work with other values of arbitrary type. You can influence those internally used values by setting "option values" or by specifying them on command line.
You can define an option value by simply writing:
// Set globally defined value TTB::TheGlobalOptions()->SetValue("xVal", "15.08"); // Set specific value for a specific method of a specific object SimObject("SimObjectA")->_SetOptionValue("xVal", "3.14", "DoSomething");
Within some method implementation of your simulated object you can access the configured value:
... double xVal = _GetOptionValue<double>("xVal", TTB_FUNC_NAME); ...
If the option value was not set before then _GetOptionValue<>() will return a default constructed value of required type. Numeric types will therefore be initialized with 0. As an alternative you can explicitly check for existence of the option via method _IsOptionSet("xVal").
For a full example see C++ sample: Testcase with option values, DumpAllOptions, AutoRestoreOptions
When calling your test executable you can specify a command line parameter:
MyTestExecutable.exe -- -xVal 6.28
Within some method implementation of your simulated object you can access the command line value:
... double xVal = TTB::TheEnvironment()->GetCommandLineOptionVal<double>_GetOptionValue<double>("-xVal"); ...
If you are in doubt which boolean or numeric options are active within your test case you can simply dump all global and object specific options with a single call to DumpAllOptions():
TTB_CMD1(TTB::DumpAllOptions, TTB::CTX_TEST_EVENT); TTB_EXP("GlobalOptions"); TTB_EXP(" objectName:all: PERMANENTLY_ACTIVE"); TTB_EXP(" xValall: VALUE 15.08"); TTB_EXP("RegisteredSimulatedObjects"); TTB_EXP("SimObjectA"); TTB_EXP(" xValDoSomething: VALUE 3.14"); TTB_EXP(" xValDoSomethingElse: VALUE 8.99"); TTB_EXP("SimObjectB"); TTB_EXP(" xValall: VALUE 10.01");
Hint: Omitting the parameter CTX_TEST_EVENT or specifying CTX_INFO instead releases you from verifying the returned settings within your test. The output will still be visible within your test protocol.
Typically for executing a specific test situation you may want to temporarily change some option setting. To automatically switch back to the original option settings you can use class AutoRestoreOptions which stores the current settings at time of construction and restores them within its destructor. Within test case you can simply write:
... { TTB::AutoRestoreOptions whenLeavingScope; // Change options TTB::TheGlobalOptions()->SetValue("xVal", "15.08"); SimObject("SimObjectC")->_SetOption(TTB::Option::oERROR, "CalculateSomething"); // perform your test actions ... } // restore original option settings ...
Besides the setting and resetting of boolean and numeric options there are a couple of methods within base class SimulatedObjectBase which may be of special interest:
Method | Purpose |
---|---|
_ContinueExecution ( std::string const & in_methodName) | Continue the execution of a method call which has been blocked. |
_Trigger ( int in_hint = 0) | General purpose method to trigger something. Base implementation does nothing. Derived classes may override this method and use the call e.g. to recheck all set options and prepare some internal data used for inter working within test. The call may also cause a direct test specific interaction with the test environment or the test object. |
_MethodCall ( std::string const & in_methodName, std::string const & in_callInfo = "", StringFunc in_func = StringFuncEmpty) | Generic method execution with support for writing to TestEvents, generating sync events and blocking. is internally used by macros TTB_METHOD_CALLx; the source code may be a good starting point for specific method implementations when TTB_METHOD_CALLx macros do not fulfill all your needs. |
For a full description of class SimulatedObjectBase see C++ code: Definition of base class SimulatedObjectBase.