Testing with GTest and GMock: General or Static Libraries

I think this question may violate some of the Q & A standards for the site, as the answer (s) that I can get can be considered opinion oriented. However, this is happening here ...

Suppose we are working on a C ++ project, using CMake to control the build / test / packaging process, as well as GTest and GMock for testing. Suppose further that the structure of our project looks like this:

cool_project | |-- source | | | |-- module_foo | | | | | |-- (bunch of source files) | | | |-- module_bar | | | |-- (yet more source files) | |-- tests | |-- module_foo | | | |-- (tests for module_foo) | |-- module_bar | |-- (tests for module_bar) 

This, of course, is a simplified situation, but you get an idea.

Now itโ€™s good if these modules are libraries, and each test (i.e. each directory under tests ) is executable, we need to associate the last with the first. The fact is that if these libraries are separated, the loader, of course, must find them. The obvious solution is to install the test working directory into the library directory using CMake set_property . However, if both GTest and GMock were also created as shared libraries, this will not work, since they must also be loaded.

The solutions I came up with were:

  • Copy both libraries (i.e. GTest and GMock) into the module assembly directory. This looks silly, since the main advantage of shared libraries (i.e. code sharing between programs) is completely eliminated, and we get several copies of these files throughout the directory.
  • Create both GTest and GMock as static libraries. This means that now we get a copy of both libraries in each executable file, which increases its size. Despite the fact that we do not have 1000 tests, it feels somewhat awkward.

So, given this situation, I would like to know if anyone has ever been struck by this, and which way he or she took. (If the solution were different than the ones I mentioned, I would be happy to hear all about it.) Ideally, I would like to be able to make && make test and do all the tests without having to run any additional script to post things. Having all the libraries built as static libraries does the job, but what if I create them as shared libraries? Should I build them twice? This is silly.

Another problem also occurs in these lines, but I think that its solution includes a redesign or similar artifact. Suppose module_foo dependent on a third-party library, for example. library_baz . If module_foo refers directly to library_baz , then any test on the first one will need to load library_baz , even if it can test unrelated functions. The same problem arises.

Failure seems like the right thing here, but for some reason I feel that it makes no sense to refactor module_foo so that it can talk to the interface (whether due to dynamic or static polymorphism) since it does not need such flexibility: library_baz does the job. I suppose some people will say something like, โ€œOf course you donโ€™t need flexibility today, but who knows tomorrow?โ€ It seems intriguing to me, trying to look through all the possible scenarios that the system may encounter, but again, there are people with much more experience than me.

Any thoughts?

+6
source share
2 answers

I think I tried to kill a mosquito with a nuclear missile.

The solution I came up with was to just build all the libraries as static objects when testing. True, in the end I have quite large binaries, but I will not distribute them.

So, we summarize:

  • Both GTest and GMock are created as static libraries.
  • The same goes for libraries that contain the functions that I am testing.
  • Tests are then associated with them and thus can be run without any problems with the working directory.

There are no significant flaws in this setting. Whenever I want to try the whole system, I just switch to shared libraries.

+2
source

Thus, I see that this is done (at least on Windows, I do not develop on * nix) completely independent of any testing:

Simply, all binary assembly artifacts and dependencies that need to be executed must be copied (or created directly) to the ./bin directory.

Then you can execute any executable from this ./bin directory, and all shared libraries will be available there.

0
source

All Articles