Skip to content

Commit df9b7be

Browse files
committed
testrunner: made -x work with individual tests [skip ci]
1 parent 89c39ec commit df9b7be

5 files changed

Lines changed: 92 additions & 64 deletions

File tree

test/fixture.cpp

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,24 @@ bool TestFixture::prepareTest(const char testname[])
9999
prepareTestInternal();
100100

101101
// Check if tests should be executed
102-
if (testToRun.empty() || testToRun == testname) {
103-
// Tests will be executed - prepare them
104-
mTestname = testname;
105-
++countTests;
106-
std::string fullTestName = classname + "::" + mTestname;
107-
if (quiet_tests) {
108-
std::putchar('.'); // Use putchar to write through redirection of std::cout/cerr
109-
std::fflush(stdout);
110-
} else {
111-
std::cout << fullTestName << std::endl;
112-
}
113-
mTimer.reset(new Timer(fullTestName, ShowTime::TOP5_SUMMARY, timerResults));
114-
return !dry_run;
102+
if (!testsToRun.empty()) {
103+
const bool match = testsToRun.count(testname);
104+
if ((match && exclude_tests) || (!match && !exclude_tests))
105+
return false;
106+
}
107+
108+
// Tests will be executed - prepare them
109+
mTestname = testname;
110+
++countTests;
111+
std::string fullTestName = classname + "::" + mTestname;
112+
if (quiet_tests) {
113+
std::putchar('.'); // Use putchar to write through redirection of std::cout/cerr
114+
std::fflush(stdout);
115+
} else {
116+
std::cout << fullTestName << std::endl;
115117
}
116-
return false;
118+
mTimer.reset(new Timer(fullTestName, ShowTime::TOP5_SUMMARY, timerResults));
119+
return !dry_run;
117120
}
118121

119122
void TestFixture::teardownTest()
@@ -358,9 +361,9 @@ void TestFixture::printHelp()
358361
" -x Exclude the specified tests.\n";
359362
}
360363

361-
void TestFixture::run(const std::string &str)
364+
void TestFixture::run(const std::set<std::string> &tests)
362365
{
363-
testToRun = str;
366+
testsToRun = tests;
364367
try {
365368
if (quiet_tests) {
366369
std::cout << '\n' << classname << ':';
@@ -388,6 +391,7 @@ void TestFixture::processOptions(const options& args)
388391
{
389392
quiet_tests = args.quiet();
390393
dry_run = args.dry_run();
394+
exclude_tests = args.exclude_tests();
391395
exename = args.exe();
392396
timerResults = args.timer_results();
393397
}
@@ -397,27 +401,27 @@ std::size_t TestFixture::runTests(const options& args)
397401
countTests = 0;
398402
errmsg.str("");
399403

404+
const auto& which_tests = args.which_tests();
405+
const auto exclude_tests = args.exclude_tests();
406+
400407
// TODO: bail out when given class/test is not found?
401-
for (std::string classname : args.which_test()) {
402-
std::string testname;
403-
const std::string::size_type pos = classname.find("::");
404-
if (pos != std::string::npos) {
405-
// TODO: excluding indiviual tests is not supported yet
406-
testname = classname.substr(pos + 2);
407-
classname.erase(pos);
408+
for (TestInstance * test : TestRegistry::theInstance().tests())
409+
{
410+
std::set<std::string> tests;
411+
if (!which_tests.empty()) {
412+
const auto it = which_tests.find(test->classname);
413+
const bool match = it != which_tests.cend();
414+
if (match && exclude_tests && it->second.empty()) // only bailout when the whole fixture is excluded
415+
continue;
416+
if (!match && !exclude_tests)
417+
continue;
418+
if (match)
419+
tests = it->second;
408420
}
409421

410-
for (TestInstance * test : TestRegistry::theInstance().tests()) {
411-
if (!classname.empty()) {
412-
const bool match = test->classname == classname;
413-
if ((match && args.exclude_tests()) || (!match && !args.exclude_tests()))
414-
continue;
415-
}
416-
417-
TestFixture* fixture = test->create();
418-
fixture->processOptions(args);
419-
fixture->run(testname);
420-
}
422+
TestFixture* fixture = test->create();
423+
fixture->processOptions(args);
424+
fixture->run(tests);
421425
}
422426

423427
if (args.summary() && !args.dry_run()) {

test/fixture.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <exception>
3535
#include <list>
3636
#include <memory>
37+
#include <set>
3738
#include <sstream>
3839
#include <stdexcept>
3940
#include <string>
@@ -58,9 +59,10 @@ class TestFixture : public ErrorLogger {
5859

5960
protected:
6061
std::string exename;
61-
std::string testToRun;
62+
std::set<std::string> testsToRun;
6263
bool quiet_tests{};
6364
bool dry_run{};
65+
bool exclude_tests{};
6466
bool mNewTemplate{};
6567
TimerResultsIntf* timerResults{};
6668

@@ -295,7 +297,7 @@ class TestFixture : public ErrorLogger {
295297
{
296298
(void) metric;
297299
}
298-
void run(const std::string &str);
300+
void run(const std::set<std::string> &tests);
299301

300302
public:
301303
static void printHelp();

test/options.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,33 @@
2020

2121
// TODO: bailout on unknown arguments
2222
options::options(int argc, const char* const argv[])
23-
: mWhichTests(argv + 1, argv + argc)
24-
,mQuiet(mWhichTests.count("-q") != 0)
25-
,mHelp(mWhichTests.count("-h") != 0 || mWhichTests.count("--help"))
26-
,mSummary(mWhichTests.count("-n") == 0)
27-
,mDryRun(mWhichTests.count("-d") != 0)
28-
,mExcludeTests(mWhichTests.count("-x") != 0)
23+
: mArgs(argv + 1, argv + argc)
24+
,mQuiet(mArgs.count("-q") != 0)
25+
,mHelp(mArgs.count("-h") != 0 || mArgs.count("--help"))
26+
,mSummary(mArgs.count("-n") == 0)
27+
,mDryRun(mArgs.count("-d") != 0)
28+
,mExcludeTests(mArgs.count("-x") != 0)
2929
,mExe(argv[0])
3030
{
3131
if (mArgs.count("-t") != 0)
3232
mTimerResults.reset(new TimerResults);
3333

34-
for (auto it = mWhichTests.cbegin(); it != mWhichTests.cend();) {
35-
if (!it->empty() && (((*it)[0] == '-') || (it->find("::") != std::string::npos && mWhichTests.count(it->substr(0, it->find("::"))))))
36-
it = mWhichTests.erase(it);
37-
else
38-
++it;
39-
}
40-
41-
if (mWhichTests.empty()) {
42-
mWhichTests.insert("");
34+
for (const auto& arg : mArgs) {
35+
if (arg.empty())
36+
continue; // empty argument
37+
if (arg[0] == '-')
38+
continue; // command-line switch
39+
const auto pos = arg.find("::");
40+
if (pos == std::string::npos) {
41+
mWhichTests[arg] = {}; // run whole fixture
42+
continue;
43+
}
44+
const std::string fixture = arg.substr(0, pos);
45+
const auto it = mWhichTests.find(fixture);
46+
if (it != mWhichTests.cend() && it->second.empty())
47+
continue; // whole fixture is already included
48+
const std::string test = arg.substr(pos+2);
49+
mWhichTests[fixture].emplace(test); // run individual test
4350
}
4451
}
4552

@@ -69,7 +76,7 @@ bool options::dry_run() const
6976
return mDryRun;
7077
}
7178

72-
const std::set<std::string>& options::which_test() const
79+
const std::map<std::string, std::set<std::string>>& options::which_tests() const
7380
{
7481
return mWhichTests;
7582
}

test/options.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef OPTIONS_H
1818
#define OPTIONS_H
1919

20+
#include <map>
2021
#include <memory>
2122
#include <set>
2223
#include <string>
@@ -46,8 +47,8 @@ class options {
4647
bool exclude_tests() const;
4748
/** The timer results. */
4849
TimerResultsIntf* timer_results() const;
49-
/** Which test should be run. Empty string means 'all tests' */
50-
const std::set<std::string>& which_test() const;
50+
/** Which tests should be run. */
51+
const std::map<std::string, std::set<std::string>>& which_tests() const;
5152

5253
const std::string& exe() const;
5354

@@ -56,7 +57,8 @@ class options {
5657
options& operator =(const options&) = delete;
5758

5859
private:
59-
std::set<std::string> mWhichTests;
60+
std::set<std::string> mArgs;
61+
std::map<std::string, std::set<std::string>> mWhichTests;
6062
const bool mQuiet;
6163
const bool mHelp;
6264
const bool mSummary;

test/testoptions.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,28 @@ class TestOptions : public TestFixture {
5151
void which_test() const {
5252
const char* argv[] = {"./test_runner", "TestClass"};
5353
options args(getArrayLength(argv), argv);
54-
ASSERT(std::set<std::string> {"TestClass"} == args.which_test());
54+
const std::map<std::string, std::set<std::string>> expected{
55+
{ "TestClass", {} }
56+
};
57+
ASSERT(expected == args.which_tests());
5558
}
5659

5760

5861
void which_test_method() const {
5962
const char* argv[] = {"./test_runner", "TestClass::TestMethod"};
6063
options args(getArrayLength(argv), argv);
61-
ASSERT(std::set<std::string> {"TestClass::TestMethod"} == args.which_test());
64+
const std::map<std::string, std::set<std::string>> expected{
65+
{ "TestClass", {"TestMethod"} }
66+
};
67+
ASSERT(expected == args.which_tests());
6268
}
6369

6470

6571
void no_test_method() const {
6672
const char* argv[] = {"./test_runner"};
6773
options args(getArrayLength(argv), argv);
68-
ASSERT(std::set<std::string> {""} == args.which_test());
74+
const std::map<std::string, std::set<std::string>> expected{};
75+
ASSERT(expected == args.which_tests());
6976
}
7077

7178

@@ -105,22 +112,28 @@ class TestOptions : public TestFixture {
105112
void multiple_testcases() const {
106113
const char* argv[] = {"./test_runner", "TestClass::TestMethod", "TestClass::AnotherTestMethod"};
107114
options args(getArrayLength(argv), argv);
108-
std::set<std::string> expected {"TestClass::TestMethod", "TestClass::AnotherTestMethod"};
109-
ASSERT(expected == args.which_test());
115+
const std::map<std::string, std::set<std::string>> expected{
116+
{ "TestClass", { "TestMethod" , "AnotherTestMethod" } }
117+
};
118+
ASSERT(expected == args.which_tests());
110119
}
111120

112121
void multiple_testcases_ignore_duplicates() const {
113122
const char* argv[] = {"./test_runner", "TestClass::TestMethod", "TestClass"};
114123
options args(getArrayLength(argv), argv);
115-
std::set<std::string> expected {"TestClass"};
116-
ASSERT(expected == args.which_test());
124+
const std::map<std::string, std::set<std::string>> expected{
125+
{ "TestClass", {} }
126+
};
127+
ASSERT(expected == args.which_tests());
117128
}
118129

119130
void invalid_switches() const {
120131
const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-a", "-v", "-q"};
121132
options args(getArrayLength(argv), argv);
122-
std::set<std::string> expected {"TestClass::TestMethod"};
123-
ASSERT(expected == args.which_test());
133+
const std::map<std::string, std::set<std::string>> expected {
134+
{ "TestClass", { "TestMethod" } }
135+
};
136+
ASSERT(expected == args.which_tests());
124137
ASSERT_EQUALS(true, args.quiet());
125138
}
126139

0 commit comments

Comments
 (0)