Skip to content

Commit

Permalink
Add option to warn when no tests ran
Browse files Browse the repository at this point in the history
  • Loading branch information
dvirtz authored and horenmar committed Feb 9, 2018
1 parent 7cbd0b5 commit 355b3f9
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,11 @@ if (BUILD_TESTING AND NOT_SUBPROJECT)
add_test(NAME ListTestNamesOnly COMMAND $<TARGET_FILE:SelfTest> --list-test-names-only)
set_tests_properties(ListTestNamesOnly PROPERTIES PASS_REGULAR_EXPRESSION "Regex string matcher")

add_test(NAME NoAssertions COMMAND $<TARGET_FILE:SelfTest> -w NoAssertions)
set_tests_properties(NoAssertions PROPERTIES PASS_REGULAR_EXPRESSION "No assertions in test case")

add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> -w NoTests "___nonexistent_test___")
set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched")

# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
Expand Down
11 changes: 9 additions & 2 deletions docs/command-line.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,16 @@ This option transforms tabs and newline characters into ```\t``` and ```\n``` re
## Warnings
<pre>-w, --warn &lt;warning name></pre>

Enables reporting of warnings (only one, at time of this writing). If a warning is issued it fails the test.
Enables reporting of suspicious test states. There are currently two
available warnings

```
NoAssertions // Fail test case / leaf section if no assertions
// (e.g. `REQUIRE`) is encountered.
NoTests // Return non-zero exit code when no test cases were run
// Also calls reporter's noMatchingTestCases method
```

The ony available warning, presently, is ```NoAssertions```. This warning fails a test case, or (leaf) section if no assertions (```REQUIRE```/ ```CHECK``` etc) are encountered.

<a id="reporting-timings"></a>
## Reporting timings
Expand Down
14 changes: 12 additions & 2 deletions include/internal/catch_commandline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,19 @@ namespace Catch {
using namespace clara;

auto const setWarning = [&]( std::string const& warning ) {
if( warning != "NoAssertions" )
auto warningSet = [&]() {
if( warning == "NoAssertions" )
return WarnAbout::NoAssertions;

if ( warning == "NoTests" )
return WarnAbout::NoTests;

return WarnAbout::Nothing;
}();

if (warningSet == WarnAbout::Nothing)
return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );
return ParserResult::ok( ParseResultType::Matched );
};
auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
Expand Down
4 changes: 3 additions & 1 deletion include/internal/catch_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace Catch {
std::string Config::getProcessName() const { return m_data.processName; }

std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; }
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }

TestSpec const& Config::testSpec() const { return m_testSpec; }
Expand All @@ -46,7 +47,8 @@ namespace Catch {
std::ostream& Config::stream() const { return m_stream->stream(); }
std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
bool Config::warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); }
bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); }
ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
unsigned int Config::rngSeed() const { return m_data.rngSeed; }
Expand Down
2 changes: 2 additions & 0 deletions include/internal/catch_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ namespace Catch {
std::string getProcessName() const;

std::vector<std::string> const& getReporterNames() const;
std::vector<std::string> const& getTestsOrTags() const;
std::vector<std::string> const& getSectionsToRun() const override;

virtual TestSpec const& testSpec() const override;
Expand All @@ -90,6 +91,7 @@ namespace Catch {
std::string name() const override;
bool includeSuccessfulResults() const override;
bool warnAboutMissingAssertions() const override;
bool warnAboutNoTests() const override;
ShowDurations::OrNot showDurations() const override;
RunTests::InWhatOrder runOrder() const override;
unsigned int rngSeed() const override;
Expand Down
4 changes: 3 additions & 1 deletion include/internal/catch_interfaces_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ namespace Catch {

struct WarnAbout { enum What {
Nothing = 0x00,
NoAssertions = 0x01
NoAssertions = 0x01,
NoTests = 0x02
}; };

struct ShowDurations { enum OrNot {
Expand Down Expand Up @@ -62,6 +63,7 @@ namespace Catch {
virtual bool includeSuccessfulResults() const = 0;
virtual bool shouldDebugBreak() const = 0;
virtual bool warnAboutMissingAssertions() const = 0;
virtual bool warnAboutNoTests() const = 0;
virtual int abortAfter() const = 0;
virtual bool showInvisibles() const = 0;
virtual ShowDurations::OrNot showDurations() const = 0;
Expand Down
18 changes: 17 additions & 1 deletion include/internal/catch_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "catch_random_number_generator.h"
#include "catch_startup_exception_registry.h"
#include "catch_text.h"
#include "catch_stream.h"

#include <cstdlib>
#include <iomanip>
Expand Down Expand Up @@ -80,6 +81,20 @@ namespace Catch {
context.reporter().skipTest(testCase);
}

if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
ReusableStringStream testConfig;

bool first = true;
for (const auto& input : config->getTestsOrTags()) {
if (!first) { testConfig << ' '; }
first = false;
testConfig << input;
}

context.reporter().noMatchingTestCases(testConfig.str());
totals.error = -1;
}

context.testGroupEnded(config->name(), totals, 1, 1);
return totals;
}
Expand Down Expand Up @@ -259,10 +274,11 @@ namespace Catch {
if( Option<std::size_t> listed = list( config() ) )
return static_cast<int>( *listed );

auto totals = runTests( m_config );
// Note that on unices only the lower 8 bits are usually used, clamping
// the return value to 255 prevents false negative when some multiple
// of 256 tests has failed
return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
return (std::min)( { MaxExitCode, totals.error, static_cast<int>( totals.assertions.failed ) } );
}
catch( std::exception& ex ) {
Catch::cerr() << ex.what() << std::endl;
Expand Down
2 changes: 1 addition & 1 deletion include/internal/catch_totals.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace Catch {

Totals delta( Totals const& prevTotals ) const;


int error = 0;
Counts assertions;
Counts testCases;
};
Expand Down

0 comments on commit 355b3f9

Please sign in to comment.