How do I run a single test with UnitTest++?
How do I run a single test with UnitTest++ ?
I am running UnitTest++ out of the box as is. My main
function looks like:
int main()
{
printf("diamond test v0.1 %s\n\n",TIMESTAMP);
diamond::startup();
UnitTest::RunAllTests();
diamond::shutdown();
printf("press any 开发者_如何学Gokey to continue...");
getc(stdin);
}
For debugging I would like to write something like UnitTest::RunSingleTests("MyNewUnitTest");
instead of UnitTest::RunAllTests();
. Does UnitTest++ provide such a function and if so, what is the syntax?
try this as your main() for unittest (I actually put this in a file and added that to the unittest library, so that when linking to the library the executable automatically uses this main(). very convenient.)
int main( int argc, char** argv )
{
if( argc > 1 )
{
//if first arg is "suite", we search for suite names instead of test names
const bool bSuite = strcmp( "suite", argv[ 1 ] ) == 0;
//walk list of all tests, add those with a name that
//matches one of the arguments to a new TestList
const TestList& allTests( Test::GetTestList() );
TestList selectedTests;
Test* p = allTests.GetHead();
while( p )
{
for( int i = 1 ; i < argc ; ++i )
if( strcmp( bSuite ? p->m_details.suiteName
: p->m_details.testName, argv[ i ] ) == 0 )
selectedTests.Add( p );
p = p->next;
}
//run selected test(s) only
TestReporterStdout reporter;
TestRunner runner( reporter );
return runner.RunTestsIf( selectedTests, 0, True(), 0 );
}
else
{
return RunAllTests();
}
}
invoke with arguments to run a single test:
> myexe MyTestName
or single suite
> myexe suite MySuite
This is almost correct. "Test" actually is purposed as a node in a linked list, so when you add it to a new list, you have to correct the pointer to avoid including more tests than you intended.
So you need to replace
p = p->next;
with
Test* q = p;
p = p->next;
q->next = NULL;
Geoffrey
RunTestsIf can only run one suite if you tell it the name.
class MyTrue
{
public:
MyTrue(const std::string & suiteName, const std::string & testName)
: suite(suiteName), test(testName) {}
bool operator()(const UnitTest::Test* const testCase) const
{
return suite.compare(testCase->m_details.suiteName) == 0 &&
test.compare(testCase->m_details.testName) == 0;
}
private:
std::string suite;
std::string test;
};
int main (...) {
bool isSuite = false;
std::string suiteName = "suite01";
std::string testName = "test01";
UnitTest::TestReporterStdout reporter;
UnitTest::TestRunner runner(reporter);
if (isSuite) {
runner.RunTestsIf(UnitTest::Test::GetTestList(),
NULL, MyTrue(suiteName, testName), 0);
} else {
runner.RunTestsIf(UnitTest::Test::GetTestList(),
NULL, UnitTest::True(), 0);
}
}
You could do this by using the predicate
parameter of RunTestsIf
:
TestReporterStdout reporter;
TestRunner runner(reporter);
return runner.RunTestsIf(Test::GetTestList(), "MySuite",
[](Test* t) {
return strcmp(t->m_details.testName, "MyTest") == 0;
}, 0);
If you do not have suites, or you want to search all of them, you can replace "MySuite"
with NULL
.
The answer given by @stijn has a bug in the test list manipulation, and therefore it usually runs additional tests that you did not request.
This example uses a predicate functor and also exploits the built-in suite name matching provided by RunTestsIf. It is correct and much simpler.
#include "UnitTest++.h"
#include "TestReporterStdout.h"
#include <string.h>
using namespace UnitTest;
/// Predicate that is true for tests with matching name,
/// or all tests if no names were given.
class Predicate
{
public:
Predicate(const char **tests, int nTests)
: _tests(tests),
_nTests(nTests)
{
}
bool operator()(Test *test) const
{
bool match = (_nTests == 0);
for (int i = 0; !match && i < _nTests; ++i) {
if (!strcmp(test->m_details.testName, _tests[i])) {
match = true;
}
}
return match;
}
private:
const char **_tests;
int _nTests;
};
int main(int argc, const char** argv)
{
const char *suiteName = 0;
int arg = 1;
// Optional "suite" arg must be followed by a suite name.
if (argc >=3 && strcmp("suite", argv[arg]) == 0) {
suiteName = argv[++arg];
++arg;
}
// Construct predicate that matches any tests given on command line.
Predicate pred(argv + arg, argc - arg);
// Run tests that match any given suite and tests.
TestReporterStdout reporter;
TestRunner runner(reporter);
return runner.RunTestsIf(Test::GetTestList(), suiteName, pred, 0);
}
The solution in the accepted answer is not working for me. When the first test of the suite is loaded into p it just won't jump to the next test (don't know exactly why).
I'm using Xcode and UnitTest++ v1.4
#include "UnitTest++.h"
#include "TestReporterStdout.h"
#define SUITE_NAME "ActionFeedback"
using namespace UnitTest;
int main( int argc, char** argv )
{
#ifdef SUITE_NAME
TestReporterStdout reporter;
TestRunner runner( reporter );
return runner.RunTestsIf( Test::GetTestList() , SUITE_NAME , True(), 0 );
#else
return RunAllTests();
#endif
}
精彩评论