I have a section of code that I would not like to run if it is being unit tested. I was hoping to find some #defined flag that is set by the gtest library that I can check. I couldn't find one that is used for that purpose, but after looking through the gtest header, I found one I thought I could use like this:
SomeClass::SomeFunctionImUnitTesting() {
// some code here
#ifndef GTEST_NAME
// some code I don't want to be tested here
#endif
// more code here
}
This doesn't seem to work as all the code runs regardless. Is there another flag I can check that might work?
Google Test doesn't need or provide its own build wrapper. You don't even have to recompile your source files sometimes. You can just link them along with your test code. Your test code calls your already-compiled library code. Your library code probably doesn't even include and Gtest headers.
If you want your library code to run differently under test, then you first need to make sure that your library code is compiled differently under test. You'll need another build target. When compiling for that build target, you can define a symbol that indicates to your code that it's in test mode. I'd avoid the GTEST prefix for that symbol; leave for use by Google's own code.
Another way to achieve what you're looking for is to use dependency injection. Move your special code into another routine, possibly in its own class. Pass a pointer to that function or class into your SomeFunctionImUnitTesting function and call it. When you're testing that code, you can have your test harness pass a different function or class to that code, therefore avoiding the problematic code without having to compile your code multiple times.
In main():
int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
setenv("GTEST_RUNNING", "1", true);
ros::init(argc, argv, "tester");
return RUN_ALL_TESTS();
}
Somewhere else:
bool gtestRunning = strcmp(getenv("GTEST_RUNNING"), "1") == 0;
if (gtestRunning)
{
}
else
{
}
Related
I am developing a command line options processor for my app. I have decided to use GTest to test it. It's implementation has been shown below in brief:
int main(int argv, char **argv)
{
if (!ProcessOptions(argc, argv)
{
return 1;
}
// Some more code here
return 0;
}
int ProcessOptions(int argc, char **argv)
{
for (int i = 1; i < argc; ++i)
{
CheckOption(argv[i]);
CheckArgument();
if (Success)
{
EnableOption();
}
}
}
The code runs as expected, but the problem is: I want to test this using GTest by supplying different options (valid and invalid) to it. The GTest manual reads:
The ::testing::InitGoogleTest() function parses the command line for
googletest flags, and removes all recognized flags. This allows the
user to control a test program's behavior via various flags, which
we'll cover in the AdvancedGuide. You must call this function before
calling RUN_ALL_TESTS(), or the flags won't be properly initialized.
But this way, I will be able to test just one sequence. I want to do this multiple times for different options. How do I do that?
Is there any better strategy to achieve this? Can I do this using test fixtures?
Have you considered a value-parameterized test? They sound perfect for your situation:
Value-parameterized tests allow you to test your code with different parameters without writing multiple copies of the same test. This is useful in a number of situations, for example:
You have a piece of code whose behavior is affected by one or more command-line flags.
You want to test different implementations of an OO interface.
You want to make sure your code performs correctly for various values of those flags.
You could write one or more test(s) which define the expected behaviour of the command line argument parser and then pass the command line flags down to it this way.
A full code example is shown in the link to the Google Test GitHub docs, but here's a quick outline:
Create a test class inheriting testing::TestWithParam<T>.
Use TEST_P and within it, the GetParam() method to access the parameter value.
You can instantiate your tests with INSTANTIATE_TEST_SUITE_P. Use the testing::Values method to supply values.
I had some code like this:
void MainWindow::saveData()
{
QDir oldDir=QDir::current();//this should return the main executable directory.Since there is no other place in my hole code where i temper with QDir.
QDir sess("Sessions");
if(!oldDir.exists("Sessions"))//if "Sessions" Dir doesn't exist
oldDir.mkdir("Sessions");//create it.
QDir::setCurrent(sess.absolutePath());
//some virtual code inside current Dir, which i didn't implement yet.
QDir::setCurrent(oldDir.absolutePath());//restore old dir
}
When I run my app firstly the code works perfectly.but in the second run, the first call to QDir::current(); returns the "Sessions" Dir and not the main executable Dir as it should be restored in the first run.actually i did manage to overcome this by adding one line at the biginning of the code, the following :
QDir::setCurrent(QCoreApplication::applicationDirPath());
Still I want to know why the first code didn't work.already checked for the documentation of the functions and found nothing.
QDir::current();//this should return the main executable directory
No it should not! Not unless you change it to point there first.
I'm dead serious when I'll say this: Yours is a myth, fantasy, whatever you call it, I have no idea what gave you the idea. Point me to a spec that says so. Oh, you can't, because there's no such spec, no such requirement. It's someone's twilight hour mirage that seems to perpetuate itself endlessly. If you heard it from someone, you have every right to be angry at them this very moment, for they did you a big disservice.
Generally speaking, for applications that are not normally started from the command line, the initial working directory can be anything and it will be platform- and session/system configuration dependent. For a typical GUI application, assuming any particular initial working directory is a fool's errand and completely misguided.
Once you change it to where you want it to point to, you of course have full control over it, but the initial working directory must be assumed to be random and out of your control.
For example, on Windows I can start your application through an Explorer shortcut where I can specify whatever startup folder I desire, and you have zero control over it. On OS X, Finder sets the working directory to something or another, IIRC to the folder where the app bundle resides. Again, you as a developer have no control over it unless there's some setting in the bundle that you could add to that effect, but that is platform-specific and will be ignored if your application is not started through Finder or bundle API mechanisms (they probably are called something else). And so on. It's completely arbitrary and it's pointless to depend on its initial value.
If you want to refer to the application's installation directory or executable directory, do so explicitly. Do not assume anything about the initial working directory of a GUI application.
I tried with the below code and it works fine for several runs.
The version details of Qt and OS may help.
Qt creator 3.3.2 (open source). Qt lib 5.4.1.Os windows 8.1
#include <QCoreApplication>
#include "QDir"
#include "qDebug"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QDir oldDir=QDir::current();
qDebug()<<QDir::current().absolutePath();
QDir sess("H:\\cuteapps\\session");
if(!oldDir.exists("H:\\cuteapps\\session"))//if "Sessions" Dir doesn't exist
oldDir.mkdir("H:\\cuteapps\\session");//create it.
QDir::setCurrent(sess.absolutePath());
qDebug()<<QDir::current().absolutePath();
return a.exec();
}
output 1:
"H:/cuteapps/build-untitled2-Desktop_Qt_5_4_1_MSVC2012_OpenGL_32bit-Debug"
"H:/cuteapps/session"
output 2:
"H:/cuteapps/build-untitled2-Desktop_Qt_5_4_1_MSVC2012_OpenGL_32bit-Debug"
"H:/cuteapps/session"
output 3:
"H:/cuteapps/build-untitled2-Desktop_Qt_5_4_1_MSVC2012_OpenGL_32bit-Debug"
"H:/cuteapps/session"
I'm currently working with Qt and qml files; many of the qml sources that I'm using takes advantage of the hability to publish C++ classes into the qml runtime with the qmlRegisterType template:
int main(int argc, char *argv[])
{
QApplication application(argc,args);
qmlRegisterType<Component1>("CompanyName", 1, 0, "Component1");
qmlRegisterType<Component2>("CompanyName", 1, 0, "Component2");
...
lots of components
...
qmlRegisterType<ComponentN>("CompanyName", 1, 0, "ComponentN");
return application.exec();
}
The amount of C++ types registered on qml is pretty high, and the registering is kind of cumbersome so I've decided to put the registering into a macro due to the fact that many of the data is repeated on all the registering process, the macro looks like the following:
#define QMLTYPE(T) qmlRegisterType<T>("CompanyName", 1, 0, #T);
And you can guess how is it intended to be used:
int main(int argc, char *argv[])
{
QApplication application(argc,args);
QMLTYPE(Component1);
QMLTYPE(Component2);
...
lots of components
...
QMLTYPE(ComponentN);
return application.exec();
}
AFAIK after expanding this macro the code should look like the first posted on this question so, the functionality should remain unaltered. But after launching the macro-version of the program, an error shows up:
Component1 is not a type
It seems that the qml runtime is unable to found the types registered, as if the macro is failing or preventing the Qt voodoo to publish the type. Reverting to the no-macro-version the application runs without errors. I swear that the only difference between both versions is the use of a macro to call the qmlRegisterType template function.
After the explanation of the problem, let me ask a pair of questions:
Is the QMLTYPE(T) macro correct or I made some kind of mistake typing that macro.
If the macro isn't the problem and it expands to the expected code, is the Qt runtime unable to register the type because the macro "doesn't look like a type registering"?
I'm using Qt Creator (3.1.2) Based on Qt 5.3.1 (MSVC 2010, 32 bit)
After weeks of giving up on the problem, I’ve found what went wrong.
The macro is correct, and the code that uses the macro is correct too.
The problem is the capitalization of Component1 which is used on the qml files with the name component1 (first letter lowercase).
So the macro is publishing the type Component1 while the code is using the type component1... it is a silly problem.
Actually here i am tring to invoke some user defined function from 1 function. But i couldnt step-in in to that function, i dont know what could be the reason.
below is the code snippet for calling function
if (!m_pCSock->ConnectTo(aszTWinServerName, m_szServicePort, false))
and below is the defination for the above call
int CSocketClient::ConnectTo(const char *szSuppliedHostname, const char *Suppliedport, bool ShowErrors)
{
if (m_Connected)
{
return m_Connected;
}
char szHostname[128] = "";
char port[128] = "";
The above 2 instances are in different projects and different files.
I tried a lot, I coudn't invoke into this function.
While debugging, when I try to invoke the below line
if (!m_pCSock->ConnectTo(aszTWinServerName, m_szServicePort, false))
it is not moving inside this, it is just moving to next statement.
I am suspecting here it might be some setting issue, I am actually to Windows.
Please help me. Thanks in advance.
maybe the file that contains the function is not built in "debug" mode.
If you perform a "clean and build" operation over the library or proyect, forces the file to be compiled with debug symbols and then debugger can visit that code.
I am trying to write a function/method for my project, which will ask to user which all test cases are you going to run?
It looks like below...,
Test_Cases_1
|_TestNo1
|_TestNo2....so on
Test_Cases_2
|_TestNo1
|_TestNo2....so on
....
....so on
Test_Cases_N
|_TestNo1
|_TestNo2....so on
So, now the challenge is while running the project it should prompt me what all test cases you would like to execute?
If I select Test_Cases_1 and Test_Cases_N. Then it should execute these two test cases and should exclude all other from Test_Cases_2 to ..... In result window also I would like to see the results of Test_Cases_1 and Test_Cases_N.
So, if I will see the GoogleTest, there is a method called test_case_to_run_count();
But all the test cases are getting registered with Test_F() method.
So, I did lots of analysis, but still did not find any solution.
Please help me.
You could use advanced options to run Google tests.
To run only some unit tests you could use --gtest_filter=Test_Cases1* command line option with value that accepts the * and ? wildcards for matching with multiple tests. I think it will solve your problem.
UPD:
Well, the question was how to run specific test cases. Integration of gtest with your GUI is another thing, which I can't really comment, because you didn't provide details of your approach. However I believe the following approach might be a good start:
Get all testcases by running tests with --gtest_list_tests
Parse this data into your GUI
Select test cases you want ro run
Run test executable with option --gtest_filter
Summarising Rasmi Ranjan Nayak's and nogard's answers and adding another option:
On the console
You should use the flag --gtest_filter, like
--gtest_filter=Test_Cases1*
(You can also do this in Properties|Configuration Properties|Debugging|Command Arguments)
On the environment
You should set the variable GTEST_FILTER like
export GTEST_FILTER = "Test_Cases1*"
On the code
You should set a flag filter, like
::testing::GTEST_FLAG(filter) = "Test_Cases1*";
such that your main function becomes something like
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
::testing::GTEST_FLAG(filter) = "Test_Cases1*";
return RUN_ALL_TESTS();
}
See section Running a Subset of the Tests for more info on the syntax of the string you can use.
Finally I got some answer,
::test::GTEST_FLAG(list_tests) = true; //From your program, not w.r.t console.
If you would like to use --gtest_filter =*; /* =*, =xyz*... etc*/ // You need to use them in Console.
So, my requirement is to use them from the program not from the console.
Updated:-
Finally I got the answer for updating the same in from the program.
::testing::GTEST_FLAG(filter) = "*Counter*:*IsPrime*:*ListenersTest.DoesNotLeak*";//":-:*Counter*";
InitGoogleTest(&argc, argv);
RUN_ALL_TEST();
So, Thanks for all the answers.
You people are great.