mirror of
https://github.com/unittest-cpp/unittest-cpp
synced 2026-09-26 16:19:30 +03:00
This commit addresses two issues:
(1) unreachable code in for loop shenanigans is eliminated.
(2) code after a failing REQUIRE check no longer executes. Used a
decorating TestReporter to achive this.
This commit is contained in:
parent
06308ee802
commit
a9161c1ba6
8 changed files with 201 additions and 10 deletions
|
|
@ -41,6 +41,10 @@
|
|||
if (!UnitTest::Check(value)) \
|
||||
UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), #value); \
|
||||
}) \
|
||||
UT_CATCH (UnitTest::AssertException, e, \
|
||||
{ \
|
||||
UT_THROW(); \
|
||||
}) \
|
||||
UT_CATCH (std::exception, e, \
|
||||
{ \
|
||||
UnitTest::MemoryOutStream message; \
|
||||
|
|
@ -60,7 +64,11 @@
|
|||
UT_TRY \
|
||||
({ \
|
||||
UnitTest::CheckEqual(*UnitTest::CurrentTest::Results(), expected, actual, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
|
||||
}) \
|
||||
}) \
|
||||
UT_CATCH (UnitTest::AssertException, e, \
|
||||
{ \
|
||||
UT_THROW(); \
|
||||
}) \
|
||||
UT_CATCH (std::exception, e, \
|
||||
{ \
|
||||
UnitTest::MemoryOutStream message; \
|
||||
|
|
@ -81,6 +89,10 @@
|
|||
({ \
|
||||
UnitTest::CheckClose(*UnitTest::CurrentTest::Results(), expected, actual, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
|
||||
}) \
|
||||
UT_CATCH (UnitTest::AssertException, e, \
|
||||
{ \
|
||||
UT_THROW(); \
|
||||
}) \
|
||||
UT_CATCH (std::exception, e, \
|
||||
{ \
|
||||
UnitTest::MemoryOutStream message; \
|
||||
|
|
@ -100,7 +112,11 @@
|
|||
UT_TRY \
|
||||
({ \
|
||||
UnitTest::CheckArrayEqual(*UnitTest::CurrentTest::Results(), expected, actual, count, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
|
||||
}) \
|
||||
}) \
|
||||
UT_CATCH (UnitTest::AssertException, e, \
|
||||
{ \
|
||||
UT_THROW(); \
|
||||
}) \
|
||||
UT_CATCH (std::exception, e, \
|
||||
{ \
|
||||
UnitTest::MemoryOutStream message; \
|
||||
|
|
@ -121,6 +137,10 @@
|
|||
({ \
|
||||
UnitTest::CheckArrayClose(*UnitTest::CurrentTest::Results(), expected, actual, count, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
|
||||
}) \
|
||||
UT_CATCH (UnitTest::AssertException, e, \
|
||||
{ \
|
||||
UT_THROW(); \
|
||||
}) \
|
||||
UT_CATCH (std::exception, e, \
|
||||
{ \
|
||||
UnitTest::MemoryOutStream message; \
|
||||
|
|
@ -140,7 +160,11 @@
|
|||
UT_TRY \
|
||||
({ \
|
||||
UnitTest::CheckArray2DClose(*UnitTest::CurrentTest::Results(), expected, actual, rows, columns, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
|
||||
}) \
|
||||
}) \
|
||||
UT_CATCH (UnitTest::AssertException, e, \
|
||||
{ \
|
||||
UT_THROW(); \
|
||||
}) \
|
||||
UT_CATCH (std::exception, e, \
|
||||
{ \
|
||||
UnitTest::MemoryOutStream message; \
|
||||
|
|
|
|||
|
|
@ -1,19 +1,14 @@
|
|||
#ifndef UNITTEST_REQUIREMACROS_H
|
||||
#define UNITTEST_REQUIREMACROS_H
|
||||
|
||||
#include "HelperMacros.h"
|
||||
#include "ExceptionMacros.h"
|
||||
#include "CurrentTest.h"
|
||||
#include "RequiredCheckTestReporter.h"
|
||||
|
||||
#ifdef REQUIRE
|
||||
#error UnitTest++ redefines REQUIRE
|
||||
#endif
|
||||
|
||||
#ifndef UNITTEST_NO_EXCEPTIONS
|
||||
#define REQUIRE \
|
||||
for (int failuresBeforeTest = UnitTest::CurrentTest::Results()->GetFailureCount(), newFailures = 0, run = 0; \
|
||||
(run == 0) || ((newFailures != 0) && (throw UnitTest::AssertException(), true)); \
|
||||
newFailures = UnitTest::CurrentTest::Results()->GetFailureCount() - failuresBeforeTest, run = 1)
|
||||
#define REQUIRE for(UnitTest::RequiredCheckTestReporter decoratedReporter(UnitTest::CurrentTest::Results()); decoratedReporter.next(); )
|
||||
#endif
|
||||
|
||||
#ifdef UNITTEST_NO_EXCEPTIONS
|
||||
|
|
|
|||
29
UnitTest++/RequiredCheckTestReporter.cpp
Normal file
29
UnitTest++/RequiredCheckTestReporter.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include "RequiredCheckTestReporter.h"
|
||||
|
||||
#include "CurrentTest.h"
|
||||
#include "TestResults.h"
|
||||
|
||||
namespace UnitTest {
|
||||
|
||||
RequiredCheckTestReporter::RequiredCheckTestReporter(TestResults* results)
|
||||
: m_results(results)
|
||||
, m_throwingReporter(0)
|
||||
, m_continue(0)
|
||||
{
|
||||
if(m_results)
|
||||
{
|
||||
m_throwingReporter.setDecorated(m_results->m_testReporter);
|
||||
m_results->m_testReporter = &m_throwingReporter;
|
||||
}
|
||||
}
|
||||
|
||||
RequiredCheckTestReporter::~RequiredCheckTestReporter()
|
||||
{
|
||||
if(m_results) m_results->m_testReporter = m_throwingReporter.getDecorated();
|
||||
}
|
||||
|
||||
bool RequiredCheckTestReporter::next()
|
||||
{
|
||||
return m_continue++ == 0;
|
||||
}
|
||||
}
|
||||
29
UnitTest++/RequiredCheckTestReporter.h
Normal file
29
UnitTest++/RequiredCheckTestReporter.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef UNITTEST_REQUIRED_CHECK_TEST_REPORTER_H
|
||||
#define UNITTEST_REQUIRED_CHECK_TEST_REPORTER_H
|
||||
|
||||
#include "HelperMacros.h"
|
||||
#include "ThrowingTestReporter.h"
|
||||
|
||||
namespace UnitTest {
|
||||
|
||||
class TestResults;
|
||||
|
||||
// This RAII class decorates the current TestReporter with
|
||||
// a version that throws after reporting a failure.
|
||||
class UNITTEST_LINKAGE RequiredCheckTestReporter
|
||||
{
|
||||
public:
|
||||
explicit RequiredCheckTestReporter(TestResults* results);
|
||||
~RequiredCheckTestReporter();
|
||||
|
||||
bool next();
|
||||
|
||||
private:
|
||||
TestResults* m_results;
|
||||
ThrowingTestReporter m_throwingReporter;
|
||||
int m_continue;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
namespace UnitTest {
|
||||
|
||||
class RequiredCheckTestReporter;
|
||||
class TestReporter;
|
||||
class TestDetails;
|
||||
|
||||
|
|
@ -22,6 +23,9 @@ namespace UnitTest {
|
|||
int GetFailureCount() const;
|
||||
|
||||
private:
|
||||
friend class RequiredCheckTestReporter;
|
||||
|
||||
private:
|
||||
TestReporter* m_testReporter;
|
||||
int m_totalTestCount;
|
||||
int m_failedTestCount;
|
||||
|
|
|
|||
51
UnitTest++/ThrowingTestReporter.cpp
Normal file
51
UnitTest++/ThrowingTestReporter.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include "ThrowingTestReporter.h"
|
||||
#include "AssertException.h"
|
||||
|
||||
namespace UnitTest {
|
||||
|
||||
ThrowingTestReporter::ThrowingTestReporter(TestReporter* decoratedReporter)
|
||||
: m_decoratedReporter(decoratedReporter)
|
||||
{
|
||||
}
|
||||
|
||||
//virtual
|
||||
ThrowingTestReporter::~ThrowingTestReporter()
|
||||
{
|
||||
}
|
||||
|
||||
//virtual
|
||||
void ThrowingTestReporter::ReportTestStart(TestDetails const& test)
|
||||
{
|
||||
if(m_decoratedReporter) m_decoratedReporter->ReportTestStart(test);
|
||||
}
|
||||
|
||||
//virtual
|
||||
void ThrowingTestReporter::ReportFailure(TestDetails const& test, char const* failure)
|
||||
{
|
||||
if(m_decoratedReporter) m_decoratedReporter->ReportFailure(test, failure);
|
||||
throw AssertException();
|
||||
}
|
||||
|
||||
//virtual
|
||||
void ThrowingTestReporter::ReportTestFinish(TestDetails const& test, float secondsElapsed)
|
||||
{
|
||||
if(m_decoratedReporter) m_decoratedReporter->ReportTestFinish(test, secondsElapsed);
|
||||
}
|
||||
|
||||
//virtual
|
||||
void ThrowingTestReporter::ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed)
|
||||
{
|
||||
if(m_decoratedReporter) m_decoratedReporter->ReportSummary(totalTestCount, failedTestCount, failureCount, secondsElapsed);
|
||||
}
|
||||
|
||||
TestReporter* ThrowingTestReporter::getDecorated() const
|
||||
{
|
||||
return m_decoratedReporter;
|
||||
}
|
||||
|
||||
void ThrowingTestReporter::setDecorated(TestReporter* reporter)
|
||||
{
|
||||
m_decoratedReporter = reporter;
|
||||
}
|
||||
|
||||
}
|
||||
29
UnitTest++/ThrowingTestReporter.h
Normal file
29
UnitTest++/ThrowingTestReporter.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef UNITTEST_THROWINGTESTREPORTER_H
|
||||
#define UNITTEST_THROWINGTESTREPORTER_H
|
||||
|
||||
#include "TestReporter.h"
|
||||
|
||||
namespace UnitTest {
|
||||
|
||||
// A TestReporter that throws when ReportFailure is called. Otherwise it
|
||||
// forwards the calls to a decorated TestReporter
|
||||
class ThrowingTestReporter : public TestReporter
|
||||
{
|
||||
public:
|
||||
explicit ThrowingTestReporter(TestReporter* reporter);
|
||||
|
||||
virtual ~ThrowingTestReporter();
|
||||
virtual void ReportTestStart(TestDetails const& test);
|
||||
virtual void ReportFailure(TestDetails const& test, char const* failure);
|
||||
virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed);
|
||||
virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed);
|
||||
|
||||
TestReporter* getDecorated() const;
|
||||
void setDecorated(TestReporter* reporter);
|
||||
|
||||
private:
|
||||
TestReporter* m_decoratedReporter;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -117,7 +117,37 @@ TEST(RequireMacroSupportsMultipleChecksWithFailingChecks)
|
|||
CHECK(failure);
|
||||
CHECK(exception);
|
||||
}
|
||||
|
||||
TEST(RequireMacroDoesntExecuteCodeAfterAFailingCheck)
|
||||
{
|
||||
bool failure = false;
|
||||
bool exception = false;
|
||||
bool run = false;
|
||||
{
|
||||
RecordingReporter reporter;
|
||||
UnitTest::TestResults testResults(&reporter);
|
||||
ScopedCurrentTest scopedResults(testResults);
|
||||
|
||||
try{
|
||||
REQUIRE
|
||||
{
|
||||
CHECK(false);
|
||||
run = true; // this shouldn't get executed.
|
||||
}
|
||||
}
|
||||
catch (const UnitTest::AssertException&)
|
||||
{
|
||||
exception = true;
|
||||
}
|
||||
|
||||
failure = (testResults.GetFailureCount() > 0);
|
||||
}
|
||||
|
||||
CHECK(failure);
|
||||
CHECK(exception);
|
||||
CHECK(!run);
|
||||
}
|
||||
|
||||
TEST(FailureReportsCorrectTestName)
|
||||
{
|
||||
RecordingReporter reporter;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue