Completed NoAssertions warning implementation

This commit is contained in:
Phil Nash 2012-08-31 08:10:36 +01:00
parent 55764c8d47
commit a70fbe3c1a
12 changed files with 668 additions and 513 deletions

View File

@ -113,6 +113,7 @@
#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" ) #define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" ) #define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" ) #define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
#define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, false, "SUCCEED" )
#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg ) #define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" ) #define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" )

View File

@ -149,6 +149,9 @@ namespace Catch {
return m_data.allowThrows; return m_data.allowThrows;
} }
const ConfigData& data() const {
return m_data;
}
ConfigData& data() { ConfigData& data() {
return m_data; return m_data;
} }

View File

@ -48,6 +48,8 @@ namespace Catch
virtual void StartGroup( const std::string& groupName ) = 0; virtual void StartGroup( const std::string& groupName ) = 0;
virtual void EndGroup( const std::string& groupName, const Totals& totals ) = 0; virtual void EndGroup( const std::string& groupName, const Totals& totals ) = 0;
virtual void StartSection( const std::string& sectionName, const std::string& description ) = 0; virtual void StartSection( const std::string& sectionName, const std::string& description ) = 0;
virtual void NoAssertionsInSection( const std::string& sectionName ) = 0;
virtual void NoAssertionsInTestCase( const std::string& testName ) = 0;
virtual void EndSection( const std::string& sectionName, const Counts& assertions ) = 0; virtual void EndSection( const std::string& sectionName, const Counts& assertions ) = 0;
virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0; virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0;
virtual void Aborted() = 0; virtual void Aborted() = 0;

View File

@ -190,8 +190,16 @@ namespace Catch {
} }
virtual void sectionEnded( const std::string& name, const Counts& prevAssertions ) { virtual void sectionEnded( const std::string& name, const Counts& prevAssertions ) {
Counts assertions = m_totals.assertions - prevAssertions;
if( assertions.total() == 0 &&
( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
!m_runningTest->isBranchSection() ) {
m_reporter->NoAssertionsInSection( name );
m_totals.assertions.failed++;
assertions.failed++;
}
m_runningTest->endSection( name ); m_runningTest->endSection( name );
m_reporter->EndSection( name, m_totals.assertions - prevAssertions ); m_reporter->EndSection( name, assertions );
} }
virtual void pushScopedInfo( ScopedInfo* scopedInfo ) { virtual void pushScopedInfo( ScopedInfo* scopedInfo ) {
@ -246,6 +254,7 @@ namespace Catch {
void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
try { try {
m_runningTest->reset(); m_runningTest->reset();
Counts prevAssertions = m_totals.assertions;
if( m_reporter->shouldRedirectStdout() ) { if( m_reporter->shouldRedirectStdout() ) {
StreamRedirect coutRedir( std::cout, redirectedCout ); StreamRedirect coutRedir( std::cout, redirectedCout );
StreamRedirect cerrRedir( std::cerr, redirectedCerr ); StreamRedirect cerrRedir( std::cerr, redirectedCerr );
@ -254,6 +263,13 @@ namespace Catch {
else { else {
m_runningTest->getTestCaseInfo().invoke(); m_runningTest->getTestCaseInfo().invoke();
} }
Counts assertions = m_totals.assertions - prevAssertions;
if( assertions.total() == 0 &&
( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
!m_runningTest->hasSections() ) {
m_totals.assertions.failed++;
m_reporter->NoAssertionsInTestCase( m_runningTest->getTestCaseInfo().getName() );
}
m_runningTest->ranToCompletion(); m_runningTest->ranToCompletion();
} }
catch( TestFailureException& ) { catch( TestFailureException& ) {

View File

@ -36,6 +36,17 @@ namespace Catch {
m_runStatus == RanToCompletionWithSections; m_runStatus == RanToCompletionWithSections;
} }
bool isBranchSection() const {
return m_currentSection &&
m_currentSection->isBranch();
}
bool hasSections() const {
return m_runStatus == RanAtLeastOneSection ||
m_runStatus == RanToCompletionWithSections ||
m_runStatus == EncounteredASection;
}
void reset() { void reset() {
m_runStatus = NothingRun; m_runStatus = NothingRun;
m_changed = false; m_changed = false;

View File

@ -52,6 +52,10 @@ namespace Catch {
return false; return false;
} }
bool isBranch() const {
return m_status == Branch;
}
void ranToCompletion() { void ranToCompletion() {
if( m_status == Branch && !hasUntestedSections() ) if( m_status == Branch && !hasUntestedSections() )
m_status = TestedBranch; m_status = TestedBranch;

View File

@ -128,11 +128,18 @@ namespace Catch {
m_sectionSpans.push_back( SpanInfo( sectionName ) ); m_sectionSpans.push_back( SpanInfo( sectionName ) );
} }
virtual void EndSection( const std::string& sectionName, const Counts& assertions ) { virtual void NoAssertionsInSection( const std::string& sectionName ) {
if( ( m_config.fullConfig.warnings & ConfigData::WarnAbout::NoAssertions ) && assertions.total() == 0 ) {
StartSpansLazily(); StartSpansLazily();
m_config.stream << "** No assertions in section **" << std::endl; TextColour colour( TextColour::ResultError );
m_config.stream << "\nNo assertions in section, '" << sectionName << "'\n" << std::endl;
} }
virtual void NoAssertionsInTestCase( const std::string& testName ) {
StartSpansLazily();
TextColour colour( TextColour::ResultError );
m_config.stream << "\nNo assertions in test case, '" << testName << "'\n" << std::endl;
}
virtual void EndSection( const std::string& sectionName, const Counts& assertions ) {
SpanInfo& sectionSpan = m_sectionSpans.back(); SpanInfo& sectionSpan = m_sectionSpans.back();
if( sectionSpan.emitted && !sectionSpan.name.empty() ) { if( sectionSpan.emitted && !sectionSpan.name.empty() ) {

View File

@ -88,7 +88,10 @@ namespace Catch {
virtual void StartSection( const std::string&, const std::string& ){} virtual void StartSection( const std::string&, const std::string& ){}
virtual void EndSection( const std::string&, const Counts& ){} virtual void NoAssertionsInSection( const std::string& ) {}
virtual void NoAssertionsInTestCase( const std::string& ) {}
virtual void EndSection( const std::string&, const Counts& ) {}
virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) ); m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) );

View File

@ -60,6 +60,8 @@ namespace Catch {
.writeAttribute( "name", sectionName ) .writeAttribute( "name", sectionName )
.writeAttribute( "description", description ); .writeAttribute( "description", description );
} }
virtual void NoAssertionsInSection( const std::string& ) {}
virtual void NoAssertionsInTestCase( const std::string& ) {}
virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
m_xml.scopedElement( "OverallResults" ) m_xml.scopedElement( "OverallResults" )

View File

@ -289,3 +289,7 @@ TEST_CASE( "example/factorial", "The Factorial function should return the factor
REQUIRE( Factorial(3) == 6 ); REQUIRE( Factorial(3) == 6 );
REQUIRE( Factorial(10) == 3628800 ); REQUIRE( Factorial(10) == 3628800 );
} }
TEST_CASE( "empty", "An empty test with no assertions" )
{
}

View File

@ -75,6 +75,9 @@ namespace Catch {
openLabel( recordSections, sectionName ); openLabel( recordSections, sectionName );
} }
virtual void NoAssertionsInSection( const std::string& ) {}
virtual void NoAssertionsInTestCase( const std::string& ) {}
virtual void EndSection( const std::string& sectionName, const Counts& ) { virtual void EndSection( const std::string& sectionName, const Counts& ) {
closeLabel( recordSections, sectionName ); closeLabel( recordSections, sectionName );
} }
@ -162,6 +165,9 @@ namespace Catch {
<< "' to succeed but there was/ were " << "' to succeed but there was/ were "
<< totals.assertions.failed << " failure(s)" ); << totals.assertions.failed << " failure(s)" );
} }
else {
SUCCEED( "Tests passed, as expected" );
}
break; break;
case Expected::ToFail: case Expected::ToFail:
if( totals.assertions.passed > 0 ) { if( totals.assertions.passed > 0 ) {
@ -171,6 +177,9 @@ namespace Catch {
<< "' to fail but there was/ were " << "' to fail but there was/ were "
<< totals.assertions.passed << " success(es)" ); << totals.assertions.passed << " success(es)" );
} }
else {
SUCCEED( "Tests failed, as expected" );
}
break; break;
} }
}; };

File diff suppressed because it is too large Load Diff