I have a C++ project which is being tested using Catch.cpp:
I compile and run the following file to run my tests:
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "test1.h"
#include "test2.h"
In the near future I'll want to run more complex tests, that require command line arguments.
In Other words, I would like to apply some logic to my tests runs, being able to run them from inside loops or conditions and pass variables to them.
I found this page: Supply your own main.
which seems like a good direction but i could not find a more detailed explanation.
Can this be done by catch? or maybe there is a better way to implement what i described?
What I managed to do is to write my own main, parse the command line and store the needed parameter (in my case an IP) in a global variable. Not the most beautiful code, but does the job:
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
std::string IP;
int main(int argc, char* const argv[])
{
Catch::Session session;
int returnCode = session.applyCommandLine(argc, argv, Catch::Session::OnUnusedOptions::Ignore);
if (returnCode != 0)
return returnCode;
for (auto token : session.unusedTokens()) {
printf("Token: %s\n", token.data.c_str());
IP = token.data;
}
return session.run();
}
I then run this as TestRunner.exe [test-case-tag] --MY_IP_HERE. Note that without the "--" in front of the parameter, they don't appear in the unusedTokens.
Related
I've been trying to call a program inside another c++ program using the command "execvp()" from the <unistd.h> library but it gets core dump, and i dont know what i am doing wrong;
below its the code i use to call the program i want to use
#include <iostream>
#include <unistd.h>
int main(int argc, char **argv)
{
char *argument_list[]={argv[1],argv[2],NULL};
char *filename = "./bin/program.exe";
execvp(filename, argument_list);
return 0;
}
below this, its the code of the program i want to call
#include <iostream>
int main(int argc, char **argv)
{
int a = atoi(argv[1]);
int b = atoi(argv[2]);
std::cout << a+b<<std::endl;
return 0;
}
when i compile the the first code, i get a "main.exe" binary, then i type "main.exe 5 6" to sum both integers, and i get the "core dump" error.
Curious thing is, if i run gdb on it, i get the sum i want
the first command line, its running directly the "child" program, showing that it works. The second command line, its using the "main" program that calls the child one
(Obviously, this programs aren't the ones i need to apply this, they're just for illustration of the problem, they're really big codes, and it wouldn't be helpful to post them here);
How can i fix this?
So, it works if i set the first argument as the filename, as said by #WhozCraig, so now it works, and looks like this:
#include
#include <unistd.h>
int main(int argc, char **argv)
{
char *argument_list[]={"program.exe",argv[1],argv[2],NULL};
char *filename = "./bin/program.exe";
execvp(filename, argument_list);
return 0;
}
However, i get this warning:
1
How can i get around it? Is there a problem leaving it like this?
Some of this code may seem foreign to you since I make 3ds homebrew programs for fun but it's essentially the same but with extra lines of code you can put in. I'm trying to read a file called about.txt in a separate folder. I made it work when I put it in the same folder but i lost that file and then my partner said he wanted it in Scratch3ds-master\assets\english\text and not in Scratch3ds-master\source I keep getting the error I coded in. I'm new to stack-overflow so this might be too much code but well here's the code:
#include <fstream>
#include <string>
#include <iostream>
int main()
{
// Initialize the services
gfxInitDefault();
consoleInit(GFX_TOP, NULL);
int version_major;
int version_minor;
int version_patch;
version_major = 0;
version_minor = 0;
version_patch = 2;
printf("This is the placeholder for Scratch3ds\n\n");
std::ifstream about_file;
about_file.open("../assets/english/text/about.txt");
if (about_file.fail())
{
std::cerr << "file has failed to load\n";
exit(1);
}
Chance are that you're using devkitpro packages. And chances are that the devkitpro team provide an equivalent of the NDS 'ARGV protocol' for 3DS programming. In which case, if you use
int main(int argc, char* argv[]);
you should have the full path to your executable in argv[0] if argc is non-zero.
https://devkitpro.org/wiki/Homebrew_Menu might help.
Your program has no a priori knowledge of what sort of arguments main() should receive, and in your question, you're using a main function that receives no argument at all.
Established standard for C/C++ programming is that main() will receive an array of constant C strings (typically named argv for arguments values) and the number of valid entries in that array (typically named argc for count). If you replace your original code with
#include <fstream>
#include <string>
#include <iostream>
int main(int argc, char* argv[])
{
// Initialize the services
// ... more code follows
then you're able to tell whether you received argument by testing argc > 0 and you'll be able to get these arguments values with argv[i].
With homebrew development, it is unlikely that you can pass arguments such as --force or --directory=/boot as on typical command-line tools, but there is one thing that is still useful: the very first entry in argv is supposed to be a full path for the running program. so you're welcome to try
std::cerr << ((argc > 0) ? argv[0] : "<no arguments>");
and see what you get.
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).
Hi I am new to C++ and Code::Block
I am trying to make a simple code to test it, using strings.
when I compile the code there is no problem, but when I try to debug it, Code::Block gives me the following warning:
Cannot open file:
File:../../../../../src/gcc-4.9.2/libgcc/unwind-sjlj.c
Info: "Multiple information windows with the same message have been
supressed."
Image of the error FYI:
Part of the code that gives me an error.
inside main function
#include <iostream>
#include <string>
int main ()
{
std::mystring("What's wrong with strings");
return 0;
}
I realise that this error only occurs when I try to debug a string or a file containing a string.
Any help would be appreciated.
some other information that might help:
Code::Block 16.01
Compiler MinGW gcc4.9.2
Windows 7 Professional 32 bits SP1
First of all, to use strings you must include the file header string. And the name of the type string is..std::string, not std::mystring.
#include <string>
int main(int argc, char** argv)
{
std::string mystring("Nothing's wrong with strings");
return 0;
}
#include <iostream>
using namespace std;
int main ()
{
string mystring = "Whats wrong with my string";
return 0;
}
If you write it in the following way, it should work.
It's safer to define strings like I showed it. It will be also easier for you if you add using namespace std in the beginning of every program if you are new to C++.
Trying to run some tests through the use of the boost test library by using the following code:
int main(int arg, char *argv[])
{
string help = "help";
#ifdef TESTING_CONSTANT
TestingPeerClass testingClass;
testingClass.test_method();
#else
//rest of the codre
#endif
}
Which calls the following test function found in another class called testing.h :
#define BOOST_TEST_MODULE mytest
#include <algorithm>
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(TestingPeerClass)
{
BOOST_CHECK(1 == 1);
}
when running the test a strange runtime error raises when it hits the BOOST_CHECK function.
I cant figure out why, any ideas? since when i built a new project it worked perfectly fine.