mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-03 21:49:32 +01:00 
			
		
		
		
	Merge from origin
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
*v1.0 build 11 (master branch)*
 | 
			
		||||
*v1.0 build 13 (master branch)*
 | 
			
		||||
 | 
			
		||||
Build status (on Travis CI) [](https://travis-ci.org/philsquared/Catch)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ Note that options are described according to the following pattern:
 | 
			
		||||
 | 
			
		||||
Test cases, wildcarded test cases, tags and tag expressions are all passed directly as arguments. Tags are distinguished by being enclosed in square brackets.
 | 
			
		||||
 | 
			
		||||
If no test specs are supplied then all test cases, except "hidden" tests (tagged ```[hide]``` or, in the legacy case, prefixed by `'./'`) are run
 | 
			
		||||
If no test specs are supplied then all test cases, except "hidden" tests (tagged ```[hide]```, ```[.]``` or, in the legacy case, prefixed by `'./'`) are run.
 | 
			
		||||
 | 
			
		||||
Specs must be enclosed in quotes if they contain spaces. If they do not contain spaces the quotes are optional.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,22 @@ For examples see the [Tutorial](tutorial.md)
 | 
			
		||||
 | 
			
		||||
## Tags
 | 
			
		||||
 | 
			
		||||
-{placeholder for documentation of tags}-
 | 
			
		||||
Tags allow an arbitrary number of additional strings to be associated with a test case. Test cases can be selected (for running, or just for listing) by tag - or even by an expression that combines several tags. At their most basic level they provide a simple way to group several related tests together.
 | 
			
		||||
 | 
			
		||||
As an example - given the following test cases:
 | 
			
		||||
 | 
			
		||||
	TEST_CASE( "A", "[widget]" ) { /* ... */ }
 | 
			
		||||
	TEST_CASE( "B", "[widget]" ) { /* ... */ }
 | 
			
		||||
	TEST_CASE( "C", "[gadget]" ) { /* ... */ }
 | 
			
		||||
	TEST_CASE( "D", "[widget][gadget]" ) { /* ... */ }
 | 
			
		||||
 | 
			
		||||
The tag expression, ```"[widget]"``` selects A, B & D. ```"[gadget]"``` selects C & D. ```"[widget][gadget]"``` selects just D and ```"[widget],[gadget]"``` selects all four test cases.
 | 
			
		||||
 | 
			
		||||
For more detail on command line selection see [the command line docs](command-line.md#specifying-which-tests-to-run)
 | 
			
		||||
 | 
			
		||||
A special tag name, ```[hide]``` causes test cases to be skipped from the default list (ie when no test cases have been explicitly selected through tag expressions or name wildcards). ```[.]``` is an alias for ```[hide]```.
 | 
			
		||||
 | 
			
		||||
Tag names are not case sensitive.
 | 
			
		||||
 | 
			
		||||
## BDD-style test cases
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -87,11 +87,11 @@ Of course there are still more issues to do deal with. For example we'll hit pro
 | 
			
		||||
Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take moment to consider those before we move on.
 | 
			
		||||
 | 
			
		||||
1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md).
 | 
			
		||||
2. We introduce test cases with the TEST_CASE macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#testCasesAndSections">Test cases and Sections</a>, below. The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md) for more information on running tests.
 | 
			
		||||
2. We introduce test cases with the TEST_CASE macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#test-cases-and-sections">Test cases and Sections</a>, below. The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md) for more information on running tests.
 | 
			
		||||
3. The name and tags arguments are just strings. We haven't had to declare a function or method - or explicitly register the test case anywhere. Behind the scenes a function with a generated name is defined for you, and automatically registered using static registry classes. By abstracting the function name away we can name our tests without the constraints of identifier names.
 | 
			
		||||
4. We write our individual test assertions using the REQUIRE macro. Rather than a separate macro for each type of condition we express the condition naturally using C/C++ syntax. Behind the scenes a simple set of expression templates captures the left-hand-side and right-hand-side of the expression so we can display the values in our test report. As we'll see later there _are_ other assertion macros - but because of this technique the number of them is drastically reduced.
 | 
			
		||||
 | 
			
		||||
<a id="testCasesAndSections"></a>
 | 
			
		||||
<a id="test-cases-and-sections"></a>
 | 
			
		||||
## Test cases and sections
 | 
			
		||||
 | 
			
		||||
Most test frameworks have a class-based fixture mechanism. That is, test cases map to methods on a class and common setup and teardown can be performed in ```setup()``` and ```teardown()``` methods (or constructor/ destructor in languages, like C++, that support deterministic destruction).
 | 
			
		||||
@@ -140,7 +140,82 @@ This works because the ```SECTION``` macro contains an if statement that calls b
 | 
			
		||||
 | 
			
		||||
So far so good - this is already an improvement on the setup/ teardown approach because now we see our setup code inline and we can use the stack.
 | 
			
		||||
 | 
			
		||||
-{placeholder for documentation on nested sections}-
 | 
			
		||||
The power of sections really shows, however, when we need to execute a sequence of, checked, operations. Continuing the vector example we might want to verify that after reserving a larger capacity, if we reserve smaller capacity (but still larger than the current size) then the capacity is not, in fact, changed. We can do that, naturally, like so:
 | 
			
		||||
 | 
			
		||||
    SECTION( "reserving bigger changes capacity but not size" ) {
 | 
			
		||||
        v.reserve( 10 );
 | 
			
		||||
        
 | 
			
		||||
        REQUIRE( v.size() == 5 );
 | 
			
		||||
        REQUIRE( v.capacity() >= 10 );
 | 
			
		||||
    
 | 
			
		||||
        SECTION( "reserving smaller again does not change capacity" ) {
 | 
			
		||||
            v.reserve( 7 );
 | 
			
		||||
            
 | 
			
		||||
            REQUIRE( v.capacity() >= 10 );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
Sections can be nested to an arbitrary depth (limited only by your stack size). Each leaf section (i.e. a section that contains no nested sections) will be executed exactly once, on a separate path of execution from any other leaf section (so no leaf section can interfere with another). Obviously a failure in a parent section will prevent nested sections from running - but that's the idea.
 | 
			
		||||
 | 
			
		||||
## BDD-Style
 | 
			
		||||
 | 
			
		||||
If you name your test cases and sections appropriately you can achieve a BDD-style specification structure. This became such a useful way of working that first class support has been added to Catch. Scenarios can be specified using ```SCENARIO```, ```GIVEN```, ```WHEN``` and ```THEN``` macros, which map on to ```TEST_CASE```s and ```SECTION```s, respectively (for more details see [Test cases and sections](test-cases-and-sections.md)).
 | 
			
		||||
 | 
			
		||||
The vector example can be adjusted to use these macros like so:
 | 
			
		||||
 | 
			
		||||
```c++
 | 
			
		||||
SCENARIO( "vectors can be sized and resized", "[vector]" ) {
 | 
			
		||||
 | 
			
		||||
    GIVEN( "A vector with some items" ) {
 | 
			
		||||
        std::vector<int> v( 5 );
 | 
			
		||||
        
 | 
			
		||||
        REQUIRE( v.size() == 5 );
 | 
			
		||||
        REQUIRE( v.capacity() >= 5 );
 | 
			
		||||
        
 | 
			
		||||
        WHEN( "the size is increased" ) {
 | 
			
		||||
            v.resize( 10 );
 | 
			
		||||
            
 | 
			
		||||
            THEN( "the size and capacity change" ) {
 | 
			
		||||
                REQUIRE( v.size() == 10 );
 | 
			
		||||
                REQUIRE( v.capacity() >= 10 );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        WHEN( "the size is reduced" ) {
 | 
			
		||||
            v.resize( 0 );
 | 
			
		||||
            
 | 
			
		||||
            THEN( "the size changes but not capacity" ) {
 | 
			
		||||
                REQUIRE( v.size() == 0 );
 | 
			
		||||
                REQUIRE( v.capacity() >= 5 );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        WHEN( "more capacity is reserved" ) {
 | 
			
		||||
            v.reserve( 10 );
 | 
			
		||||
            
 | 
			
		||||
            THEN( "the capacity changes but not the size" ) {
 | 
			
		||||
                REQUIRE( v.size() == 5 );
 | 
			
		||||
                REQUIRE( v.capacity() >= 10 );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        WHEN( "less capacity is reserved" ) {
 | 
			
		||||
            v.reserve( 0 );
 | 
			
		||||
            
 | 
			
		||||
            THEN( "neither size nor capacity are changed" ) {
 | 
			
		||||
                REQUIRE( v.size() == 5 );
 | 
			
		||||
                REQUIRE( v.capacity() >= 5 );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
A nice consequence of this is that when these tests are run the test names are reported like this:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
Scenario: vectors can be sized and resized
 | 
			
		||||
     Given: A vector with some items
 | 
			
		||||
      When: more capacity is reserved
 | 
			
		||||
      Then: the capacity changes but not the size
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Next steps
 | 
			
		||||
For more specific information see the [Reference pages](reference-index.md)
 | 
			
		||||
 
 | 
			
		||||
@@ -30,76 +30,29 @@ namespace Catch {
 | 
			
		||||
            std::cout << "All available test cases:\n";
 | 
			
		||||
        else
 | 
			
		||||
            std::cout << "Matching test cases:\n";
 | 
			
		||||
        std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
 | 
			
		||||
        std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
 | 
			
		||||
 | 
			
		||||
        // First pass - get max tags
 | 
			
		||||
        std::size_t maxTagLen = 0;
 | 
			
		||||
        std::size_t maxNameLen = 0;
 | 
			
		||||
        for(; it != itEnd; ++it ) {
 | 
			
		||||
            if( matchesFilters( config.filters(), *it ) ) {
 | 
			
		||||
                maxTagLen = (std::max)( it->getTestCaseInfo().tagsAsString.size(), maxTagLen );
 | 
			
		||||
                maxNameLen = (std::max)( it->getTestCaseInfo().name.size(), maxNameLen );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Try to fit everything in. If not shrink tag column first, down to 30
 | 
			
		||||
        // then shrink name column until it all fits (strings will be wrapped within column)
 | 
			
		||||
        while( maxTagLen + maxNameLen > CATCH_CONFIG_CONSOLE_WIDTH-5 ) {
 | 
			
		||||
            if( maxTagLen > 30 )
 | 
			
		||||
                --maxTagLen;
 | 
			
		||||
            else
 | 
			
		||||
                --maxNameLen;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::size_t matchedTests = 0;
 | 
			
		||||
        for( it = allTests.begin(); it != itEnd; ++it ) {
 | 
			
		||||
        TextAttributes nameAttr, tagsAttr;
 | 
			
		||||
        nameAttr.setInitialIndent( 2 ).setIndent( 4 );
 | 
			
		||||
        tagsAttr.setIndent( 6 );
 | 
			
		||||
 | 
			
		||||
        std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
 | 
			
		||||
        for( std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
 | 
			
		||||
                it != itEnd;
 | 
			
		||||
                ++it )
 | 
			
		||||
            if( matchesFilters( config.filters(), *it ) ) {
 | 
			
		||||
                matchedTests++;
 | 
			
		||||
                Text nameWrapper(   it->getTestCaseInfo().name,
 | 
			
		||||
                                    TextAttributes()
 | 
			
		||||
                                        .setWidth( maxNameLen+2 )
 | 
			
		||||
                                        .setInitialIndent(2)
 | 
			
		||||
                                        .setIndent(4) );
 | 
			
		||||
                TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
 | 
			
		||||
                Colour::Code colour = testCaseInfo.isHidden
 | 
			
		||||
                    ? Colour::SecondaryText
 | 
			
		||||
                    : Colour::None;
 | 
			
		||||
                Colour colourGuard( colour );
 | 
			
		||||
 | 
			
		||||
                Text tagsWrapper(   it->getTestCaseInfo().tagsAsString,
 | 
			
		||||
                                    TextAttributes()
 | 
			
		||||
                                        .setWidth( maxTagLen )
 | 
			
		||||
                                        .setInitialIndent(0)
 | 
			
		||||
                                        .setIndent( 2 ) );
 | 
			
		||||
 | 
			
		||||
                for( std::size_t i = 0; i < (std::max)( nameWrapper.size(), tagsWrapper.size() ); ++i ) {
 | 
			
		||||
                    Colour::Code colour = Colour::None;
 | 
			
		||||
                    if( it->getTestCaseInfo().isHidden )
 | 
			
		||||
                        colour = Colour::SecondaryText;
 | 
			
		||||
                    std::string nameCol;
 | 
			
		||||
                    if( i < nameWrapper.size() ) {
 | 
			
		||||
                        nameCol = nameWrapper[i];
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        nameCol = "    ...";
 | 
			
		||||
                        colour = Colour::SecondaryText;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    {
 | 
			
		||||
                        Colour colourGuard( colour );
 | 
			
		||||
                        std::cout << nameCol;
 | 
			
		||||
                    }
 | 
			
		||||
                    if( i < tagsWrapper.size() && !tagsWrapper[i].empty() ) {
 | 
			
		||||
                        size_t padLen( maxNameLen > nameCol.size() ? maxNameLen - nameCol.size() : 0 );
 | 
			
		||||
                        if( i == 0 ) {
 | 
			
		||||
                            Colour colourGuard( Colour::SecondaryText );
 | 
			
		||||
                            std::cout << "  " << std::string( padLen, '.' ) << "  ";
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            std::cout << std::string( padLen, ' ' ) << "    ";
 | 
			
		||||
                        }
 | 
			
		||||
                        std::cout << tagsWrapper[i];
 | 
			
		||||
                    }
 | 
			
		||||
                    std::cout << "\n";
 | 
			
		||||
                }
 | 
			
		||||
                std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl;
 | 
			
		||||
                if( !testCaseInfo.tags.empty() )
 | 
			
		||||
                    std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if( config.filters().empty() )
 | 
			
		||||
            std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
 | 
			
		||||
        else
 | 
			
		||||
@@ -112,21 +65,20 @@ namespace Catch {
 | 
			
		||||
            std::cout << "All available tags:\n";
 | 
			
		||||
        else
 | 
			
		||||
            std::cout << "Matching tags:\n";
 | 
			
		||||
        std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
 | 
			
		||||
        std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
 | 
			
		||||
 | 
			
		||||
        std::map<std::string, int> tagCounts;
 | 
			
		||||
 | 
			
		||||
        std::size_t maxTagLen = 0;
 | 
			
		||||
 | 
			
		||||
        for(; it != itEnd; ++it ) {
 | 
			
		||||
        std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
 | 
			
		||||
        for( std::vector<TestCase>::const_iterator  it = allTests.begin(),
 | 
			
		||||
                                                    itEnd = allTests.end();
 | 
			
		||||
                it != itEnd;
 | 
			
		||||
                ++it ) {
 | 
			
		||||
            if( matchesFilters( config.filters(), *it ) ) {
 | 
			
		||||
                for( std::set<std::string>::const_iterator  tagIt = it->getTestCaseInfo().tags.begin(),
 | 
			
		||||
                                                            tagItEnd = it->getTestCaseInfo().tags.end();
 | 
			
		||||
                        tagIt != tagItEnd;
 | 
			
		||||
                        ++tagIt ) {
 | 
			
		||||
                    std::string tagName = *tagIt;
 | 
			
		||||
                    maxTagLen = (std::max)( maxTagLen, tagName.size() );
 | 
			
		||||
                    std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
 | 
			
		||||
                    if( countIt == tagCounts.end() )
 | 
			
		||||
                        tagCounts.insert( std::make_pair( tagName, 1 ) );
 | 
			
		||||
@@ -135,26 +87,18 @@ namespace Catch {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        maxTagLen +=4;
 | 
			
		||||
        if( maxTagLen > CATCH_CONFIG_CONSOLE_WIDTH-10 )
 | 
			
		||||
            maxTagLen = CATCH_CONFIG_CONSOLE_WIDTH-10;
 | 
			
		||||
 | 
			
		||||
        for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(), countItEnd = tagCounts.end();
 | 
			
		||||
        for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(),
 | 
			
		||||
                                                        countItEnd = tagCounts.end();
 | 
			
		||||
                countIt != countItEnd;
 | 
			
		||||
                ++countIt ) {
 | 
			
		||||
            std::ostringstream oss;
 | 
			
		||||
            oss << "  " << countIt->second << "  ";
 | 
			
		||||
            Text wrapper( "[" + countIt->first + "]", TextAttributes()
 | 
			
		||||
                                                        .setIndent(2)
 | 
			
		||||
                                                        .setWidth( maxTagLen ) );
 | 
			
		||||
            std::cout << wrapper;
 | 
			
		||||
            std::size_t dots = 2;
 | 
			
		||||
            if( maxTagLen > wrapper.last().size() )
 | 
			
		||||
                dots += maxTagLen - wrapper.last().size();
 | 
			
		||||
            {
 | 
			
		||||
                Colour colourGuard( Colour::SecondaryText );
 | 
			
		||||
                std::cout << std::string( dots, '.' );
 | 
			
		||||
            }
 | 
			
		||||
            std::cout   << countIt->second
 | 
			
		||||
                        << "\n";
 | 
			
		||||
                                                        .setInitialIndent( 0 )
 | 
			
		||||
                                                        .setIndent( oss.str().size() )
 | 
			
		||||
                                                        .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
 | 
			
		||||
            std::cout << oss.str() << wrapper << "\n";
 | 
			
		||||
        }
 | 
			
		||||
        std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
 | 
			
		||||
        return tagCounts.size();
 | 
			
		||||
 
 | 
			
		||||
@@ -14,8 +14,7 @@ namespace Catch {
 | 
			
		||||
 | 
			
		||||
    // These numbers are maintained by a script
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    const T LibraryVersionInfo<T>::value( 1, 0, 11, "master" );
 | 
			
		||||
 | 
			
		||||
    const T LibraryVersionInfo<T>::value( 1, 0, 13, "master" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
@@ -41,13 +41,18 @@ namespace Catch {
 | 
			
		||||
        virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
 | 
			
		||||
            AssertionResult const& result = _assertionStats.assertionResult;
 | 
			
		||||
 | 
			
		||||
            bool printInfoMessages = true;
 | 
			
		||||
 | 
			
		||||
            // Drop out if result was successful and we're not printing those
 | 
			
		||||
            if( !m_config->includeSuccessfulResults() && result.isOk() )
 | 
			
		||||
                return false;
 | 
			
		||||
            if( !m_config->includeSuccessfulResults() && result.isOk() ) {
 | 
			
		||||
                if( result.getResultType() != ResultWas::Warning )
 | 
			
		||||
                    return false;
 | 
			
		||||
                printInfoMessages = false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            lazyPrint();
 | 
			
		||||
 | 
			
		||||
            AssertionPrinter printer( stream, _assertionStats );
 | 
			
		||||
            AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
 | 
			
		||||
            printer.print();
 | 
			
		||||
            stream << std::endl;
 | 
			
		||||
            return true;
 | 
			
		||||
@@ -105,13 +110,14 @@ namespace Catch {
 | 
			
		||||
        class AssertionPrinter {
 | 
			
		||||
            void operator= ( AssertionPrinter const& );
 | 
			
		||||
        public:
 | 
			
		||||
            AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats )
 | 
			
		||||
            AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
 | 
			
		||||
            :   stream( _stream ),
 | 
			
		||||
                stats( _stats ),
 | 
			
		||||
                result( _stats.assertionResult ),
 | 
			
		||||
                colour( Colour::None ),
 | 
			
		||||
                message( result.getMessage() ),
 | 
			
		||||
                messages( _stats.infoMessages )
 | 
			
		||||
                messages( _stats.infoMessages ),
 | 
			
		||||
                printInfoMessages( _printInfoMessages )
 | 
			
		||||
            {
 | 
			
		||||
                switch( result.getResultType() ) {
 | 
			
		||||
                    case ResultWas::Ok:
 | 
			
		||||
@@ -214,7 +220,9 @@ namespace Catch {
 | 
			
		||||
                for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
 | 
			
		||||
                        it != itEnd;
 | 
			
		||||
                        ++it ) {
 | 
			
		||||
                    stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
 | 
			
		||||
                    // If this assertion is a warning ignore any INFO messages
 | 
			
		||||
                    if( printInfoMessages || it->type != ResultWas::Info )
 | 
			
		||||
                        stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            void printSourceInfo() const {
 | 
			
		||||
@@ -230,6 +238,7 @@ namespace Catch {
 | 
			
		||||
            std::string messageLabel;
 | 
			
		||||
            std::string message;
 | 
			
		||||
            std::vector<MessageInfo> messages;
 | 
			
		||||
            bool printInfoMessages;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        void lazyPrint() {
 | 
			
		||||
@@ -315,9 +324,14 @@ namespace Catch {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void printTotals( const Totals& totals ) {
 | 
			
		||||
            if( totals.assertions.total() == 0 ) {
 | 
			
		||||
            if( totals.testCases.total() == 0 ) {
 | 
			
		||||
                stream << "No tests ran";
 | 
			
		||||
            }
 | 
			
		||||
            else if( totals.assertions.total() == 0 ) {
 | 
			
		||||
                Colour colour( Colour::Yellow );
 | 
			
		||||
                printCounts( "test case", totals.testCases );
 | 
			
		||||
                stream << " (no assertions)";
 | 
			
		||||
            }
 | 
			
		||||
            else if( totals.assertions.failed ) {
 | 
			
		||||
                Colour colour( Colour::ResultError );
 | 
			
		||||
                printCounts( "test case", totals.testCases );
 | 
			
		||||
 
 | 
			
		||||
@@ -373,6 +373,16 @@ ExceptionTests.cpp:<line number>: FAILED:
 | 
			
		||||
due to unexpected exception with message:
 | 
			
		||||
  3.14
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
./succeeding/message
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
MessageTests.cpp:<line number>
 | 
			
		||||
...............................................................................
 | 
			
		||||
 | 
			
		||||
MessageTests.cpp:<line number>:
 | 
			
		||||
warning:
 | 
			
		||||
  this is a warning
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
./failing/message/info/1
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
@@ -640,6 +650,16 @@ MiscTests.cpp:<line number>: FAILED:
 | 
			
		||||
with expansion:
 | 
			
		||||
  "this string contains 'abc' as a substring" equals: "something else"
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Nice descriptive name
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
MiscTests.cpp:<line number>
 | 
			
		||||
...............................................................................
 | 
			
		||||
 | 
			
		||||
MiscTests.cpp:<line number>:
 | 
			
		||||
warning:
 | 
			
		||||
  This one ran
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
./failing/CatchSectionInfiniteLoop
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
@@ -680,6 +700,28 @@ Some information
 | 
			
		||||
An error
 | 
			
		||||
hello
 | 
			
		||||
hello
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
./inprogress/failing/Tricky/trailing expression
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
TrickyTests.cpp:<line number>
 | 
			
		||||
...............................................................................
 | 
			
		||||
 | 
			
		||||
TrickyTests.cpp:<line number>:
 | 
			
		||||
warning:
 | 
			
		||||
  Uncomment the code in this test to check that it gives a sensible compiler
 | 
			
		||||
  error
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
./inprogress/failing/Tricky/compound lhs
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
TrickyTests.cpp:<line number>
 | 
			
		||||
...............................................................................
 | 
			
		||||
 | 
			
		||||
TrickyTests.cpp:<line number>:
 | 
			
		||||
warning:
 | 
			
		||||
  Uncomment the code in this test to check that it gives a sensible compiler
 | 
			
		||||
  error
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
./failing/Tricky/non streamable type
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  CATCH v1.0 build 11 (master branch)
 | 
			
		||||
 *  Generated: 2013-10-23 15:34:32.120349
 | 
			
		||||
 *  CATCH v1.0 build 13 (master branch)
 | 
			
		||||
 *  Generated: 2013-11-13 08:10:05.836093
 | 
			
		||||
 *  ----------------------------------------------------------
 | 
			
		||||
 *  This file has been merged from multiple headers. Please don't edit it directly
 | 
			
		||||
 *  Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
 | 
			
		||||
@@ -595,6 +595,7 @@ namespace Catch {
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
#include <limits>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#ifdef __OBJC__
 | 
			
		||||
// #included from: catch_objc_arc.hpp
 | 
			
		||||
@@ -4573,75 +4574,29 @@ namespace Catch {
 | 
			
		||||
            std::cout << "All available test cases:\n";
 | 
			
		||||
        else
 | 
			
		||||
            std::cout << "Matching test cases:\n";
 | 
			
		||||
        std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
 | 
			
		||||
        std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
 | 
			
		||||
 | 
			
		||||
        // First pass - get max tags
 | 
			
		||||
        std::size_t maxTagLen = 0;
 | 
			
		||||
        std::size_t maxNameLen = 0;
 | 
			
		||||
        for(; it != itEnd; ++it ) {
 | 
			
		||||
            if( matchesFilters( config.filters(), *it ) ) {
 | 
			
		||||
                maxTagLen = (std::max)( it->getTestCaseInfo().tagsAsString.size(), maxTagLen );
 | 
			
		||||
                maxNameLen = (std::max)( it->getTestCaseInfo().name.size(), maxNameLen );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Try to fit everything in. If not shrink tag column first, down to 30
 | 
			
		||||
        // then shrink name column until it all fits (strings will be wrapped within column)
 | 
			
		||||
        while( maxTagLen + maxNameLen > CATCH_CONFIG_CONSOLE_WIDTH-5 ) {
 | 
			
		||||
            if( maxTagLen > 30 )
 | 
			
		||||
                --maxTagLen;
 | 
			
		||||
            else
 | 
			
		||||
                --maxNameLen;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::size_t matchedTests = 0;
 | 
			
		||||
        for( it = allTests.begin(); it != itEnd; ++it ) {
 | 
			
		||||
        TextAttributes nameAttr, tagsAttr;
 | 
			
		||||
        nameAttr.setInitialIndent( 2 ).setIndent( 4 );
 | 
			
		||||
        tagsAttr.setIndent( 6 );
 | 
			
		||||
 | 
			
		||||
        std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
 | 
			
		||||
        for( std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
 | 
			
		||||
                it != itEnd;
 | 
			
		||||
                ++it )
 | 
			
		||||
            if( matchesFilters( config.filters(), *it ) ) {
 | 
			
		||||
                matchedTests++;
 | 
			
		||||
                Text nameWrapper(   it->getTestCaseInfo().name,
 | 
			
		||||
                                    TextAttributes()
 | 
			
		||||
                                        .setWidth( maxNameLen+2 )
 | 
			
		||||
                                        .setInitialIndent(2)
 | 
			
		||||
                                        .setIndent(4) );
 | 
			
		||||
                TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
 | 
			
		||||
                Colour::Code colour = testCaseInfo.isHidden
 | 
			
		||||
                    ? Colour::SecondaryText
 | 
			
		||||
                    : Colour::None;
 | 
			
		||||
                Colour colourGuard( colour );
 | 
			
		||||
 | 
			
		||||
                Text tagsWrapper(   it->getTestCaseInfo().tagsAsString,
 | 
			
		||||
                                    TextAttributes()
 | 
			
		||||
                                        .setWidth( maxTagLen )
 | 
			
		||||
                                        .setInitialIndent(0)
 | 
			
		||||
                                        .setIndent( 2 ) );
 | 
			
		||||
 | 
			
		||||
                for( std::size_t i = 0; i < (std::max)( nameWrapper.size(), tagsWrapper.size() ); ++i ) {
 | 
			
		||||
                    Colour::Code colour = Colour::None;
 | 
			
		||||
                    if( it->getTestCaseInfo().isHidden )
 | 
			
		||||
                        colour = Colour::SecondaryText;
 | 
			
		||||
                    std::string nameCol;
 | 
			
		||||
                    if( i < nameWrapper.size() ) {
 | 
			
		||||
                        nameCol = nameWrapper[i];
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        nameCol = "    ...";
 | 
			
		||||
                        colour = Colour::SecondaryText;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    {
 | 
			
		||||
                        Colour colourGuard( colour );
 | 
			
		||||
                        std::cout << nameCol;
 | 
			
		||||
                    }
 | 
			
		||||
                    if( i < tagsWrapper.size() && !tagsWrapper[i].empty() ) {
 | 
			
		||||
                        if( i == 0 ) {
 | 
			
		||||
                            Colour colourGuard( Colour::SecondaryText );
 | 
			
		||||
                            std::cout << "  " << std::string( maxNameLen - nameCol.size(), '.' ) << "  ";
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            std::cout << std::string( maxNameLen - nameCol.size(), ' ' ) << "    ";
 | 
			
		||||
                        }
 | 
			
		||||
                        std::cout << tagsWrapper[i];
 | 
			
		||||
                    }
 | 
			
		||||
                    std::cout << "\n";
 | 
			
		||||
                }
 | 
			
		||||
                std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl;
 | 
			
		||||
                if( !testCaseInfo.tags.empty() )
 | 
			
		||||
                    std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if( config.filters().empty() )
 | 
			
		||||
            std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
 | 
			
		||||
        else
 | 
			
		||||
@@ -4654,21 +4609,20 @@ namespace Catch {
 | 
			
		||||
            std::cout << "All available tags:\n";
 | 
			
		||||
        else
 | 
			
		||||
            std::cout << "Matching tags:\n";
 | 
			
		||||
        std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
 | 
			
		||||
        std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
 | 
			
		||||
 | 
			
		||||
        std::map<std::string, int> tagCounts;
 | 
			
		||||
 | 
			
		||||
        std::size_t maxTagLen = 0;
 | 
			
		||||
 | 
			
		||||
        for(; it != itEnd; ++it ) {
 | 
			
		||||
        std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
 | 
			
		||||
        for( std::vector<TestCase>::const_iterator  it = allTests.begin(),
 | 
			
		||||
                                                    itEnd = allTests.end();
 | 
			
		||||
                it != itEnd;
 | 
			
		||||
                ++it ) {
 | 
			
		||||
            if( matchesFilters( config.filters(), *it ) ) {
 | 
			
		||||
                for( std::set<std::string>::const_iterator  tagIt = it->getTestCaseInfo().tags.begin(),
 | 
			
		||||
                                                            tagItEnd = it->getTestCaseInfo().tags.end();
 | 
			
		||||
                        tagIt != tagItEnd;
 | 
			
		||||
                        ++tagIt ) {
 | 
			
		||||
                    std::string tagName = *tagIt;
 | 
			
		||||
                    maxTagLen = (std::max)( maxTagLen, tagName.size() );
 | 
			
		||||
                    std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
 | 
			
		||||
                    if( countIt == tagCounts.end() )
 | 
			
		||||
                        tagCounts.insert( std::make_pair( tagName, 1 ) );
 | 
			
		||||
@@ -4677,26 +4631,18 @@ namespace Catch {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        maxTagLen +=4;
 | 
			
		||||
        if( maxTagLen > CATCH_CONFIG_CONSOLE_WIDTH-10 )
 | 
			
		||||
            maxTagLen = CATCH_CONFIG_CONSOLE_WIDTH-10;
 | 
			
		||||
 | 
			
		||||
        for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(), countItEnd = tagCounts.end();
 | 
			
		||||
        for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(),
 | 
			
		||||
                                                        countItEnd = tagCounts.end();
 | 
			
		||||
                countIt != countItEnd;
 | 
			
		||||
                ++countIt ) {
 | 
			
		||||
            std::ostringstream oss;
 | 
			
		||||
            oss << "  " << countIt->second << "  ";
 | 
			
		||||
            Text wrapper( "[" + countIt->first + "]", TextAttributes()
 | 
			
		||||
                                                        .setIndent(2)
 | 
			
		||||
                                                        .setWidth( maxTagLen ) );
 | 
			
		||||
            std::cout << wrapper;
 | 
			
		||||
            std::size_t dots = 2;
 | 
			
		||||
            if( maxTagLen > wrapper.last().size() )
 | 
			
		||||
                dots += maxTagLen - wrapper.last().size();
 | 
			
		||||
            {
 | 
			
		||||
                Colour colourGuard( Colour::SecondaryText );
 | 
			
		||||
                std::cout << std::string( dots, '.' );
 | 
			
		||||
            }
 | 
			
		||||
            std::cout   << countIt->second
 | 
			
		||||
                        << "\n";
 | 
			
		||||
                                                        .setInitialIndent( 0 )
 | 
			
		||||
                                                        .setIndent( oss.str().size() )
 | 
			
		||||
                                                        .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
 | 
			
		||||
            std::cout << oss.str() << wrapper << "\n";
 | 
			
		||||
        }
 | 
			
		||||
        std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
 | 
			
		||||
        return tagCounts.size();
 | 
			
		||||
@@ -6371,7 +6317,7 @@ namespace Catch {
 | 
			
		||||
namespace Catch {
 | 
			
		||||
 | 
			
		||||
    // These numbers are maintained by a script
 | 
			
		||||
    Version libraryVersion( 1, 0, 11, "master" );
 | 
			
		||||
    Version libraryVersion( 1, 0, 13, "master" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// #included from: catch_text.hpp
 | 
			
		||||
@@ -7294,13 +7240,18 @@ namespace Catch {
 | 
			
		||||
        virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
 | 
			
		||||
            AssertionResult const& result = _assertionStats.assertionResult;
 | 
			
		||||
 | 
			
		||||
            bool printInfoMessages = true;
 | 
			
		||||
 | 
			
		||||
            // Drop out if result was successful and we're not printing those
 | 
			
		||||
            if( !m_config->includeSuccessfulResults() && result.isOk() )
 | 
			
		||||
                return false;
 | 
			
		||||
            if( !m_config->includeSuccessfulResults() && result.isOk() ) {
 | 
			
		||||
                if( result.getResultType() != ResultWas::Warning )
 | 
			
		||||
                    return false;
 | 
			
		||||
                printInfoMessages = false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            lazyPrint();
 | 
			
		||||
 | 
			
		||||
            AssertionPrinter printer( stream, _assertionStats );
 | 
			
		||||
            AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
 | 
			
		||||
            printer.print();
 | 
			
		||||
            stream << std::endl;
 | 
			
		||||
            return true;
 | 
			
		||||
@@ -7358,13 +7309,14 @@ namespace Catch {
 | 
			
		||||
        class AssertionPrinter {
 | 
			
		||||
            void operator= ( AssertionPrinter const& );
 | 
			
		||||
        public:
 | 
			
		||||
            AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats )
 | 
			
		||||
            AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
 | 
			
		||||
            :   stream( _stream ),
 | 
			
		||||
                stats( _stats ),
 | 
			
		||||
                result( _stats.assertionResult ),
 | 
			
		||||
                colour( Colour::None ),
 | 
			
		||||
                message( result.getMessage() ),
 | 
			
		||||
                messages( _stats.infoMessages )
 | 
			
		||||
                messages( _stats.infoMessages ),
 | 
			
		||||
                printInfoMessages( _printInfoMessages )
 | 
			
		||||
            {
 | 
			
		||||
                switch( result.getResultType() ) {
 | 
			
		||||
                    case ResultWas::Ok:
 | 
			
		||||
@@ -7467,7 +7419,9 @@ namespace Catch {
 | 
			
		||||
                for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
 | 
			
		||||
                        it != itEnd;
 | 
			
		||||
                        ++it ) {
 | 
			
		||||
                    stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
 | 
			
		||||
                    // If this assertion is a warning ignore any INFO messages
 | 
			
		||||
                    if( printInfoMessages || it->type != ResultWas::Info )
 | 
			
		||||
                        stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            void printSourceInfo() const {
 | 
			
		||||
@@ -7483,6 +7437,7 @@ namespace Catch {
 | 
			
		||||
            std::string messageLabel;
 | 
			
		||||
            std::string message;
 | 
			
		||||
            std::vector<MessageInfo> messages;
 | 
			
		||||
            bool printInfoMessages;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        void lazyPrint() {
 | 
			
		||||
@@ -7568,9 +7523,14 @@ namespace Catch {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void printTotals( const Totals& totals ) {
 | 
			
		||||
            if( totals.assertions.total() == 0 ) {
 | 
			
		||||
            if( totals.testCases.total() == 0 ) {
 | 
			
		||||
                stream << "No tests ran";
 | 
			
		||||
            }
 | 
			
		||||
            else if( totals.assertions.total() == 0 ) {
 | 
			
		||||
                Colour colour( Colour::Yellow );
 | 
			
		||||
                printCounts( "test case", totals.testCases );
 | 
			
		||||
                stream << " (no assertions)";
 | 
			
		||||
            }
 | 
			
		||||
            else if( totals.assertions.failed ) {
 | 
			
		||||
                Colour colour( Colour::ResultError );
 | 
			
		||||
                printCounts( "test case", totals.testCases );
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user