1
0
mirror of https://github.com/catchorg/Catch2.git synced 2025-01-16 15:18:00 +00:00

Compare commits

...

7 Commits

Author SHA1 Message Date
Martin Hořeňovský
7f21cc6c55
v2.13.0 2020-07-12 20:28:38 +02:00
Martin Hořeňovský
4c85248179
Fixup whitespace in TAPReporter 2020-07-12 20:27:25 +02:00
Martin Hořeňovský
b4e2237152
Remove pointless CompactReporter::getPreferences override 2020-07-12 20:06:14 +02:00
Martin Hořeňovský
40937b67c7
Merge pull request #1983 from s7726/patch-1
Update catch_reporter_tap.hpp
2020-07-12 20:00:03 +02:00
Martin Hořeňovský
0d5b131394
Improve documentation for --min-duration 2020-07-12 16:27:55 +02:00
Martin Hořeňovský
ad3b90553b
Document GENERATE's new usage between SECTIONs 2020-07-12 16:24:32 +02:00
Gavin S
b1c45652e5
Update catch_reporter_tap.hpp
TAP format requires all results to be reported.
Removed extraneous preferences function (handled by parent)
Incorporated fix from 3d9e7db2e0
Simplified total printing
2020-07-12 01:17:37 -07:00
12 changed files with 173 additions and 71 deletions

View File

@ -14,7 +14,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif()
project(Catch2 LANGUAGES CXX VERSION 2.12.4)
project(Catch2 LANGUAGES CXX VERSION 2.13.0)
# Provide path for scripts
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://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)
[![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)
<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!

View File

@ -224,7 +224,13 @@ When set to ```yes``` Catch will report the duration of each test case, in milli
<pre>-D, --min-duration &lt;value></pre>
When set, Catch will report the duration of each test case that took more than &lt;value> seconds, in milliseconds.
> `--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
than &lt;value> seconds, in milliseconds. This option is overriden by both
`-d yes` and `-d no`, so that either all durations are reported, or none
are.
<a id="input-file"></a>
## Load test names to run from a file

View File

@ -11,6 +11,38 @@ are run once per each value in a generator.
This is best explained with an example:
```cpp
TEST_CASE("Generators") {
auto i = GENERATE(1, 3, 5);
REQUIRE(is_odd(i));
}
```
The "Generators" `TEST_CASE` will be entered 3 times, and the value of
`i` will be 1, 3, and 5 in turn. `GENERATE`s can also be used multiple
times at the same scope, in which case the result will be a cartesian
product of all elements in the generators. This means that in the snippet
below, the test case will be run 6 (2\*3) times.
```cpp
TEST_CASE("Generators") {
auto i = GENERATE(1, 2);
auto j = GENERATE(3, 4, 5);
}
```
There are 2 parts to generators in Catch2, the `GENERATE` macro together
with the already provided generators, and the `IGenerator<T>` interface
that allows users to implement their own generators.
## Combining `GENERATE` and `SECTION`.
`GENERATE` can be seen as an implicit `SECTION`, that goes from the place
`GENERATE` is used, to the end of the scope. This can be used for various
effects. The simplest usage is shown below, where the `SECTION` "one"
runs 4 (2\*2) times, and `SECTION` "two" is run 6 times (2\*3).
```
TEST_CASE("Generators") {
auto i = GENERATE(1, 2);
SECTION("one") {
@ -24,29 +56,43 @@ TEST_CASE("Generators") {
}
```
The `SECTION` "one" will be run 4 (2\*2) times, because the outer
generator has 2 elements in it, and the inner generator also has 2
elements in it. The `SECTION` "two" will be run 6 (2\*3) times. The
sections will be run in order "one", "one", "two", "two", "two", "one",
...
The specific order of the `SECTION`s will be "one", "one", "two", "two",
"two", "one"...
It is also possible to have multiple generators at the same level of
nesting. The result is the same as when generators are inside nested
sections, that is, the result will be a cartesian product of all
elements. This means that in the snippet below, the test case will be
run 6 (2\*3) times.
The fact that `GENERATE` introduces a virtual `SECTION` can als obe used
to make a generator replay only some `SECTION`s, without having to
explicitly add a `SECTION`. As an example, the code below reports 3
assertions, because the "first" section is run once, but the "second"
section is run twice.
```cpp
TEST_CASE("Generators") {
auto i = GENERATE(1, 2);
auto j = GENERATE(3, 4, 5);
TEST_CASE("GENERATE between SECTIONs") {
SECTION("first") { REQUIRE(true); }
auto _ = GENERATE(1, 2);
SECTION("second") { REQUIRE(true); }
}
```
This can lead to surprisingly complex test flows. As an example, the test
below will report 14 assertions:
There are 2 parts to generators in Catch2, the `GENERATE` macro together
with the already provided generators, and the `IGenerator<T>` interface
that allows users to implement their own generators.
```cpp
TEST_CASE("Complex mix of sections and generates") {
auto i = GENERATE(1, 2);
SECTION("A") {
SUCCEED("A");
}
auto j = GENERATE(3, 4);
SECTION("B") {
SUCCEED("B");
}
auto k = GENERATE(5, 6);
SUCCEED();
}
```
> 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

View File

@ -2,6 +2,7 @@
# Release notes
**Contents**<br>
[2.13.0](#2130)<br>
[2.12.4](#2124)<br>
[2.12.3](#2123)<br>
[2.12.2](#2122)<br>
@ -39,6 +40,18 @@
[Older versions](#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

View File

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

View File

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

View File

@ -245,10 +245,6 @@ private:
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 ) {
stream << "No test cases matched '" << spec << '\'' << std::endl;
}

View File

@ -22,8 +22,6 @@ namespace Catch {
static std::string getDescription();
ReporterPreferences getPreferences() const override;
void noMatchingTestCases(std::string const& spec) override;
void assertionStarting(AssertionInfo const&) override;

View File

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

View File

@ -1,6 +1,6 @@
/*
* Catch v2.12.4
* Generated: 2020-07-05 11:47:18.451282
* Catch v2.13.0
* Generated: 2020-07-12 20:07:49.015950
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved.
@ -14,8 +14,8 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 12
#define CATCH_VERSION_PATCH 4
#define CATCH_VERSION_MINOR 13
#define CATCH_VERSION_PATCH 0
#ifdef __clang__
# pragma clang system_header
@ -4522,6 +4522,7 @@ namespace Catch {
virtual int abortAfter() const = 0;
virtual bool showInvisibles() const = 0;
virtual ShowDurations::OrNot showDurations() const = 0;
virtual double minDuration() const = 0;
virtual TestSpec const& testSpec() const = 0;
virtual bool hasTestFilters() const = 0;
virtual std::vector<std::string> const& getTestsOrTags() const = 0;
@ -5294,6 +5295,7 @@ namespace Catch {
Verbosity verbosity = Verbosity::Normal;
WarnAbout::What warnings = WarnAbout::Nothing;
ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
double minDuration = -1;
RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
UseColour::YesOrNo useColour = UseColour::Auto;
WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
@ -5344,6 +5346,7 @@ namespace Catch {
bool warnAboutMissingAssertions() const override;
bool warnAboutNoTests() const override;
ShowDurations::OrNot showDurations() const override;
double minDuration() const override;
RunTests::InWhatOrder runOrder() const override;
unsigned int rngSeed() const override;
UseColour::YesOrNo useColour() const override;
@ -5721,6 +5724,9 @@ namespace Catch {
// Returns double formatted as %.3f (format expected on output)
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 );
template<typename DerivedT>
@ -6114,8 +6120,6 @@ namespace Catch {
static std::string getDescription();
ReporterPreferences getPreferences() const override;
void noMatchingTestCases(std::string const& spec) override;
void assertionStarting(AssertionInfo const&) override;
@ -7499,6 +7503,7 @@ namespace TestCaseTracking {
virtual bool isSuccessfullyCompleted() const = 0;
virtual bool isOpen() const = 0; // Started but not complete
virtual bool hasChildren() const = 0;
virtual bool hasStarted() const = 0;
virtual ITracker& parent() = 0;
@ -7565,6 +7570,9 @@ namespace TestCaseTracking {
bool isSuccessfullyCompleted() const override;
bool isOpen() const override;
bool hasChildren() const override;
bool hasStarted() const override {
return m_runState != NotStarted;
}
void addChild( ITrackerPtr const& child ) override;
@ -9861,6 +9869,9 @@ namespace Catch {
| Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
["-d"]["--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" )
["-f"]["--input-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::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); }
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; }
unsigned int Config::rngSeed() const { return m_data.rngSeed; }
UseColour::YesOrNo Config::useColour() const { return m_data.useColour; }
@ -12547,7 +12559,7 @@ namespace Catch {
currentTracker.addChild( tracker );
}
if( !ctx.completedCycle() && !tracker->isComplete() ) {
if( !tracker->isComplete() ) {
tracker->open();
}
@ -12561,8 +12573,28 @@ namespace Catch {
}
void close() override {
TrackerBase::close();
// Generator interface only finds out if it has another item on atual move
if (m_runState == CompletedSuccessfully && m_generator->next()) {
// If a generator has a child (it is followed by a section)
// 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_runState = Executing;
}
@ -12702,7 +12734,6 @@ namespace Catch {
using namespace Generators;
GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext,
TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) );
assert( tracker.isOpen() );
m_lastAssertionInfo.lineInfo = lineInfo;
return tracker;
}
@ -14381,7 +14412,8 @@ namespace TestCaseTracking {
bool SectionTracker::isComplete() const {
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()) {
complete = TrackerBase::isComplete();
}
@ -15206,7 +15238,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 2, 12, 4, "", 0 );
static Version version( 2, 13, 0, "", 0 );
return version;
}
@ -15608,6 +15640,17 @@ namespace Catch {
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 ) {
ReusableStringStream oss;
bool first = true;
@ -15874,10 +15917,6 @@ private:
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 ) {
stream << "No test cases matched '" << spec << '\'' << std::endl;
}
@ -15904,8 +15943,9 @@ private:
}
void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
if (m_config->showDurations() == ShowDurations::Always) {
stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
double dur = _sectionStats.durationInSeconds;
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 << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
}
if (m_config->showDurations() == ShowDurations::Always) {
stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
double dur = _sectionStats.durationInSeconds;
if (shouldShowDuration(*m_config, dur)) {
stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl;
}
if (m_headerPrinted) {
m_headerPrinted = false;

View File

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