Redefined Catch unit tests - c++

I'm testing a huge piece of software and would like to use Catch for this task.
I'm using the "single include" version 1.9, integrating it in Visual Studio 2012 update 4 and using C++04 standard.
As you will see below, I use three ".cpp" files. Each of them reference:
a include file providing "abstraction" macros (eg. #define Assert(x) REQUIRE(x));
a utility file providing... utilities for the test;
the specific test target include files;
some "using namespace" statement, all cpp files "using" the same namespace;
the actual tests, written with the macros (eg. Assert(2 == getNumber())).
More details on the files content below.
This configuration works, but one of the test file is growing bigger by the day and I would like to split it in 3, or more. Now, say that I do the following:
take part of the content of a test test.cpp and move it in a new file test2.cpp;
add the same includes and defines to make it compile;
include the new file in my main
this error pops up when I run the tests:
=============================
No tests ran
error: TEST_CASE( "test 2" ) already defined.
First seen at c:\tests\catchtest2\catchtest2\test2.cpp(3)
Redefined at c:\tests\catchtest2\catchtest2\test2.cpp(3)
where test2.cpp is the new file.
If I move the content back to test.cpp it all works, but working with tests thousands of lines long is almost harder than working on the project itself, and the dimension could grow 3, 4 times bigger still.
Is there a way to split the tests in multiple files?
-- NOTES --
I reckon including Catch in a header and using the including header instead of catch.cpp directly is not a good idea, but I successfully used this configuration with 3 (exactly 3) included .cpp test files, and am unable to use this with 4 files.
I remember reading that it was somehow related to the line at which the components were defined, but I can also move the code so that the test cases are defined at different lines and the behaviour doesn't change.
I also tried to "clean and rebuild", because it may well be that dirty data is kept in the compiler / linker's caches, but to no avail.
I couldn't create an actual MWE right now, so I gave you a sketch of the test setup as accurate as I thought it could be needed. I'm more than willing to provide additional details or try and build an actual MWE and share it.
Any idea is appreciated!
My "working" code looks like this:
main.cpp
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include "test1.cpp"
#include "test2.cpp"
#include "test3.cpp"
int main( int argc, char* argv[] )
{
cleanDir("c:\\temp");
init (argv);
int result = Catch::Session().run( argc, argv );
return ( result < 0xff ? result : 0xff );
}
test1.cpp
#include "unitTestSuite.h"
#include "utils.h"
#include "systemundertest.h"
using namespace system::under::test;
my_test_case("test 1") {
my_section("does X") {
// tests...
}
}
my_test_case("test 2") {
my_section("does Y") {
// tests...
}
}
unitTestSuite.h
#ifndef UNIT_TEST_SUITE
#define UNIT_TEST_SUITE 1
#include "catch.hpp"
#define my_test_case(x) TEST_CASE("Testing: " x)
... // here is also a namespace with some unit test specific utils
#endif
utils.h
#ifndef _UTILS_
#define _UTILS_
// some global variables declared here and defined in utils.cpp
// template functions defined in the header
// non-template functions defined in utils.cpp
// a test generation namespace with some template functions and some non-template functions defined in utils.cpp
#endif
After the "split":
test1.cpp
#include "unitTestSuite.h"
#include "utils.h"
#include "systemundertest.h"
using namespace system::under::test;
my_test_case("test 1") {
my_section("does X") {
// tests...
}
}
test1.2.cpp
#include "unitTestSuite.h"
#include "utils.h"
#include "systemundertest.h"
using namespace system::under::test;
my_test_case("test 2") {
my_section("does Y") {
// tests...
}
}
main.cpp
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include "test1.cpp"
#include "test1.2.cpp"
#include "test2.cpp"
#include "test3.cpp"
int main( int argc, char* argv[] )
{
cleanDir("c:\\temp");
init (argv);
int result = Catch::Session().run( argc, argv );
return ( result < 0xff ? result : 0xff );
}
program output:
=============================
No tests ran
error: TEST_CASE( "test 2" ) already defined.
First seen at c:\tests\catchtest2\catchtest2\test1.2.cpp(3)
Redefined at c:\tests\catchtest2\catchtest2\test1.2.cpp(3)

Don’t include the cpp files, just add them to the project.
Your main.cpp file only needs the first two lines (a define and an include).

Related

How to link multiple .cpp files in Code::Blocks for a single project?

While following the book C++ For Dummies, I have three files in my CodeBlocks project, main.cpp, Pen.h, and Pen.cpp. They look like this:
main.cpp:
#include <iostream>
#include "Pen.h"
//#include "Pen.cpp"
using namespace std;
int main()
{
Pen MyPen = Pen();
MyPen.test();
}
Pen.h:
#ifndef PEN_H_INCLUDED
#define PEN_H_INCLUDED
//#include "Pen.cpp" // Uncommenting this gives a different error
using namespace std;
class Pen
{
public:
// attributes omitted
// PROTOTYPES:
// other functions omitted
void test();
};
#endif // PEN_H_INCLUDED
Pen.cpp:
#include <iostream>
#include "Pen.h"
using namespace std;
//other function definitions omitted
void Pen::test()
{
cout << "Test successful." << endl;
}
When I run the code as listed above, I get an "undefined reference to `Pen::test()'" error. To fix this, I changed the #include statements at the top of main.cpp to:
#include <iostream>
//#include "Pen.h"
#include "Pen.cpp"
This works as intended and correctly prints out "Test successful."
My question is this: what in the world is the point of putting a function prototype in a header file if I have to import the .cpp file later on anyways?
EDIT: It turns out this was a problem with not knowing how to use Code::Blocks rather than with the C++ language.
Assuming you're using gcc, you can compile and link in one step by supplying multiple .cpp files via the command line.
g++ Pen.cpp main.cpp
clang should be similar.
clang++ Pen.cpp main.cpp
An #include should never reference a .cpp file. At all. There's no good reason to do it. Include your headers and then supply the names of all .cpp files when you compile. If your project gets big and you have too many .cpp files to reasonably list, then it's time to break out a makefile or similar.
In the main.cpp include the header file:
#include "Pen.h"
The Pen.h file it's ok.
You need to add the Pen.cpp file to the project tree.
Go to Project -> Add files... and add Pen.cpp

Understanding Preprocessor Directives in C++ as a beginner

I recently began learning C++. As a programmer coming from Python, I've noticed some general similarities when it comes to how certain things in C++ do the same thing over in Python.
One question I had is understanding Preprocessor directives. I/O Stream seems to be a common one to use in beginner programs.
Is #include effectively the same thing as import in Python, or is it completely different than importing "modules"?
C++ did not have modules until the latest standard (C++20). #include is not the same as import in the languages that support modules. Instead, it is a source code - level inclusion of a "header" file. Usually, the headers only contain declarations but not definitions of what you are "importing". The definitions are contained in compiled libraries that are added by the linker.
Congrats on diving in to C++, you're going to have many more questions and confusions coming from Python, especially if you use some of the newer standards (like C++11/14/17/20).
That aside, answering your question directly:
Is #include effectively the same thing as import in Python or is it completely different than importing "modules."
I won't speak to C++20 modules as that functionality is not fully supported across the various compilers and that is not your question. Unfortunately the answer is not a simple yes or no, it's kind of both.
In C and C++, the #include pre-processor directive essentially does a "copy-paste" of whatever file you #include before it does the compilation stage. This allows you to separate large chunks of code into easier to manage files and still reference the code in said file.
In Python/C#/Java and various other languages, you don't #include a file you want to access the classes and functions of, you import the namespace or module you wish to reference and the JIT compiler "knows" which file that module or namespace is in, allowing you to use the functionality of the code in that file.
Python and C++ don't "build" the code in the same way and thus don't reference parts of the source code in the same way.
To illustrate this point more succinctly, take the following C++ code:
file: fun.hpp
#define FUN_NUM 1
namespace fun
{
int get_fun()
{
return FUN_NUM;
}
}
file: main.cpp
#include <iostream>
#include "fun.hpp"
int main(int argc, char* argvp[])
{
if (fun::get_fun() == FUN_NUM) {
std::cout << "Fun!" << std::endl;
}
return FUN_NUM;
}
In the above code, when we #include "fun.hpp", what the C++ pre-processor does before compiling is essentially "copy-and-paste" the code in iostream and fun.hpp, so what actually gets compiled is something like the following:
file: main.cpp
// #include <iostream> <- this is replaced with the whole std::iostream file
// not putting that here as it's huge.
// #include "fun.hpp" <- this is replaced with this:
#define FUN_NUM 1
namespace fun
{
int get_fun()
{
return FUN_NUM;
}
}
int main(int argc, char* argvp[])
{
if (fun::get_fun() == FUN_NUM) {
std::cout << "Fun!" << std::endl;
}
return FUN_NUM;
}
It is because of this "copy-paste" that you also need to have include guards, because if you did something like the following:
file: main.cpp
#include <iostream>
#include "fun.hpp"
#include "fun.hpp"
int main(int argc, char* argvp[])
{
if (fun::get_fun() == FUN_NUM) {
std::cout << "Fun!" << std::endl;
}
return FUN_NUM;
}
This code won't compile because you'll get errors about various items being redeclared since what gets compiled is the following:
file: main.cpp
// #include <iostream> <- this is replaced with the whole std::iostream file
// not putting that here as it's huge.
// #include "fun.hpp" <- this is replaced with this:
#define FUN_NUM 1
namespace fun
{
int get_fun()
{
return FUN_NUM;
}
}
// #include "fun.hpp" <- this is replaced with this:
#define FUN_NUM 1
namespace fun
{
int get_fun()
{
return FUN_NUM;
}
}
int main(int argc, char* argvp[])
{
if (fun::get_fun() == FUN_NUM) {
std::cout << "Fun!" << std::endl;
}
return FUN_NUM;
}
To protect from the double inclusion and redefinition, you can simply do something like the following:
file: fun.hpp
#if !defined(FUN_HPP)
#define FUN_HPP
#define FUN_NUM 1
namespace fun
{
int get_fun()
{
return FUN_NUM;
}
}
#endif // define FUN_HPP
So unless you pass FUN_HPP as a pre-processor define to the compiler, then FUN_HPP will not be defined until the file is #include'd once, then any other times it's included, FUN_HPP will already be defined and thus the pre-processor will not include the code again, ridding the problem of double-definitions.
So where your question is concerned, the #include directive in C++ is somewhat like the import directive in Python, but mostly to the effect that they both allow the file you are putting that directive in, to access code more directly from that import or #include.
I hope that can add a little clarity.

Eclipse C++ multiple main error only when using multiple headers

I'm trying to learn how to utilize header files in C++ projects, so I made .cpp files containing simple functions to make sure I'm doing all the declaring and including correctly.
Everything worked fine when I only had one set of .cpp and .h files, but when I try to add more I get errors.
To start with, in my project I had:
helloworld.cpp
#include "helloworld.h"
#include <iostream>
#include <cstdio>
using namespace std;
int HelloWorld() {
puts("Hello, World!");
cout << "Hello, World!" << endl;
return 0;
}
helloworld.h
#ifndef HELLOWORLD_H_INCLUDED
#define HELLOWORLD_H_INCLUDED
int HelloWorld();
#endif /* HELLOWORLD_H_INCLUDED */
main.cpp
#include "helloworld.h"
#include <iostream>
using namespace std;
int main(){
HelloWorld();
return 0;
}
Which built with no errors and ran correctly.
Next I tried adding a second .cpp and .h file, which created building errors.
pointers.cpp
#include "pointers.h"
#include <iostream>
using namespace std;
int Pointers() {
int x = 1;
int *ptr_a = &x;
cout << *ptr_a << endl;
return 0;
}
pointers.h
#ifndef POINTERS_H_INCLUDED
#ifndef POINTERS_H_INCLUDED
int Pointers();
#endif /* POINTERS_H_INCLUDED */
and modified main.cpp:
#include "helloworld.h"
#include "pointers.h"
#include <iostream>
using namespace std;
int main(){
HelloWorld();
Pointers();
return 0;
}
Now when I try to build, I get an error saying there are multiple definitions of main -- one in main.cpp, and the other in pointers.cpp.
Even more oddly, if I make a new project and do the exact same thing but reverse the order in which I create the .cpp and .h files (i.e. pointers first then helloworld), it builds and runs correctly with just the pointers files but runs into the same error when adding helloworld files, saying that the multiple exceptions of main are in main.cpp and helloworld.cpp.
I figure it must have something to do with Eclipse itself, but I don't know what the exact issue is.
Does anyone know what might be going on?

field declared void / struct or variable not declared in this scope

I've been teaching myself some OpenGL using SFML for creating windows/handling inputs, etc. My main.cpp started getting a bit unwieldy so I decided to start splitting my code up. I created a 4X_vertex.h and a 4X_vertex.cpp (4X is the name of the project) and moved the relevant functions and structs out of my main and into these files. However, when I compile, I get the error
variable or field "drawVertexArray" declared void
which from my research seems to be just an unhelpful message relating to the next error, which is
vertex was not declared in this scope
Here's my list of includes from my main.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include "4x_vertex.h"
#include "4x_constants.h"
My 4X_vertex.h:
#ifndef _4X_VERT_H
#define _4X_VERT_H
struct vertex{
GLfloat x,y,z;
GLfloat r,g,b;
};
void drawVertexArray(vertex v[]);
vertex* loadVertexData();
#include "4X_vertex.cpp"
#endif
The part of 4X_vertex.cpp that's giving me the trouble:
using namespace std;
void drawVertexArray(vertex v[]){
... openGL stuff...
}
All of this worked before I started moving it around so I'm assuming there's something weird going on with the includes, or something. All help is greatly appreciated!
Just some pointers. Best practice is to divide your project up into multiple source files. Typically, you would use the word "main" in the file name of the main source file (if applicable). So you might have something like...
main.cpp
feature1.cpp
feature2.cpp
tools.cpp
For your other files, you will typically name them after the class they implement. You will most often have both a .h and a .cpp. Put your declarations in the .h and your definitions in the .cpp had have the .cpp include the .h. That might give you...
main.cpp
feature1.cpp feature1.h
feature2.cpp feature2.h
tools.cpp tools.h
The modules that reference one of your classes includes it's .h as well. So, main.cpp might look like...
#include <iostream>
#include "feature1.h"
#include "feature2.h"
using namespace std;
void main(int argc, char **argv)
{ ...
cout << "Done!\n";
}
And feature1.cpp might be...
#include "feature1.h"
#include "tools.h"
feature1_class::feature1_class() { ... }
void feature1_class::AUsefulFeature(int val) { ... }
//etc.
...where feature1.h declares the class, defined constants, etc. f.g.,
#ifndef FEATURE1
#define FEATURE1
#include "tools.h"
class feature1_class
{
public:
feature1_class();
void AUsefulFeature(int val);
int APublicMember;
};
#endif
You may have noticed that tools.h is actually include twice in feature1.cpp. It is included from within the feature1.h and explicitly from the .cpp file. If you use the following pattern in your .h files ...
#ifndef TOOLS_H
#define TOOLS_H
//... do your thing
#endif
... then multiple includes shouldn't cause you any problems. And as you refactor code, it is one less thing to have to worry about cleaning up.
If you have been using a single file for all your source up till now, you may have been compiling like so...
cl main.cpp
Which gives you your .exe and .obj and maybe other files. But with multiple source files involved, it isnt much different. You can say...
cl main.cpp feature1.cpp feature2.cpp tools.cpp
There is much more to learn, but this is a start and helps you on the way to better organization of your coding thoughts.
You need to #include "4X_vertex.h" at the top of your 4X_vertex.cpp file. This will allow the .cpp file to see the declaration for the struct vertex.
In general, each file (both .h and .cpp files) needs to #include any header files which contain declarations for items used in that file. This includes the standard headers and OpenGL headers, as well as your custom ones.

LNK2005, "already defined error" linker error in MSVC2010

I am trying to implement a test project using the Point Cloud Library and OpenCV with multiple files. When I try to compile, I get the "already defined error" message. Probably I'm doing something stupid that cannot realize for some reason - I tried out a couple of solutions found here, none of them seemed to be help in my case.
What I have:
A libs.h file, where I load the lib files (in Project properties, I only set up the .lib paths and load the libs "by hand", like the headers):
#pragma once
#ifndef PCLTEST_LIBS
#define PCLTEST_LIBS
#ifdef _DEBUG
#pragma comment(lib, "pcl_apps-gd.lib")
#pragma comment(lib, "pcl_common-gd.lib")
// a bunch of other debug libs
#else
// the release libs
#endif
#endif
A main file from which I basically deleted everything at this point to debug:
// load the libs
#ifndef PCLTEST_LIBS
#include "libs.h"
#endif
// pcltest includes
// if only this first one is #included, everything is OK
#include "opencvOperations.h"
// #including this one causes the error
#include "files.h"
// these ones are not working also
//#include "cloudOperations.h"
//#include "visualize.h"
// c++ headers
#include <stdio.h>
#include <string>
//#include <sstream>
//#include <iostream>
void writeInfo()
{
// some std::cout calls
}
int main( int argc, char* argv[] )
{
writeInfo();
// this function is in opencvOperations.h and works OK
pcltest::openLena();
}
Then I get several error messages in my main.obj that some (PCL related) symbols are already defined in files.obj. I use PCL related calls both in opencvOperations and files, the first one is OK, the second one does not work.
Edit:
To add more detail, my files.h header:
#pragma once
#ifndef PCLTEST_FILES
#define PCLTEST_FILES
// pcl headers
#ifndef PCL_COMMON_H_
#include <pcl/common/common_headers.h>
#endif
#ifndef PCL_IO_FILE_IO_H_
#include <pcl/io/file_io.h>
#endif
#ifndef PCL_IO_PCD_IO_H_
#include <pcl/io/pcd_io.h>
#endif
#ifndef PCL_IO_PLY_IO_H_
#include <pcl/io/ply_io.h>
#endif
// boost headers
#ifndef BOOST_FILESYSTEM_OPERATIONSX_HPP
#include <boost/filesystem/operations.hpp>
#endif
#endif
namespace pcltest
{
// function to open PCL or binary PLY files
pcl::PointCloud<pcl::PointXYZ>::Ptr openCloud(std::string filename);
// function to save the point cloud to PCD format
void saveCloud();
}
Before splitting the code into separate files, everything worked well (with the same project settings).
Edit2:
I located the source of the problem,
#include <pcl/io/ply_io.h>
causes this. For now, I got rid of everything related to PLY and everything works fine. I'll look at it later, this might be a PCL library specific issue. Still strange to me why this call causes linker error in an other file, where I don't even use PLY related functions/variables.
I had the same problem as you had. I had a surface.h and surface.cpp file, and I found out that I had to include the ply_io.h file from surface.cpp rather than surface.h and now it compiles fine. I hope that helps or makes sense! haha
If a constant is being instantiated in an include one can also use selectany, per http://msdn.microsoft.com/en-us/library/5tkz6s71%28v=vs.80%29.aspx -- in my case:
const int CSdata[] = {1, 2, 3, 4};
when included in more than one source part produces LNK2005 at link time, avoided via:
const __declspec(selectany) int CSdata[] = {1, 2, 3, 4};
Non-portable, yeah ...