This commit is contained in:
Martin Hořeňovský 2020-07-12 20:28:38 +02:00
parent 4c85248179
commit 7f21cc6c55
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
9 changed files with 94 additions and 39 deletions

View File

@ -14,7 +14,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif() endif()
project(Catch2 LANGUAGES CXX VERSION 2.12.4) project(Catch2 LANGUAGES CXX VERSION 2.13.0)
# Provide path for scripts # Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")

View File

@ -5,11 +5,11 @@
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2) [![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2) [![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
[![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2) [![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/wRuqI3INY7fTagL7) [![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/aavJBzemrxUgGV9S)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD) [![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.12.4/catch.hpp">The latest version of the single header can be downloaded directly using this link</a> <a href="https://github.com/catchorg/Catch2/releases/download/v2.13.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released! ## Catch2 is released!

View File

@ -224,7 +224,7 @@ When set to ```yes``` Catch will report the duration of each test case, in milli
<pre>-D, --min-duration &lt;value></pre> <pre>-D, --min-duration &lt;value></pre>
> `--min-duration` was [introduced](https://github.com/catchorg/Catch2/pull/1910) in Catch X.Y.Z > `--min-duration` was [introduced](https://github.com/catchorg/Catch2/pull/1910) in Catch 2.13.0
When set, Catch will report the duration of each test case that took more When set, Catch will report the duration of each test case that took more
than &lt;value> seconds, in milliseconds. This option is overriden by both than &lt;value> seconds, in milliseconds. This option is overriden by both

View File

@ -92,7 +92,7 @@ TEST_CASE("Complex mix of sections and generates") {
} }
``` ```
> The ability to place `GENERATE` between two `SECTION`s was [introduced](https://github.com/catchorg/Catch2/issues/1938) in Catch X.Y.Z. > The ability to place `GENERATE` between two `SECTION`s was [introduced](https://github.com/catchorg/Catch2/issues/1938) in Catch 2.13.0.
## Provided generators ## Provided generators

View File

@ -2,6 +2,7 @@
# Release notes # Release notes
**Contents**<br> **Contents**<br>
[2.13.0](#2130)<br>
[2.12.4](#2124)<br> [2.12.4](#2124)<br>
[2.12.3](#2123)<br> [2.12.3](#2123)<br>
[2.12.2](#2122)<br> [2.12.2](#2122)<br>
@ -39,6 +40,18 @@
[Older versions](#older-versions)<br> [Older versions](#older-versions)<br>
[Even Older versions](#even-older-versions)<br> [Even Older versions](#even-older-versions)<br>
## 2.13.0
### Improvements
* `GENERATE` can now follow a `SECTION` at the same level of nesting (#1938)
* The `SECTION`(s) before the `GENERATE` will not be run multiple times, the following ones will.
* Added `-D`/`--min-duration` command line flag (#1910)
* If a test takes longer to finish than the provided value, its name and duration will be printed.
* This flag is overriden by setting `-d`/`--duration`.
### Fixes
* `TAPReporter` no longer skips successful assertions (#1983)
## 2.12.4 ## 2.12.4

View File

@ -10,8 +10,8 @@
#define TWOBLUECUBES_CATCH_HPP_INCLUDED #define TWOBLUECUBES_CATCH_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 12 #define CATCH_VERSION_MINOR 13
#define CATCH_VERSION_PATCH 4 #define CATCH_VERSION_PATCH 0
#ifdef __clang__ #ifdef __clang__
# pragma clang system_header # pragma clang system_header

View File

@ -37,7 +37,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 2, 12, 4, "", 0 ); static Version version( 2, 13, 0, "", 0 );
return version; return version;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Catch v2.12.4 * Catch v2.13.0
* Generated: 2020-07-05 11:47:18.451282 * Generated: 2020-07-12 20:07:49.015950
* ---------------------------------------------------------- * ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly * This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved.
@ -14,8 +14,8 @@
#define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 12 #define CATCH_VERSION_MINOR 13
#define CATCH_VERSION_PATCH 4 #define CATCH_VERSION_PATCH 0
#ifdef __clang__ #ifdef __clang__
# pragma clang system_header # pragma clang system_header
@ -4522,6 +4522,7 @@ namespace Catch {
virtual int abortAfter() const = 0; virtual int abortAfter() const = 0;
virtual bool showInvisibles() const = 0; virtual bool showInvisibles() const = 0;
virtual ShowDurations::OrNot showDurations() const = 0; virtual ShowDurations::OrNot showDurations() const = 0;
virtual double minDuration() const = 0;
virtual TestSpec const& testSpec() const = 0; virtual TestSpec const& testSpec() const = 0;
virtual bool hasTestFilters() const = 0; virtual bool hasTestFilters() const = 0;
virtual std::vector<std::string> const& getTestsOrTags() const = 0; virtual std::vector<std::string> const& getTestsOrTags() const = 0;
@ -5294,6 +5295,7 @@ namespace Catch {
Verbosity verbosity = Verbosity::Normal; Verbosity verbosity = Verbosity::Normal;
WarnAbout::What warnings = WarnAbout::Nothing; WarnAbout::What warnings = WarnAbout::Nothing;
ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
double minDuration = -1;
RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
UseColour::YesOrNo useColour = UseColour::Auto; UseColour::YesOrNo useColour = UseColour::Auto;
WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
@ -5344,6 +5346,7 @@ namespace Catch {
bool warnAboutMissingAssertions() const override; bool warnAboutMissingAssertions() const override;
bool warnAboutNoTests() const override; bool warnAboutNoTests() const override;
ShowDurations::OrNot showDurations() const override; ShowDurations::OrNot showDurations() const override;
double minDuration() const override;
RunTests::InWhatOrder runOrder() const override; RunTests::InWhatOrder runOrder() const override;
unsigned int rngSeed() const override; unsigned int rngSeed() const override;
UseColour::YesOrNo useColour() const override; UseColour::YesOrNo useColour() const override;
@ -5721,6 +5724,9 @@ namespace Catch {
// Returns double formatted as %.3f (format expected on output) // Returns double formatted as %.3f (format expected on output)
std::string getFormattedDuration( double duration ); std::string getFormattedDuration( double duration );
//! Should the reporter show
bool shouldShowDuration( IConfig const& config, double duration );
std::string serializeFilters( std::vector<std::string> const& container ); std::string serializeFilters( std::vector<std::string> const& container );
template<typename DerivedT> template<typename DerivedT>
@ -6114,8 +6120,6 @@ namespace Catch {
static std::string getDescription(); static std::string getDescription();
ReporterPreferences getPreferences() const override;
void noMatchingTestCases(std::string const& spec) override; void noMatchingTestCases(std::string const& spec) override;
void assertionStarting(AssertionInfo const&) override; void assertionStarting(AssertionInfo const&) override;
@ -7499,6 +7503,7 @@ namespace TestCaseTracking {
virtual bool isSuccessfullyCompleted() const = 0; virtual bool isSuccessfullyCompleted() const = 0;
virtual bool isOpen() const = 0; // Started but not complete virtual bool isOpen() const = 0; // Started but not complete
virtual bool hasChildren() const = 0; virtual bool hasChildren() const = 0;
virtual bool hasStarted() const = 0;
virtual ITracker& parent() = 0; virtual ITracker& parent() = 0;
@ -7565,6 +7570,9 @@ namespace TestCaseTracking {
bool isSuccessfullyCompleted() const override; bool isSuccessfullyCompleted() const override;
bool isOpen() const override; bool isOpen() const override;
bool hasChildren() const override; bool hasChildren() const override;
bool hasStarted() const override {
return m_runState != NotStarted;
}
void addChild( ITrackerPtr const& child ) override; void addChild( ITrackerPtr const& child ) override;
@ -9861,6 +9869,9 @@ namespace Catch {
| Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
["-d"]["--durations"] ["-d"]["--durations"]
( "show test durations" ) ( "show test durations" )
| Opt( config.minDuration, "seconds" )
["-D"]["--min-duration"]
( "show test durations for tests taking at least the given number of seconds" )
| Opt( loadTestNamesFromFile, "filename" ) | Opt( loadTestNamesFromFile, "filename" )
["-f"]["--input-file"] ["-f"]["--input-file"]
( "load test names to run from a file" ) ( "load test names to run from a file" )
@ -10008,6 +10019,7 @@ namespace Catch {
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); } bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); }
ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
double Config::minDuration() const { return m_data.minDuration; }
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
unsigned int Config::rngSeed() const { return m_data.rngSeed; } unsigned int Config::rngSeed() const { return m_data.rngSeed; }
UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } UseColour::YesOrNo Config::useColour() const { return m_data.useColour; }
@ -12547,7 +12559,7 @@ namespace Catch {
currentTracker.addChild( tracker ); currentTracker.addChild( tracker );
} }
if( !ctx.completedCycle() && !tracker->isComplete() ) { if( !tracker->isComplete() ) {
tracker->open(); tracker->open();
} }
@ -12561,8 +12573,28 @@ namespace Catch {
} }
void close() override { void close() override {
TrackerBase::close(); TrackerBase::close();
// Generator interface only finds out if it has another item on atual move // If a generator has a child (it is followed by a section)
if (m_runState == CompletedSuccessfully && m_generator->next()) { // and none of its children have started, then we must wait
// until later to start consuming its values.
// This catches cases where `GENERATE` is placed between two
// `SECTION`s.
// **The check for m_children.empty cannot be removed**.
// doing so would break `GENERATE` _not_ followed by `SECTION`s.
const bool should_wait_for_child =
!m_children.empty() &&
std::find_if( m_children.begin(),
m_children.end(),
[]( TestCaseTracking::ITrackerPtr tracker ) {
return tracker->hasStarted();
} ) == m_children.end();
// This check is a bit tricky, because m_generator->next()
// has a side-effect, where it consumes generator's current
// value, but we do not want to invoke the side-effect if
// this generator is still waiting for any child to start.
if ( should_wait_for_child ||
( m_runState == CompletedSuccessfully &&
m_generator->next() ) ) {
m_children.clear(); m_children.clear();
m_runState = Executing; m_runState = Executing;
} }
@ -12702,7 +12734,6 @@ namespace Catch {
using namespace Generators; using namespace Generators;
GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext, GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext,
TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) ); TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) );
assert( tracker.isOpen() );
m_lastAssertionInfo.lineInfo = lineInfo; m_lastAssertionInfo.lineInfo = lineInfo;
return tracker; return tracker;
} }
@ -14381,7 +14412,8 @@ namespace TestCaseTracking {
bool SectionTracker::isComplete() const { bool SectionTracker::isComplete() const {
bool complete = true; bool complete = true;
if ((m_filters.empty() || m_filters[0] == "") if (m_filters.empty()
|| m_filters[0] == ""
|| std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) { || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
complete = TrackerBase::isComplete(); complete = TrackerBase::isComplete();
} }
@ -15206,7 +15238,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 2, 12, 4, "", 0 ); static Version version( 2, 13, 0, "", 0 );
return version; return version;
} }
@ -15608,6 +15640,17 @@ namespace Catch {
return std::string(buffer); return std::string(buffer);
} }
bool shouldShowDuration( IConfig const& config, double duration ) {
if ( config.showDurations() == ShowDurations::Always ) {
return true;
}
if ( config.showDurations() == ShowDurations::Never ) {
return false;
}
const double min = config.minDuration();
return min >= 0 && duration >= min;
}
std::string serializeFilters( std::vector<std::string> const& container ) { std::string serializeFilters( std::vector<std::string> const& container ) {
ReusableStringStream oss; ReusableStringStream oss;
bool first = true; bool first = true;
@ -15874,10 +15917,6 @@ private:
return "Reports test results on a single line, suitable for IDEs"; return "Reports test results on a single line, suitable for IDEs";
} }
ReporterPreferences CompactReporter::getPreferences() const {
return m_reporterPrefs;
}
void CompactReporter::noMatchingTestCases( std::string const& spec ) { void CompactReporter::noMatchingTestCases( std::string const& spec ) {
stream << "No test cases matched '" << spec << '\'' << std::endl; stream << "No test cases matched '" << spec << '\'' << std::endl;
} }
@ -15904,8 +15943,9 @@ private:
} }
void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
if (m_config->showDurations() == ShowDurations::Always) { double dur = _sectionStats.durationInSeconds;
stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; if ( shouldShowDuration( *m_config, dur ) ) {
stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << std::endl;
} }
} }
@ -16325,8 +16365,9 @@ void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
stream << "\nNo assertions in test case"; stream << "\nNo assertions in test case";
stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
} }
if (m_config->showDurations() == ShowDurations::Always) { double dur = _sectionStats.durationInSeconds;
stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; if (shouldShowDuration(*m_config, dur)) {
stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl;
} }
if (m_headerPrinted) { if (m_headerPrinted) {
m_headerPrinted = false; m_headerPrinted = false;

View File

@ -23,16 +23,17 @@ namespace Catch {
using StreamingReporterBase::StreamingReporterBase; using StreamingReporterBase::StreamingReporterBase;
TAPReporter( ReporterConfig const& config ):
StreamingReporterBase( config ) {
m_reporterPrefs.shouldReportAllAssertions = true;
}
~TAPReporter() override; ~TAPReporter() override;
static std::string getDescription() { static std::string getDescription() {
return "Reports test results in TAP format, suitable for test harnesses"; return "Reports test results in TAP format, suitable for test harnesses";
} }
ReporterPreferences getPreferences() const override {
return m_reporterPrefs;
}
void noMatchingTestCases( std::string const& spec ) override { void noMatchingTestCases( std::string const& spec ) override {
stream << "# No test cases matched '" << spec << "'" << std::endl; stream << "# No test cases matched '" << spec << "'" << std::endl;
} }
@ -203,16 +204,15 @@ namespace Catch {
return; return;
} }
// using messages.end() directly (or auto) yields compilation error: const auto itEnd = messages.cend();
std::vector<MessageInfo>::const_iterator itEnd = messages.end(); const auto N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
{ {
Colour colourGuard( colour ); Colour colourGuard( colour );
stream << " with " << pluralise( N, "message" ) << ":"; stream << " with " << pluralise( N, "message" ) << ":";
} }
for(; itMessage != itEnd; ) { while( itMessage != itEnd ) {
// If this assertion is a warning ignore any INFO messages // If this assertion is a warning ignore any INFO messages
if( printInfoMessages || itMessage->type != ResultWas::Info ) { if( printInfoMessages || itMessage->type != ResultWas::Info ) {
stream << " '" << itMessage->message << "'"; stream << " '" << itMessage->message << "'";
@ -220,7 +220,9 @@ namespace Catch {
Colour colourGuard( dimColour() ); Colour colourGuard( dimColour() );
stream << " and"; stream << " and";
} }
continue;
} }
++itMessage;
} }
} }
@ -234,10 +236,9 @@ namespace Catch {
}; };
void printTotals( const Totals& totals ) const { void printTotals( const Totals& totals ) const {
stream << "1.." << totals.assertions.total();
if( totals.testCases.total() == 0 ) { if( totals.testCases.total() == 0 ) {
stream << "1..0 # Skipped: No tests ran."; stream << " # Skipped: No tests ran.";
} else {
stream << "1.." << counter;
} }
} }
}; };