mirror of
https://github.com/unittest-cpp/unittest-cpp
synced 2026-09-26 16:19:30 +03:00
Merge 7c98f0a674 into c331bb0dea
This commit is contained in:
commit
d31befcf19
14 changed files with 574 additions and 2 deletions
81
UnitTest++/ArgumentsReader.cpp
Normal file
81
UnitTest++/ArgumentsReader.cpp
Normal file
|
|
@ -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
UnitTest++/ArgumentsReader.h
Normal file
21
UnitTest++/ArgumentsReader.h
Normal file
|
|
@ -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
UnitTest++/PredicateCmdBuilder.cpp
Normal file
23
UnitTest++/PredicateCmdBuilder.cpp
Normal file
|
|
@ -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
UnitTest++/PredicateCmdBuilder.h
Normal file
16
UnitTest++/PredicateCmdBuilder.h
Normal file
|
|
@ -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
UnitTest++/SuitePredicate.cpp
Normal file
105
UnitTest++/SuitePredicate.cpp
Normal file
|
|
@ -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
UnitTest++/SuitePredicate.h
Normal file
40
UnitTest++/SuitePredicate.h
Normal file
|
|
@ -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
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "TestDetails.h"
|
||||
#include <cstring> // "c" version required for gcc
|
||||
|
||||
namespace UnitTest {
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "TestReporterStdout.h"
|
||||
#include "TimeHelpers.h"
|
||||
#include "MemoryOutStream.h"
|
||||
#include "PredicateCmdBuilder.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "UnitTest++/UnitTestPP.h"
|
||||
|
||||
int main(int, char const *[])
|
||||
int main(int argc, char**argv)
|
||||
{
|
||||
return UnitTest::RunAllTests();
|
||||
return UnitTest::RunTestsCmd(argc, argv);
|
||||
}
|
||||
|
|
|
|||
88
tests/TestArgumentsReader.cpp
Normal file
88
tests/TestArgumentsReader.cpp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
#include "UnitTest++/UnitTestPP.h"
|
||||
#include "UnitTest++/ArgumentsReader.h"
|
||||
|
||||
using namespace UnitTest;
|
||||
|
||||
SUITE(ArgumentsReader)
|
||||
{
|
||||
TEST(Extract_IgnoreUndesired)
|
||||
{
|
||||
char full[] = "C:\\myProgram.exe";
|
||||
char valFake1[] = "fake";
|
||||
char valFake2[] = "fakeBis";
|
||||
char* argv[] = { full, valFake1, valFake2 };
|
||||
ArgumentsReader args(3, argv);
|
||||
|
||||
CHECK(args.extractValues("--unexisting").empty());
|
||||
}
|
||||
|
||||
TEST(Extract_CanExtractImplicitly)
|
||||
{
|
||||
char full[] = "C:\\myProgram.exe";
|
||||
char val1[] = "val1";
|
||||
char val2[] = "val2";
|
||||
char* argv[] = { full, val1, val2 };
|
||||
ArgumentsReader args(3, argv);
|
||||
|
||||
vector<string> values = args.extractValues("");
|
||||
REQUIRE CHECK_EQUAL(2u, values.size());
|
||||
CHECK_EQUAL(val1, values[0]);
|
||||
CHECK_EQUAL(val2, values[1]);
|
||||
}
|
||||
|
||||
|
||||
TEST(Extract_ReadSimple)
|
||||
{
|
||||
char full[] = "C:\\myProgram.exe";
|
||||
char paramToto[] = "--toto";
|
||||
char val1[] = "myTest";
|
||||
char* argv[] = { full, paramToto, val1 };
|
||||
ArgumentsReader args(3, argv);
|
||||
|
||||
vector<string> values = args.extractValues(paramToto);
|
||||
REQUIRE CHECK_EQUAL(1u, values.size());
|
||||
CHECK_EQUAL(val1, values[0]);
|
||||
}
|
||||
|
||||
|
||||
TEST(Extract_CanReadMultiple)
|
||||
{
|
||||
char full[] = "C:\\myProgram.exe";
|
||||
char fake[] = "fake";
|
||||
char paramToto[] = "--toto";
|
||||
char val1[] = "myTest";
|
||||
char val2[] = "myOtherTest";
|
||||
char* argv[] = { full, fake, paramToto, val1, val2 };
|
||||
ArgumentsReader args(5, argv);
|
||||
|
||||
CHECK(args.extractValues("--unexisting").empty());
|
||||
|
||||
vector<string> values = args.extractValues(paramToto);
|
||||
REQUIRE CHECK_EQUAL(2u, values.size());
|
||||
CHECK_EQUAL(val1, values[0]);
|
||||
CHECK_EQUAL(val2, values[1]);
|
||||
}
|
||||
|
||||
|
||||
TEST(Extract_BlindTest)
|
||||
{
|
||||
char full[] = "C:\\myProgram.exe";
|
||||
char fake[] = "fake";
|
||||
char paramToto[] = "--toto";
|
||||
char totoVal1[] = "myTest";
|
||||
char totoVal2[] = "myOtherTest";
|
||||
char paramTiti[] = "--titi";
|
||||
char titiVal[] = "yourTest";
|
||||
char* argv[] = { full, fake, paramToto, totoVal1, totoVal2, paramTiti, titiVal };
|
||||
ArgumentsReader args(7, argv);
|
||||
|
||||
vector<string> valuesToto = args.extractValues(paramToto);
|
||||
REQUIRE CHECK_EQUAL(2u, valuesToto.size());
|
||||
CHECK_EQUAL(totoVal1, valuesToto[0]);
|
||||
CHECK_EQUAL(totoVal2, valuesToto[1]);
|
||||
|
||||
vector<string> valuesTiti = args.extractValues(paramTiti);
|
||||
REQUIRE CHECK_EQUAL(1u, valuesTiti.size());
|
||||
CHECK_EQUAL(titiVal, valuesTiti[0]);
|
||||
}
|
||||
}
|
||||
100
tests/TestSuitePredicate.cpp
Normal file
100
tests/TestSuitePredicate.cpp
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
#include "UnitTest++/UnitTestPP.h"
|
||||
#include "UnitTest++/SuitePredicate.h"
|
||||
|
||||
SUITE(SuitePredicate)
|
||||
{
|
||||
using namespace UnitTest;
|
||||
|
||||
|
||||
TEST(Operator_DetectsTests)
|
||||
{
|
||||
SuitePredicate predicate;
|
||||
predicate.addTest("test1");
|
||||
predicate.addTest("testFake");
|
||||
|
||||
Test test1("test1", "suite1");
|
||||
Test test2("test2");
|
||||
|
||||
CHECK(predicate.operator()(&test1));
|
||||
CHECK(!predicate.operator()(&test2));
|
||||
}
|
||||
|
||||
|
||||
TEST(Operator_DetectsSuites)
|
||||
{
|
||||
SuitePredicate predicate;
|
||||
predicate.addSuite("suite1");
|
||||
predicate.addSuite("suiteFake");
|
||||
|
||||
Test test1("test1", "suite1");
|
||||
Test test2("test2");
|
||||
|
||||
CHECK(predicate.operator()(&test1));
|
||||
CHECK(!predicate.operator()(&test2));
|
||||
}
|
||||
|
||||
|
||||
TEST(Operator_WhenAddAll_AllAreAdded)
|
||||
{
|
||||
SuitePredicate predicate;
|
||||
predicate.addAll();
|
||||
|
||||
Test test1("test1", "suite1");
|
||||
Test test2("test2");
|
||||
|
||||
CHECK(predicate.operator()(&test1));
|
||||
CHECK(predicate.operator()(&test2));
|
||||
}
|
||||
|
||||
TEST(AddMultiple_AndCheckWithGetters)
|
||||
{
|
||||
vector<string> tests;
|
||||
tests.push_back("test1");
|
||||
tests.push_back("test2");
|
||||
|
||||
vector<string> suites;
|
||||
suites.push_back("suite1");
|
||||
suites.push_back("suite2");
|
||||
|
||||
SuitePredicate predicate;
|
||||
predicate.addTests(tests);
|
||||
predicate.addSuites(suites);
|
||||
|
||||
REQUIRE CHECK_EQUAL(tests.size(), predicate.getTests().size());
|
||||
CHECK_ARRAY_EQUAL(tests, predicate.getTests(), tests.size());
|
||||
|
||||
REQUIRE CHECK_EQUAL(suites.size(), predicate.getSuites().size());
|
||||
CHECK_ARRAY_EQUAL(suites, predicate.getSuites(), suites.size());
|
||||
}
|
||||
|
||||
|
||||
TEST(EmptyPredicate_IsFlaggedAsEmpty)
|
||||
{
|
||||
SuitePredicate predicate;
|
||||
CHECK(predicate.empty());
|
||||
}
|
||||
|
||||
|
||||
TEST(EmptyPredicate_WhenTestAdded_IsFlaggedAsNonEmpty)
|
||||
{
|
||||
SuitePredicate predicate;
|
||||
predicate.addTest("toto");
|
||||
CHECK(!predicate.empty());
|
||||
}
|
||||
|
||||
|
||||
TEST(EmptyPredicate_WhenSuiteAdded_IsFlaggedAsNonEmpty)
|
||||
{
|
||||
SuitePredicate predicate;
|
||||
predicate.addSuite("toto");
|
||||
CHECK(!predicate.empty());
|
||||
}
|
||||
|
||||
|
||||
TEST(EmptyPredicate_WhenAllAdded_IsFlaggedAsNonEmpty)
|
||||
{
|
||||
SuitePredicate predicate;
|
||||
predicate.addAll();
|
||||
CHECK(!predicate.empty());
|
||||
}
|
||||
}
|
||||
36
tests/TestTestDetails.cpp
Normal file
36
tests/TestTestDetails.cpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#include "UnitTest++/UnitTestPP.h"
|
||||
#include "UnitTest++/TestDetails.h"
|
||||
|
||||
|
||||
SUITE(TestDetails)
|
||||
{
|
||||
using namespace UnitTest;
|
||||
|
||||
TEST(SameTest_SameValues_AreEqual)
|
||||
{
|
||||
TestDetails details1("test1", "suite1", "file1", 1234);
|
||||
TestDetails details2("test1", "suite1", "file1", 1234);
|
||||
CHECK(details1.sameTest(details2));
|
||||
}
|
||||
|
||||
TEST(SameTest_DifferentValues_AreNotEqual)
|
||||
{
|
||||
TestDetails details1("test1", "suite1", "file1", 1234);
|
||||
TestDetails details2("test2", "suite2", "file2", 4321);
|
||||
CHECK(!details1.sameTest(details2));
|
||||
}
|
||||
|
||||
TEST(SameTest_LineNumber_AreIgnored)
|
||||
{
|
||||
TestDetails details1("test1", "suite1", "file1", 1234);
|
||||
TestDetails details2("test1", "suite1", "file1", 0);
|
||||
CHECK(details1.sameTest(details2));
|
||||
}
|
||||
|
||||
TEST(SameTest_CopyConstructor_AreEqual)
|
||||
{
|
||||
TestDetails details1("test1", "suite1", "file1", 1234);
|
||||
TestDetails details2(details1, 4321);
|
||||
CHECK(details1.sameTest(details2));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue