简体   繁体   中英

C++, shared library, “unit tests” in main function

Background: I have a complicated application that I have inherited and am extending (graduate research project). I want to make sure my re-organizations have a positive long term effect on maintainability and usability -- in other words I want to make sure I set things up in as standard a way as possible for future people who might work on the code. I do not have time, nor is it my place, to completely re-structure the application.

The application is an ecosystem model. It consists of a shared library written in C++ that does the heavy lifting. The library is included in a Java application that "drives" the simulation -- handles some database I/O and provides a GUI.

In the course of my development, I have added a number of utility functions to the project, mostly for convenient printing of internal variables to the console (directly from the C++ portions of the code) during run-time.

I am now factoring these functions out into a utility file (header and cpp) that is included in other files as needed. I put the functions in their own namespace following an example here: Organising utility functions in C++

Question: If I want to write some tests for the utility functions so that I can develop and experiment w/o re-compiling and modifying/running the entire model, where and how should these tests be best included?

Will it be a problem if I have a main() function in the util.cpp file? To my surprise, I tried this and it works; I can compile and run the util.cpp file independently. Also the primary application which includes util.cpp still compiles and runs fine. I was surprised because I thought the presence of a second main() would be a problem -- although the application entry point is in the java code.

However I am not sure if this is the best route; I don't have enough experience to see future pitfalls with this tactic.

Here is a short example of the my util.cpp file:

#include "util.hpp"
#include <iostream>
#include <vector>
namespace util {
  /** Prints a std::vector of doubles in a format that can be 
  * copied directly into a python console. */
  void util::pyprint_vec(const std::vector<double> & v){
    std::cout << "[";
    for(std::vector<double>::const_iterator it = v.begin(); it != v.end(); ++it){
      std::cout << *it << ", ";
    } 
    std::cout << "\b\b]"; // remove the last comma
  }
}

int main() {
  using namespace util;
  using namespace std;

  cout << "Testing some of the utility functions...\n";
  vector<double> a_vec(50,12.0);
  pyprint_vec(a_vec);
  cout << endl;

  return 0;
}

Ultimately I envision templating some of the functions (at which point they actually move to util.hpp) and adding to the file as well as being able to use it in other projects. Thanks in advance for any advice.

Normally, you would want to write a seperate executable program that includes the unit tests and that links against the functions that are to be tested. For example, you could create a util_test.cpp that includes a main()-function and the code with the tests, and that *#include*s the util.hpp. When compiling, use static or dynamic linking to the code that you want to be tested.

Technicaly, it won't be a problem to have a main() function in the util.cpp. However, if you include a second main function somewhere else in the library (to unit-test something else), and link it into the same shared object, you will recieve linker errors.

The main function has no special meaning other than, when the linker creates the executable, it inserts special code so that when you start the program, the code from main gets executed. If you load a "shared object" library, you don't "start" the program, and as long as you don't call the main function explicitly that code won't get executed.

From a purely getting it working point of view, one main function is fine, but two is going to break your compilation as only one can be called at startup.

You really want to looking into a unit-testing framework, something like cppunit or cxxtest (my current favorite). These are going to provide functionality that you'll find yourself re-implementing poorly if you try to go it alone. Generating multiple executables is a losers game, it will take forever to compile if your codebase is of any size at all. You really want one compiled executable driven by some kind of framework.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM