mirror of
https://github.com/unittest-cpp/unittest-cpp
synced 2026-09-26 16:19:30 +03:00
r8 | charles.nicholson | 2010-03-16 21:27:33 -0500 (Tue, 16 Mar 2010) | 1 line
fixed bug where tests weren't correctly executing while testing the TestRunner (accessing the Details and Results singletons was redirecting failures to bogus RecordingReporters, instead of the real UT++ test engine). Hoisted assert failure reporting into ReportAssert, in preparation for setjmp/longjmp assert handling in the absence of exceptions. Slight renamings and cosmetic fixups
This commit is contained in:
parent
ab8b818591
commit
3a40aa80a1
16 changed files with 196 additions and 98 deletions
|
|
@ -2,38 +2,16 @@
|
|||
|
||||
#ifdef UNITTEST_USE_EXCEPTIONS
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace UnitTest {
|
||||
|
||||
AssertException::AssertException(char const* description, char const* filename, int lineNumber)
|
||||
: m_lineNumber(lineNumber)
|
||||
AssertException::AssertException()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
strcpy(m_description, description);
|
||||
strcpy(m_filename, filename);
|
||||
}
|
||||
|
||||
AssertException::~AssertException()
|
||||
{
|
||||
}
|
||||
|
||||
char const* AssertException::what() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
char const* AssertException::Filename() const
|
||||
{
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
int AssertException::LineNumber() const
|
||||
{
|
||||
return m_lineNumber;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,18 +12,8 @@ namespace UnitTest {
|
|||
class AssertException : public std::exception
|
||||
{
|
||||
public:
|
||||
AssertException(char const* description, char const* filename, int lineNumber);
|
||||
AssertException();
|
||||
virtual ~AssertException();
|
||||
|
||||
virtual char const* what() const;
|
||||
|
||||
char const* Filename() const;
|
||||
int LineNumber() const;
|
||||
|
||||
private:
|
||||
char m_description[512];
|
||||
char m_filename[256];
|
||||
int m_lineNumber;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,10 +130,15 @@
|
|||
if (!caught_) \
|
||||
UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), "Expected exception: \"" #ExpectedExceptionType "\" not thrown"); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
|
||||
#define CHECK_ASSERT(expression) \
|
||||
CHECK_THROW(expression, UnitTest::AssertException);
|
||||
do \
|
||||
{ \
|
||||
UnitTest::ExpectAssert(true); \
|
||||
CHECK_THROW(expression, UnitTest::AssertException); \
|
||||
UnitTest::ExpectAssert(false); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,9 +14,10 @@
|
|||
namespace UnitTest {
|
||||
|
||||
template< typename T >
|
||||
void ExecuteTest(T& testObject, TestDetails const& details)
|
||||
void ExecuteTest(T& testObject, TestDetails const& details, bool isMockTest)
|
||||
{
|
||||
CurrentTest::Details() = &details;
|
||||
if (isMockTest == false)
|
||||
CurrentTest::Details() = &details;
|
||||
|
||||
#ifndef UNITTEST_POSIX
|
||||
UT_TRY
|
||||
|
|
@ -33,8 +34,7 @@ void ExecuteTest(T& testObject, TestDetails const& details)
|
|||
|
||||
UT_CATCH(AssertException, e,
|
||||
{
|
||||
CurrentTest::Results()->OnTestFailure(
|
||||
TestDetails(details.testName, details.suiteName, e.Filename(), e.LineNumber()), e.what());
|
||||
(void)e;
|
||||
})
|
||||
UT_CATCH(std::exception, e,
|
||||
{
|
||||
|
|
@ -44,7 +44,7 @@ void ExecuteTest(T& testObject, TestDetails const& details)
|
|||
})
|
||||
UT_CATCH_ALL
|
||||
({
|
||||
CurrentTest::Results()->OnTestFailure(details, "Unhandled exception: Crash!");
|
||||
CurrentTest::Results()->OnTestFailure(details, "Unhandled exception: test crashed");
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,52 @@
|
|||
#include "ReportAssert.h"
|
||||
#include "AssertException.h"
|
||||
#include "CurrentTest.h"
|
||||
#include "TestResults.h"
|
||||
#include "TestDetails.h"
|
||||
|
||||
namespace UnitTest {
|
||||
|
||||
namespace
|
||||
{
|
||||
bool& AssertExpectedFlag()
|
||||
{
|
||||
static bool s_assertExpected = false;
|
||||
return s_assertExpected;
|
||||
}
|
||||
}
|
||||
|
||||
void ReportAssert(char const* description, char const* filename, int lineNumber)
|
||||
{
|
||||
(void)description;
|
||||
(void)filename;
|
||||
(void)lineNumber;
|
||||
ReportAssertEx(CurrentTest::Results(), CurrentTest::Details(), description, filename, lineNumber);
|
||||
}
|
||||
|
||||
void ReportAssertEx(TestResults* testResults,
|
||||
const TestDetails* testDetails,
|
||||
char const* description,
|
||||
char const* filename,
|
||||
int lineNumber)
|
||||
{
|
||||
if (AssertExpectedFlag() == false)
|
||||
{
|
||||
TestDetails assertDetails(testDetails->testName, testDetails->suiteName, filename, lineNumber);
|
||||
testResults->OnTestFailure(assertDetails, description);
|
||||
}
|
||||
|
||||
ExpectAssert(false);
|
||||
|
||||
#ifdef UNITTEST_USE_EXCEPTIONS
|
||||
throw AssertException(description, filename, lineNumber);
|
||||
throw AssertException();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ExpectAssert(bool expected)
|
||||
{
|
||||
AssertExpectedFlag() = expected;
|
||||
}
|
||||
|
||||
bool AssertExpected()
|
||||
{
|
||||
return AssertExpectedFlag();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,20 @@
|
|||
|
||||
namespace UnitTest {
|
||||
|
||||
class TestResults;
|
||||
class TestDetails;
|
||||
|
||||
void ReportAssert(char const* description, char const* filename, int lineNumber);
|
||||
|
||||
|
||||
void ReportAssertEx(TestResults* testResults,
|
||||
const TestDetails* testDetails,
|
||||
char const* description,
|
||||
char const* filename,
|
||||
int lineNumber);
|
||||
|
||||
void ExpectAssert(bool expected);
|
||||
bool AssertExpected();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ TestList& Test::GetTestList()
|
|||
|
||||
Test::Test(char const* testName, char const* suiteName, char const* filename, int lineNumber)
|
||||
: m_details(testName, suiteName, filename, lineNumber)
|
||||
, next(0)
|
||||
, m_nextTest(0)
|
||||
, m_timeConstraintExempt(false)
|
||||
, m_isMockTest(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ Test::~Test()
|
|||
|
||||
void Test::Run()
|
||||
{
|
||||
ExecuteTest(*this, m_details);
|
||||
ExecuteTest(*this, m_details, m_isMockTest);
|
||||
}
|
||||
|
||||
void Test::RunImpl() const
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ public:
|
|||
void Run();
|
||||
|
||||
TestDetails const m_details;
|
||||
Test* next;
|
||||
Test* m_nextTest;
|
||||
mutable bool m_timeConstraintExempt;
|
||||
mutable bool m_isMockTest;
|
||||
|
||||
static TestList& GetTestList();
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ void TestList::Add(Test* test)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_tail->next = test;
|
||||
m_tail->m_nextTest = test;
|
||||
m_tail = test;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,11 +83,11 @@
|
|||
({ \
|
||||
Fixture##Name##Helper fixtureHelper(m_details); \
|
||||
ctorOk = true; \
|
||||
UnitTest::ExecuteTest(fixtureHelper, m_details); \
|
||||
UnitTest::ExecuteTest(fixtureHelper, m_details, false); \
|
||||
}) \
|
||||
UT_CATCH (UnitTest::AssertException, e, \
|
||||
{ \
|
||||
UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(m_details.testName, m_details.suiteName, e.Filename(), e.LineNumber()), e.what()); \
|
||||
(void)e; \
|
||||
}) \
|
||||
UT_CATCH (std::exception, e, \
|
||||
{ \
|
||||
|
|
|
|||
|
|
@ -32,6 +32,11 @@ TestRunner::~TestRunner()
|
|||
delete m_timer;
|
||||
}
|
||||
|
||||
TestResults* TestRunner::GetTestResults()
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
int TestRunner::Finish() const
|
||||
{
|
||||
float const secondsElapsed = static_cast<float>(m_timer->GetTimeInMs() / 1000.0);
|
||||
|
|
@ -51,7 +56,8 @@ bool TestRunner::IsTestInSuite(const Test* const curTest, char const* suiteName)
|
|||
|
||||
void TestRunner::RunTest(TestResults* const result, Test* const curTest, int const maxTestTimeInMs) const
|
||||
{
|
||||
CurrentTest::Results() = result;
|
||||
if (curTest->m_isMockTest == false)
|
||||
CurrentTest::Results() = result;
|
||||
|
||||
Timer testTimer;
|
||||
testTimer.Start();
|
||||
|
|
@ -70,7 +76,7 @@ void TestRunner::RunTest(TestResults* const result, Test* const curTest, int con
|
|||
result->OnTestFailure(curTest->m_details, stream.GetText());
|
||||
}
|
||||
|
||||
result->OnTestFinish(curTest->m_details, static_cast<float>(testTimeInMs/1000.0));
|
||||
result->OnTestFinish(curTest->m_details, static_cast< float >(testTimeInMs / 1000.0));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public:
|
|||
explicit TestRunner(TestReporter& reporter);
|
||||
~TestRunner();
|
||||
|
||||
template <class Predicate>
|
||||
template< class Predicate >
|
||||
int RunTestsIf(TestList const& list, char const* suiteName,
|
||||
const Predicate& predicate, int maxTestTimeInMs) const
|
||||
{
|
||||
|
|
@ -38,12 +38,14 @@ public:
|
|||
if (IsTestInSuite(curTest, suiteName) && predicate(curTest))
|
||||
RunTest(m_result, curTest, maxTestTimeInMs);
|
||||
|
||||
curTest = curTest->next;
|
||||
curTest = curTest->m_nextTest;
|
||||
}
|
||||
|
||||
return Finish();
|
||||
}
|
||||
|
||||
TestResults* GetTestResults();
|
||||
|
||||
private:
|
||||
TestReporter* m_reporter;
|
||||
TestResults* m_result;
|
||||
|
|
|
|||
|
|
@ -1,49 +1,111 @@
|
|||
#include "../Config.h"
|
||||
|
||||
#ifdef UNITTEST_USE_EXCEPTIONS
|
||||
|
||||
#include "../unittestpp.h"
|
||||
#include "../AssertException.h"
|
||||
#include "../ReportAssert.h"
|
||||
#include "../AssertException.h"
|
||||
|
||||
#include "RecordingReporter.h"
|
||||
|
||||
using namespace UnitTest;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(CanSetAssertExpected)
|
||||
{
|
||||
ExpectAssert(true);
|
||||
CHECK(AssertExpected());
|
||||
|
||||
ExpectAssert(false);
|
||||
CHECK(!AssertExpected());
|
||||
}
|
||||
|
||||
#ifdef UNITTEST_USE_EXCEPTIONS
|
||||
|
||||
TEST(ReportAssertThrowsAssertException)
|
||||
{
|
||||
bool caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
ReportAssert("", "", 0);
|
||||
TestResults testResults;
|
||||
TestDetails testDetails("", "", "", 0);
|
||||
ReportAssertEx(&testResults, &testDetails, "", "", 0);
|
||||
}
|
||||
catch(AssertException const&)
|
||||
{
|
||||
caught = true;
|
||||
}
|
||||
|
||||
CHECK (true == caught);
|
||||
CHECK(true == caught);
|
||||
}
|
||||
|
||||
TEST(ReportAssertSetsCorrectInfoInException)
|
||||
TEST(ReportAssertClearsExpectAssertFlag)
|
||||
{
|
||||
RecordingReporter reporter;
|
||||
TestResults testResults(&reporter);
|
||||
TestDetails testDetails("", "", "", 0);
|
||||
|
||||
try
|
||||
{
|
||||
ExpectAssert(true);
|
||||
ReportAssertEx(&testResults, &testDetails, "", "", 0);
|
||||
}
|
||||
catch(AssertException const&)
|
||||
{
|
||||
}
|
||||
|
||||
CHECK(AssertExpected() == false);
|
||||
CHECK_EQUAL(0, reporter.testFailedCount);
|
||||
}
|
||||
|
||||
TEST(ReportAssertWritesFailureToResultsAndDetailsWhenAssertIsNotExpected)
|
||||
{
|
||||
const int lineNumber = 12345;
|
||||
const char* description = "description";
|
||||
const char* filename = "filename";
|
||||
|
||||
RecordingReporter reporter;
|
||||
TestResults testResults(&reporter);
|
||||
TestDetails testDetails("", "", "", 0);
|
||||
|
||||
try
|
||||
{
|
||||
ReportAssert(description, filename, lineNumber);
|
||||
ReportAssertEx(&testResults, &testDetails, description, filename, lineNumber);
|
||||
}
|
||||
catch(AssertException const& e)
|
||||
catch(AssertException const&)
|
||||
{
|
||||
CHECK_EQUAL(description, e.what());
|
||||
CHECK_EQUAL(filename, e.Filename());
|
||||
CHECK_EQUAL(lineNumber, e.LineNumber());
|
||||
}
|
||||
|
||||
CHECK_EQUAL(description, reporter.lastFailedMessage);
|
||||
CHECK_EQUAL(filename, reporter.lastFailedFile);
|
||||
CHECK_EQUAL(lineNumber, reporter.lastFailedLine);
|
||||
}
|
||||
|
||||
TEST(ReportAssertReportsNoErrorsWhenAssertIsExpected)
|
||||
{
|
||||
ExpectAssert(true);
|
||||
|
||||
RecordingReporter reporter;
|
||||
TestResults testResults(&reporter);
|
||||
TestDetails testDetails("", "", "", 0);
|
||||
|
||||
try
|
||||
{
|
||||
ReportAssertEx(&testResults, &testDetails, "", "", 0);
|
||||
}
|
||||
catch(AssertException const&)
|
||||
{
|
||||
}
|
||||
|
||||
CHECK_EQUAL(0, reporter.testFailedCount);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(CheckAssertMacroSetsAssertExpectationToFalseAfterRunning)
|
||||
{
|
||||
CHECK_ASSERT(ReportAssert("", "", 0));
|
||||
CHECK(!AssertExpected());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,23 +6,23 @@ using namespace UnitTest;
|
|||
namespace {
|
||||
|
||||
|
||||
TEST (TestListIsEmptyByDefault)
|
||||
TEST(TestListIsEmptyByDefault)
|
||||
{
|
||||
TestList list;
|
||||
CHECK (list.GetHead() == 0);
|
||||
CHECK(list.GetHead() == 0);
|
||||
}
|
||||
|
||||
TEST (AddingTestSetsHeadToTest)
|
||||
TEST(AddingTestSetsHeadToTest)
|
||||
{
|
||||
Test test("test");
|
||||
TestList list;
|
||||
list.Add(&test);
|
||||
|
||||
CHECK (list.GetHead() == &test);
|
||||
CHECK (test.next == 0);
|
||||
CHECK(list.GetHead() == &test);
|
||||
CHECK(test.m_nextTest == 0);
|
||||
}
|
||||
|
||||
TEST (AddingSecondTestAddsItToEndOfList)
|
||||
TEST(AddingSecondTestAddsItToEndOfList)
|
||||
{
|
||||
Test test1("test1");
|
||||
Test test2("test2");
|
||||
|
|
@ -31,20 +31,20 @@ TEST (AddingSecondTestAddsItToEndOfList)
|
|||
list.Add(&test1);
|
||||
list.Add(&test2);
|
||||
|
||||
CHECK (list.GetHead() == &test1);
|
||||
CHECK (test1.next == &test2);
|
||||
CHECK (test2.next == 0);
|
||||
CHECK(list.GetHead() == &test1);
|
||||
CHECK(test1.m_nextTest == &test2);
|
||||
CHECK(test2.m_nextTest == 0);
|
||||
}
|
||||
|
||||
TEST (ListAdderAddsTestToList)
|
||||
TEST(ListAdderAddsTestToList)
|
||||
{
|
||||
TestList list;
|
||||
|
||||
Test test("");
|
||||
ListAdder adder(list, &test);
|
||||
|
||||
CHECK (list.GetHead() == &test);
|
||||
CHECK (test.next == 0);
|
||||
CHECK(list.GetHead() == &test);
|
||||
CHECK(test.m_nextTest == 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ TEST_EX(DummyTest, list1)
|
|||
TEST (TestsAreAddedToTheListThroughMacro)
|
||||
{
|
||||
CHECK(list1.GetHead() != 0);
|
||||
CHECK(list1.GetHead()->next == 0);
|
||||
CHECK(list1.GetHead()->m_nextTest == 0);
|
||||
}
|
||||
|
||||
#ifdef UNITTEST_USE_EXCEPTIONS
|
||||
|
|
|
|||
|
|
@ -10,6 +10,23 @@ using namespace UnitTest;
|
|||
namespace
|
||||
{
|
||||
|
||||
struct TestRunnerFixture
|
||||
{
|
||||
TestRunnerFixture()
|
||||
: runner(reporter)
|
||||
{
|
||||
s_testRunnerFixtureTestResults = runner.GetTestResults();
|
||||
}
|
||||
|
||||
static TestResults* s_testRunnerFixtureTestResults;
|
||||
|
||||
RecordingReporter reporter;
|
||||
TestList list;
|
||||
TestRunner runner;
|
||||
};
|
||||
|
||||
TestResults* TestRunnerFixture::s_testRunnerFixtureTestResults = NULL;
|
||||
|
||||
struct MockTest : public Test
|
||||
{
|
||||
MockTest(char const* testName, bool const success_, bool const assert_, int const count_ = 1)
|
||||
|
|
@ -18,16 +35,19 @@ struct MockTest : public Test
|
|||
, asserted(assert_)
|
||||
, count(count_)
|
||||
{
|
||||
m_isMockTest = true;
|
||||
}
|
||||
|
||||
virtual void RunImpl(TestResults& testResults_) const
|
||||
virtual void RunImpl() const
|
||||
{
|
||||
TestResults* testResults = TestRunnerFixture::s_testRunnerFixtureTestResults;
|
||||
|
||||
for (int i=0; i < count; ++i)
|
||||
{
|
||||
if (asserted)
|
||||
ReportAssert("desc", "file", 0);
|
||||
ReportAssertEx(testResults, &m_details, "desc", "file", 0);
|
||||
else if (!success)
|
||||
testResults_.OnTestFailure(m_details, "message");
|
||||
testResults->OnTestFailure(m_details, "message");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,19 +56,6 @@ struct MockTest : public Test
|
|||
int const count;
|
||||
};
|
||||
|
||||
|
||||
struct TestRunnerFixture
|
||||
{
|
||||
TestRunnerFixture()
|
||||
: runner(reporter)
|
||||
{
|
||||
}
|
||||
|
||||
RecordingReporter reporter;
|
||||
TestList list;
|
||||
TestRunner runner;
|
||||
};
|
||||
|
||||
TEST_FIXTURE(TestRunnerFixture, TestStartIsReportedCorrectly)
|
||||
{
|
||||
MockTest test("goodtest", true, false);
|
||||
|
|
@ -104,7 +111,7 @@ TEST_FIXTURE(TestRunnerFixture, CallsReportFailureOncePerFailingTest)
|
|||
MockTest test3("test", false, false);
|
||||
list.Add(&test3);
|
||||
|
||||
CHECK_EQUAL(2, runner.RunTestsIf(list, NULL, True(), 0));
|
||||
CHECK_EQUAL(2, runner.RunTestsIf(list, NULL, True(), 0));
|
||||
CHECK_EQUAL(2, reporter.testFailedCount);
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +124,6 @@ TEST_FIXTURE(TestRunnerFixture, TestsThatAssertAreReportedAsFailing)
|
|||
CHECK_EQUAL(1, reporter.testFailedCount);
|
||||
}
|
||||
|
||||
|
||||
TEST_FIXTURE(TestRunnerFixture, ReporterNotifiedOfTestCount)
|
||||
{
|
||||
MockTest test1("test", true, false);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue