execute all tests (gtest) from library - c++

I have a foo library in c++, and I am using gtest as testing framework.
I want to create testFoo executable which calls runTests which is defined in statically linked testFoo library which contains all tests for statically linked foo library.
I have created all that I am written, but google test shows me "Empty test suite."
testFooLib.h
int runTests(int argc, char* argv[]);
testFooLib.cpp
int runTests(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
If I put
TEST(Testing, someTest){
EXPECT_EQ(true, true);
}
in testFooLib.cpp, this test is found, but if I put it in some other cpp it will not be found.
testFooExecutable.h
#include "testFooLib.h"
int main(int argc, char** argv) {
return runTests(argc, argv);
}
I have some tests in project, I don't want to pollute my post with it...
update, I have put tests in code.
I have same problem as here important-note-for-visual-c-users.
Note: I have tried with clang, gcc and msvc and result is always the same.

Seems that by design GTest picks up only TEST() cases defined in the .exe project. Those from static library are ignored.
Check this configuration:
Build gtest lib as a static library.
Put tests in .cpp (TEST() macro, ...) into the project which creates the executable.
GTest initialization should be called from main in .exe project:
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();

Related

Building a temporary `main()` function in c++

I'm just learning c++. I have a main.cpp unit which has a lot of stuff in it already, and I just want to build a quick little testMain.cpp unit that will test a couple of things.
Basically I want to trick the compiler (xCode) into ignoring the real main function for a minute. I could
Rename the main() function inside main.cpp to mmain() temporarily.
Remove the reference to main.cpp in my project temporarily.
Comment out the main() method in main.cpp temporarily.
All these seem pretty clunky. There has to be an easier way. I suspect this is a common thing people do. How do you do it?
Another solution would be to separate the code into multiple files, have most of the logic in one file, have the real main in another and the test main in a third, you compile and link either the first and second or first and third files but never all three together.
Your option 2 is the most common strategie, and from my understanding also the cleanest.
After all, your test application will most likely not share the same command line interface, and that is usually about the only thing which should (of at all) be located in the main function or file.
If your main.cpp contains significantly more than just the entry point, you should immediately start thinking about how to distribute that logic into the modules you already have.
Use a macro.
Option 1: Use a macro to include/exclude entire files:
main.cpp:
#ifdef USE_REAL_MAIN
int main(int argc, char* argv[]) {
...
}
#endif
testMain.cpp
#ifdef USE_TEST_MAIN
int main(int argc, char* argv[]) {
...
}
#ENDIF
build file:
gcc -DUSE_REAL_MAIN
gcc -DUSE_TEST_MAIN
Option 2: Use a command-line macro to rename main:
main.cpp:
int realMain(int argc, char* argv[]) {
...
}
testMain.cpp
int testMain(int argc, char* argv[]) {
...
}
build file:
gcc -DrealMain=main
gcc -DtestMain=main
Note this is probably the least attractive option because it breaks the convention of macros having UPPER_CASE names and means the real entrypoint of your program is non-obvious to someone who hasn't seen the build script. It also means the program simply won't compile (as there's no main function) without your custom build script either.
Option 3: Have a new common main with the #ifdef directives instead:
main.cpp
#include "realMain.h"
#include "testMain.h"
int main(int argc, char* argv[]) {
#ifdef USE_TEST_MAIN
return testMain( argc, argv );
#else
return realMain( argc, argv );
#endif
}
build file:
gcc -DUSE_REAL_MAIN
gcc -DUSE_TEST_MAIN
I think this is my preferred option because it's almost self-documenting and makes it clear to another programmer how to get it to work without needing your custom build script.

How can googletest preserve the test code during linking?

I have a small test project with the following layout:
testmain.cc
Foo\
|--FooClass1_test.cc
|--FooClass2_test.cc
Bar\
|--BarClass1_test.cc
|--BarClass2_test.cc
In the *_test files I have defined tests along the lines of
TEST(Foo, foo_func1_works)
{
EXPECT_EQ(42, the_answer);
}
And testmain.cc contains only:
#include <gtest/gtest.h>
int main(int argc, char* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
I can see that the TEST macros generate self-registering classes which RUN_ALL_TESTS will know about, but how is this code linked? Nothing references the tests defined in the .cc files, no includes etc. Why does the linker not throw this code away? I am compiling the project with MSVC 2010.

libgit2 and Qt error

I want to use git from an Qt application. So far, I use QProcess, but I do not want to use that. So I found libgit2.
This works as expected:
#include <QApplication>
#include "git2.h"
int main(int argc, char* argv[])
{
git_repository* repo = 0;
git_clone(&repo, "/path_to/barerep", "/path_to/test_clone", NULL);
git_repository_free(repo);
repo = 0;
}
But here, git_clone crashes.
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
git_repository* repo = 0;
git_clone(&repo, "/path_to/barerep", "/path_to/test_clone", NULL);
git_repository_free(repo);
repo = 0;
return a.exec();
}
The error is:
*** Error in `/path_to/gittest': free(): invalid pointer: 0x09d53a88 ***
Any suggestions? Of course, omitting QApplication is not an alternative. The same error occurs without return a.exec().
Note: Actually, there is a class GitRepository with a method clone(const QString & url) (the path is stored somewhere in the class).
Again, this works
int main(int argc, char* argv[])
{
GitRepository g;
g.clone("path_to/barerep");
}
But this does not. (QObject!)
int main(int argc, char* argv[])
{
QObject(); // <--
GitRepository g;
g.clone("path_to/barerep");
}
does not.
bool GitRepository::clone(const QString & url)
{
git_repository* repo = 0;
git_clone(&repo, CSTR(url), CSTR(path()), NULL);
git_repository_free(repo);
repo = 0;
//loadFromTempDir();
return true;
}
Replacing QApplication by QObject in the first example suppresses the error.
You need to call git_libgit2_init() before calling any other libgit2 functions. As the documentation says:
This function must the called before any other libgit2 function in order to set up global state and threading.
These kind of errors are really hard to find. I also had problems mixing Qt libraries with other libraries. The trick is to organize your code in a way that there is only one library included in one compilation unit.
Create a class, which wraps around libgit2, and only include the libgit2 headers in the cpp file of this class. Do not include any qt headers in the same file.
Only refer to libgit throw your wrapper. Sure it seems like a lot of work, but as a result your code will be cleaner, and these misterious errors will be gone.

Unit testing with google test

I want to learn using google test framework with everyday projects, so I looked up a few tutorials, but I have no idea how to get started.
I'm using Qtcreator in Ubuntu 14.04, I downloaded gtest.zip from the google site and unzipped it, but here is where it all stoped.
This is the code i want to "gtest":
//main.cpp
#include <iostream>
#include <cstdlib>
#include "fib.h"
using namespace std;
int main(int argc, char *argv[])
{
int n = atof(argv[1]);
fib fibnumber;
cout << "\nDesired number is: " << fibnumber.fibRec(n) << endl;
}
//fib.h
#ifndef FIB_H
#define FIB_H
class fib
{
public:
int fibRec(int n);
};
#endif // FIB_H
//fib.cpp
#include "fib.h"
int fib::fibRec(int n)
{
if(n <= 0) return 0;
if(n == 1) return 1;
else return(fibRec(n-1)+fibRec(n-2));
}
So where do i even begin, I want to make unit test and compile it without any plugins, but i don't know how to make use of the file I unzipped and then use it to write a unit test.
The google Testing framework works by building it as part of your source code. That means there is no library that you have to link to, instead you build the library when you compile your code (there is a good reason for this).
Have a look at the official documentation:
https://github.com/google/googletest/blob/master/googletest/docs/primer.md
Steps
Try to build a test testcase for your program. I can't tell you how to do it with Qtcreator but that should be easy enough to find. Create a test that will definitely fail, like the one below.
TEST(MyFirstTest, ThisTestShallFail) {
EXPECT_EQ(1, 2);
}
Run this very simple test to check that it fails. If you want, change it to make it pass.
Start creating your unit tests. Check for a few easy number. Check boundary conditions etc.
In addition to #Unapiedra's suggestions, I would suggest to write a separate test file and a separate source/implementation file to test the code with google test framework and link the project using a build system or better a build generator system.
My example below demonstrates this using a cmake build generator. (My assumption here is that the user is familiar with cmake)
Note: although in practice it is recommended to write code incrementally using the Test Driven Development philosophy, I don't do it since the purpose here is to show how a simple unit test can be written and compiled using google test framework.
charOperations.hpp
#ifndef CHAR_OPERATIONS_H
#define CHAR_OPERATIONS_H
#incude <string>
class CharOperations{
private :
// ...
public:
//converts lower case characters to upper case
// and returns a std::string object from this
std::string convertToUpper(const char letter){
char upCase = std::toupper(static_cast<unsigned char>(letter));
return std::string(1, upCase);
}
//converts upper case characters to lower case
// and returns a std::string object from this
std::string convertToLower(const char letter){
char loCase = std::tolower(static_cast<unsigned char>(letter));
return std::string(1, loCase);
}
// more functions ...
};
#endif //class definition ends
test_example.cpp
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "CharOperations.hpp"
//declare a test fixture so that the object
// CharOperation need not be declared in each test
//Each test fixture has to be publicly derived from
// testing::Test
class CharOperationsTest : public testing::Test{
//class object public so that it is accessible
//within the tests that are written
public:
CharOperations charOps;
};
// now write the tests using macro TEST_F
// which is used for testing with test fixtures
//1st parameter to TEST_F is the name of the fixture
//second parameter to TEST_F is the name of the test
//each test has to have a unique name.
//test #1
TEST_F(CharOperationsTest, ConvertsCharToUpperCaseString){
ASSERT_THAT(charOps.convertToUpper('a') testing::Eq("A");
}
//test #2
TEST_F(CharOperationsTest, ConvertsCharToLowerCaseString){
ASSERT_THAT(charOps.convertToLower('A') testing::Eq("a");
}
//more tests ...
//run all tests
int main(int argc, char **argv){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.2.3)
project(TDD CXX)
enable_testing()
set(CMAKE_CXX_STANDARD 11)
find_package(PkgConfig REQUIRED)
pkg_check_modules(gtest REQUIRED gtest>=1.8.1)
pkg_check_modules(gmock REQUIRED gmock>=1.8.1)
include_directories(${gtest_INCLUDE_DIRS})
include_directories(${gmock_INCLUDE_DIRS})
add_executable(test.out ##target executable name
test_example.cpp
)
target_link_libraries(test.out ${gtest_LIBRARIES})
A general suggestion for writing tests: It can be observed in the file test_example.cpp, the Macros/Functions Test. Eq and InitGoogleTests reside under the namespace testing. Hence it might be prudent to declare a using namespace testing declaration at the beginning of the file after all #includes. Lastly needles to say to compile in a separate build directory

executable parameter c++

if i got a c++ executable file like this: executable.exe and i want to add some parameters like:
executable.exe +username = pino
how do i get in c++ that i filled in pino as my username?
Arguments to main. Your main is
int main(int argc, char **argv) {
...
}
All the command-line params are in argv. There are also Windows-specific APIs.