How to test multiple classes within a project?
I am testing a project that contains multiple classes. I have generated a stub file for the project to cover all calls to methods in other projects and I have generated stub files for each class where necessary to cover calls to other public class methods within the project. When testing the project, this approach does not work because stubs are ignored when the original class is available. This is highlighted as a limitation in the User Guide.
I guess I need to use one of the alternative 'Unit Testing settings' to 'Create separate test-executable'. However, each executable and log file must have a different location or name and there doesn't appear to be an appropriate variable available to achieve this. What is the recommended approach to what must be a common scenario?
Answers
-
Further information:
The following is an extract from my customized Test Execution Flow script, intended to create a separate executable and log for each class:
<TestRunnerGenerationStep testSuiteConfigFile="${cpptest:testware_loc}/testsuites.xml" testrunnerCFile="${cpptest:testware_loc}/cpptest_testrunner.c" testrunnerCppFile="${cpptest:testware_loc}/cpptest_testrunner.cpp" testLogFile="${cpptest:testware_loc}/${file_name}Results.tlog" covLogFile="${cpptest:testware_loc}/${file_name}Results.clog" /> <CompileStep /> <BuildRuntimeLibStep ignoreDbgOpts="true" /> <LinkStep result="${cpptest:testware_loc}/${file_name}Test.elf"/>
The variable file_name does not work in this context.
0 -
Hi davemr,
Auto stubs have lower priority than original definitions, so if you have both in the test scope, the original definition "will win".
User stubs, however, have higher priority than original definition, so if you create a user stub for a function/method, it will be used even if the original definition appears in the test scope.
It would help me with recommending you the setup approach if you could share some more information regarding what you are trying to achieve.
Do you want to test all your classes in isolation (using all the generated stubs) when selecting the project for testing or your intention is to use original definitions?
0 -
Hi Mirek,
Thank you for responding. I need to automatically test every class within the project in isolation.
As an example, within a project I have a class MyClass, that contains a public method GetRevision. The test suite for MyClass must use the original method. However, when testing other classes that use GetRevision, they must use a stub, so that I can define the output.
I was thinking I could create a single executable for the project but I now understand why that is expecting too much of the linker. The alternative was to 'Create separate test-executable for each tested context' but the executable file location and name are the same for each test suite '${project_name}Test.elf' and so only 1 test suite can be generated at a time. Is there another approach?
0 -
Hi davemr,
I'm sorry for not responding sooner - I'm traveling, hence the delay in response.
I would not give up on the idea of creating a single test executable.
Please note that it is a perfectly valid scenario to call the original symbol definition from the stub.So in your case, you can create a stub for GetRevision method and configure the behavior of the stub from the test case. Your test cases created for other classes would configure the stub to return "fake" value that is required for your specific test scenario, while your test cases created for MyClass can simply configure the stub to perform "proxy" call and invoke the original method.
If you are using C++test 10.4.x, you can apply so-called stub callbacks to configure desired behavior. Below you can find a simple example I've created using our demo project. It assumes that stub for getBalance is already generated. Configuration is done from the source code level, but if you are using test case editor exactly the same functionality is provided. Please see user manual for more details on stub callbacks.
- Call original definition
void TestSuite_Account_cxx_49070052::StubCallback_Account_getBalance(CppTest_StubCallInfo* stubCallInfo, double* __return, ::Account* __this)
{
*__return = __this->getBalance();
}
void TestSuite_Account_cxx_49070052::test_case_copy()
{
::Account _cpptest_TestObject;
double _amount = 10.0;
CPPTEST_REGISTER_STUB_CALLBACK("Account::getBalance", &StubCallback_Account_getBalance);
double _return = _cpptest_TestObject.debit(_amount);
CPPTEST_ASSERT_FLOAT_EQUAL_DELTA(20.0, _return, 0.01);
}- Simulate the value through stub
void TestSuite_Account_cxx_49070052::StubCallback_Account_getBalance(CppTest_StubCallInfo* stubCallInfo, double* __return, ::Account* __this)
{
*__return = 20; // My arbitrary value
}
void TestSuite_Account_cxx_49070052::test_case_copy()
{
::Account _cpptest_TestObject;
double _amount = 10.0;
CPPTEST_REGISTER_STUB_CALLBACK("Account::getBalance", &StubCallback_Account_getBalance);
double _return = _cpptest_TestObject.debit(_amount);
CPPTEST_ASSERT_FLOAT_EQUAL_DELTA(20.0, _return, 0.01);
}Hope this helps,
Mirek0 - Call original definition