Skip to content

Run tests/suites using custom selection from command line #132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c92794c
Moved notion of "next test" from Test class to dedicated class TestLi…
killoctal Aug 29, 2016
546801f
Created method for compare TestDetails
killoctal Aug 29, 2016
2b10f11
created predicate "SuitePredicate"
killoctal Aug 29, 2016
468ed14
Created tests for TestDetails comparison
killoctal Aug 29, 2016
7772acd
Imported first basic version of RunTestsCmd
killoctal Aug 29, 2016
5d0847e
Used in main()
killoctal Aug 29, 2016
83b3040
Minor simplification
killoctal Aug 29, 2016
53c478d
Partially extracted ArgumentsReader
killoctal Aug 29, 2016
a6e914c
extracted in a dedicated class
killoctal Sep 8, 2016
93a5df8
simplification
killoctal Sep 8, 2016
a4a3b24
optionally allow implicit suite/test argument
killoctal Sep 8, 2016
c5ede39
Revert "Moved notion of "next test" from Test class to dedicated clas…
killoctal Sep 8, 2016
97e3228
Merge branch 'master' into TestRunnerCmd
killoctal Sep 8, 2016
0b15cf5
fixed wrong include
killoctal Sep 8, 2016
25b44ba
splitted "ArgumentsReader" h/cpp
killoctal Sep 8, 2016
79326cb
bug fix: wrong index
killoctal Sep 8, 2016
f12885a
created tests for ArgumentsReader
killoctal Sep 8, 2016
6b6006e
use method instead of direct data
killoctal Sep 9, 2016
a68d7b7
created tests for SuitePredicate
killoctal Sep 9, 2016
1e5d6ec
const methods
killoctal Sep 9, 2016
449a77c
small refactor
killoctal Sep 9, 2016
78fd096
improved comment of explainations
killoctal Sep 9, 2016
7e5608e
added virtual destructor
killoctal Sep 9, 2016
8b6a85d
minor optimisation
killoctal Sep 9, 2016
8d91f32
removed useless include
killoctal Sep 9, 2016
5dd0975
named suite TestDetails
killoctal Sep 9, 2016
6ca1119
possibility to disable implicit args
killoctal Sep 9, 2016
cd287cf
changed comment
killoctal Sep 9, 2016
ef3c0c8
Fixed warnings (treated as error)
killoctal Sep 9, 2016
d5e6fe1
fix for gcc: TestDetails.cpp:38:47: error: ‘strcmp’ was not declared …
killoctal Sep 9, 2016
f8e366b
added overload with same signatire as "int main(int argc, char**argv)"
killoctal Sep 12, 2016
b3b3df9
added comment
killoctal Sep 12, 2016
7c98f0a
fixed some int -> size_t
killoctal Sep 12, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions UnitTest++/ArgumentsReader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include "ArgumentsReader.h"

using namespace UnitTest;

ArgumentsReader::ArgumentsReader(int argc, char**argv)
{
_arguments.reserve(argc);
for (int i = 0; i < argc; i++)
{
_arguments.push_back(argv[i]);
}
}


ArgumentsReader::~ArgumentsReader()
{
}


bool ArgumentsReader::findArgumentListIndex(const string & argumentName, size_t & outFrom, size_t & outCount) const
{
if (_arguments.empty())
{
return false;
}
outCount = 0;
if (argumentName.empty())
{
outFrom = 1;
}
else
{
outFrom = 0;
for (size_t i = 1; i < _arguments.size(); i++)
{
if (argumentName == _arguments[i])
{
outFrom = i + 1;
break;
}
}
if (outFrom == 0)
{
return false;
}
}

for (size_t i = outFrom; i < _arguments.size(); i++)
{
const string & value = _arguments[i];
if (value.size() >= 2 && value.substr(0, 2) == "--")
{
break;
}
outCount++;
}

return true;
}


vector<string> ArgumentsReader::extractValues(const string & argumentName) const
{
size_t from, count;
if (!findArgumentListIndex(argumentName, from, count))
{
return vector<string>();
}
vector<string> values;
for (size_t i = from; i < from + count; i++)
{
values.push_back(getArgument(i));
}
return values;
}


string ArgumentsReader::getArgument(size_t index) const
{
return _arguments[index];
}
21 changes: 21 additions & 0 deletions UnitTest++/ArgumentsReader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <string>
#include <vector>

namespace UnitTest {

using namespace std;

class ArgumentsReader
{
public:
ArgumentsReader(int argc, char**argv);
virtual ~ArgumentsReader();

bool findArgumentListIndex(const string & argumentName, size_t & outFrom, size_t & outCount) const;
vector<string> extractValues(const string & argumentName) const;
string getArgument(size_t index) const;

private:
vector<string> _arguments;
};
}
23 changes: 23 additions & 0 deletions UnitTest++/PredicateCmdBuilder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "PredicateCmdBuilder.h"

using namespace UnitTest;


void PredicateCmdBuilder::fillSuitePredicate(const ArgumentsReader & arguments, SuitePredicate & outPredicate, bool allowImplicitArgs)
{
outPredicate.addSuites(arguments.extractValues("--suite"));
outPredicate.addTests(arguments.extractValues("--test"));

if (allowImplicitArgs)
{
vector<string> implicitArguments = arguments.extractValues("");
outPredicate.addSuites(implicitArguments);
outPredicate.addTests(implicitArguments);
}

if (outPredicate.empty())
{
outPredicate.addAll();
}
}

16 changes: 16 additions & 0 deletions UnitTest++/PredicateCmdBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef UNITTEST_PredicateCmdBuilder_H
#define UNITTEST_TESTRUNNERCMD_H

#include "ArgumentsReader.h"
#include "SuitePredicate.h"

namespace UnitTest {

class PredicateCmdBuilder
{
public:
static void fillSuitePredicate(const ArgumentsReader & arguments, SuitePredicate & outPredicate, bool allowImplicitArgs = true);
};
}

#endif
105 changes: 105 additions & 0 deletions UnitTest++/SuitePredicate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "SuitePredicate.h"

using namespace std;
using namespace UnitTest;


SuitePredicate::SuitePredicate()
: _all(false)
{
}


SuitePredicate::~SuitePredicate()
{
}


void SuitePredicate::addSuite(const string & suiteName)
{
_suiteNames.push_back(suiteName);
}


void SuitePredicate::addTest(const string & testName)
{
_testNames.push_back(testName);
}


void SuitePredicate::addSuites(const vector<string> & suiteNames)
{
for (size_t i = 0; i < suiteNames.size(); i++)
{
addSuite(suiteNames[i]);
}
}


void SuitePredicate::addTests(const vector<string> & testNames)
{
for (size_t i = 0; i < testNames.size(); i++)
{
addTest(testNames[i]);
}
}


void SuitePredicate::addAll()
{
_all = true;
}


bool SuitePredicate::empty()
{
if (!_suiteNames.empty())
{
return false;
}
if (!_testNames.empty())
{
return false;
}
if (_all)
{
return false;
}
return true;
}


bool SuitePredicate::operator()(Test const * const test) const
{
if (_all)
{
return true;
}
return (mustExecuteSuite(test) || mustExecuteTest(test));
}


bool SuitePredicate::mustExecuteSuite(Test const * const test) const
{
for (size_t i = 0; i < _suiteNames.size(); i++)
{
if (_suiteNames[i] == test->m_details.suiteName)
{
return true;
}
}
return false;
}


bool SuitePredicate::mustExecuteTest(Test const * const test) const
{
for (size_t i = 0; i < _testNames.size(); i++)
{
if (_testNames[i] == test->m_details.testName)
{
return true;
}
}
return false;
}
40 changes: 40 additions & 0 deletions UnitTest++/SuitePredicate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#ifndef UNITTEST_SUITEPREDICATE_H
#define UNITTEST_SUITEPREDICATE_H

#include <string>
#include <vector>
#include "Test.h"

namespace UnitTest
{
using namespace std;

class UNITTEST_LINKAGE SuitePredicate
{
public:
SuitePredicate();
virtual ~SuitePredicate();

void addSuite(const string & suiteName);
void addTest(const string & testName);
void addSuites(const vector<string> & suiteNames);
void addTests(const vector<string> & testNames);
void addAll();
bool empty();

bool operator()(Test const * const test) const;

const vector<string> & getSuites() const { return _suiteNames; }
const vector<string> & getTests() const { return _testNames; }

private:
bool mustExecuteSuite(Test const * const test) const;
bool mustExecuteTest(Test const * const test) const;

vector<string> _suiteNames;
vector<string> _testNames;
bool _all;
};
}

#endif
25 changes: 25 additions & 0 deletions UnitTest++/TestDetails.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "TestDetails.h"
#include <cstring> // "c" version required for gcc

namespace UnitTest {

Expand All @@ -18,5 +19,29 @@ namespace UnitTest {
, timeConstraintExempt(details.timeConstraintExempt)
{}

bool TestDetails::sameTest(const TestDetails & details) const
{
if (&details == this)
{
return true;
}

// Fast pointer comparison
if (details.suiteName == suiteName &&
details.testName == testName &&
details.filename == filename)
{
return true;
}

// Long string comparison
if (!strcmp(details.suiteName, suiteName) &&
!strcmp(details.testName, testName) &&
!strcmp(details.filename, filename))
{
return true;
}

return false;
}
}
2 changes: 2 additions & 0 deletions UnitTest++/TestDetails.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace UnitTest {
int const lineNumber;
mutable bool timeConstraintExempt;

bool sameTest(const TestDetails & details) const;

TestDetails(TestDetails const&); // Why is it public? --> http://gcc.gnu.org/bugs.html#cxx_rvalbind
private:
TestDetails& operator=(TestDetails const&);
Expand Down
16 changes: 16 additions & 0 deletions UnitTest++/TestRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "TestReporterStdout.h"
#include "TimeHelpers.h"
#include "MemoryOutStream.h"
#include "PredicateCmdBuilder.h"

#include <cstring>

Expand All @@ -17,6 +18,21 @@ namespace UnitTest {
return runner.RunTestsIf(Test::GetTestList(), NULL, True(), 0);
}

int RunTestsCmd(int argc, char**argv, bool allowImplicitArgs)
{
SuitePredicate predicate;
ArgumentsReader arguments(argc, argv);
PredicateCmdBuilder::fillSuitePredicate(arguments, predicate, allowImplicitArgs);

TestReporterStdout reporter;
TestRunner runner(reporter);
return runner.RunTestsIf(Test::GetTestList(), 0, predicate, 0);
}

int RunTestsCmd(int argc, char**argv)
{
return RunTestsCmd(argc, argv, true);
}

TestRunner::TestRunner(TestReporter& reporter)
: m_reporter(&reporter)
Expand Down
19 changes: 19 additions & 0 deletions UnitTest++/TestRunner.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,25 @@ namespace UnitTest {
class TestResults;
class Timer;

/**
* Run tests/suites using custom selection from command line.
*
* Commands:
* --test One or multiple test names to execute, can be combined with --suite
* --suite One or multiple suite names to execute, can be combined with --test
*
* Special feature: You do not have to specify explicitely --test and --suite, you
* can mix suite names and test names and the cmd will find the way. The
* constraint is that it must have no arguments beginning with --.
* For disabling this feature, set allowImplicitArgs=false
*
* Usage examples:
* Explicit: myTests.exe --suite MySuite1 MyOtherSuite --test MySpecialTest MyOtherTest
* Implicit: myTests.exe MySpecialTest MyOtherTest MySuite1
*/
UNITTEST_LINKAGE int RunTestsCmd(int argc, char**argv, bool allowImplicitArgs);
UNITTEST_LINKAGE int RunTestsCmd(int argc, char**argv); // Important: keep version with same signature as int main()

UNITTEST_LINKAGE int RunAllTests();

struct True
Expand Down
Loading