[Unlock] Catch2 - C ++ testing framework (Quick Start)

Catch2

Catch2 is simple and C ++ test framework, and gtest, boost.test and CppUnit Catch2 very small compared to even if you only need one header file can easily use. In small-scale projects which can easily use it to build a testing framework, in conjunction with a simple piling frame Stub , every minute to make your test cases run up.
Today, we have to [unlock] Catch2.

Obtain

There are two ways to get Catch2:
one is the direct download headers catch.hpp - recommend using this mode, you can simply integrate into your project.
The other is to get catch2 source, https: //github.com/catchorg/Catch2.git for secondary development or learning inside the demo.

Compile

Because we want to unlock Catch2 usage by analyzing several examples Catch2 today, they are compiled with source code.

1. Get the source

git clone https://github.com/catchorg/Catch2.git

2. Turn the compiler examples
cmake -DCATCH_BUILD_EXAMPLES=ON ../

(base) frank@deepin:~/git/Catch2$ mkdir build
(base) frank@deepin:~/git/Catch2$ cd build/
(base) frank@deepin:~/git/Catch2/build$ cmake -DCATCH_BUILD_EXAMPLES=ON ../
-- The CXX compiler identification is GNU 9.2.0
-- Check for working CXX compiler: /usr/local/bin/c++
-- Check for working CXX compiler: /usr/local/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PythonInterp: /home/frank/miniconda3/bin/python (found version "3.7.4") 
-- Examples included
-- Configuring done
-- Generating done
-- Build files have been written to: /home/frank/git/Catch2/build
(base) frank@deepin:~/git/Catch2/build$ make -j4

test

Most start with a simple example.

#define CATCH_CONFIG_MAIN

#include <catch2/catch.hpp>

int Factorial( int number ) {
   return number <= 1 ? number : Factorial( number - 1 ) * number;  // fail
// return number <= 1 ? 1      : Factorial( number - 1 ) * number;  // pass
}

TEST_CASE( "Factorial of 0 is 1 (fail)", "[single-file]" ) {
    REQUIRE( Factorial(0) == 1 );
}

TEST_CASE( "Factorials of 1 and higher are computed (pass)", "[single-file]" ) {
    REQUIRE( Factorial(1) == 1 );
    REQUIRE( Factorial(2) == 2 );
    REQUIRE( Factorial(3) == 6 );
    REQUIRE( Factorial(10) == 3628800 );
}

Line 1: #define CATCH_CONFIG_MAIN, this macro defines the main function of catch2.

// Standard C/C++ main entry point
int main (int argc, char * argv[]) {
    return Catch::Session().run( argc, argv );
}

Line 3: introducing catch2 header files, here it is "<...>", which is run make install after use compiled and installed catch2, make installed in the system directory. If you use a single header file, you should use "catch2.hpp", 确认catch2.hppin your project directory or introduced it in the header file directory.

Line 5: int Factorial (int number) is measured function.

10, 14 lines: are the two test cases
REQUIRE: is asserted.

Results are as follows:


010-TestCase is a Catch v2.11.1 host application.
Run with -? for options

-------------------------------------------------------------------------------
Factorial of 0 is 1 (fail)
-------------------------------------------------------------------------------
/home/frank/git/Catch2/examples/010-TestCase.cpp:13
...............................................................................

/home/frank/git/Catch2/examples/010-TestCase.cpp:14: FAILED:
  REQUIRE( Factorial(0) == 1 )
with expansion:
  0 == 1

===============================================================================
test cases: 2 | 1 passed | 1 failed
assertions: 5 | 4 passed | 1 failed

Write your own main ()

If you do not want to use the main Catch2 provided () function, you can write your own main (). Many projects often need to write main () function, you can use the following method itself.

#define CATCH_CONFIG_RUNNER
#include "catch.hpp"

int main( int argc, char* argv[] ) {
  // global setup...

  int result = Catch::Session().run( argc, argv );

  // global clean-up...

  return result;
}

If you want to use your own command-line parameters, can be achieved:

#define CATCH_CONFIG_RUNNER
#include "catch.hpp"

int main( int argc, char* argv[] )
{
  Catch::Session session; // There must be exactly one instance
  
  int height = 0; // Some user variable you want to be able to set
  
  // Build a new parser on top of Catch's
  using namespace Catch::clara;
  auto cli 
    = session.cli() // Get Catch's composite command line parser
    | Opt( height, "height" ) // bind variable to a new option, with a hint string
        ["-g"]["--height"]    // the option names it will respond to
        ("how high?");        // description string for the help output
        
  // Now pass the new composite back to Catch so it uses that
  session.cli( cli ); 
  
  // Let Catch (using Clara) parse the command line
  int returnCode = session.applyCommandLine( argc, argv );
  if( returnCode != 0 ) // Indicates a command line error
      return returnCode;

  // if set on the command line then 'height' is now set at this point
  if( height > 0 )
      std::cout << "height: " << height << std::endl;

  return session.run();
}

SECTION

You test a class when you need to set the class as a whole property, you can use setup () and teardow () way. Test methods are based on each member of these specific properties, but often each member will have different methods of test scenarios, then you can come in handy SECTION.
That is, a set of attributes of this class of embodiments may be used TEST_CASE category, within the scope of this TEST_CASE different scenarios member SECTION method may be visible.
Explained by the following example:

#include <catch2/catch.hpp>

TEST_CASE( "vectors can be sized and resized", "[vector]" ) {

    // For each section, vector v is anew:

    std::vector<int> v( 5 );

    REQUIRE( v.size() == 5 );
    REQUIRE( v.capacity() >= 5 );

    SECTION( "resizing bigger changes size and capacity" ) {
        v.resize( 10 );

        REQUIRE( v.size() == 10 );
        REQUIRE( v.capacity() >= 10 );
    }
    SECTION( "resizing smaller changes size but not capacity" ) {
        v.resize( 0 );

        REQUIRE( v.size() == 0 );
        REQUIRE( v.capacity() >= 5 );
    }
    SECTION( "reserving bigger changes capacity but not size" ) {
        v.reserve( 10 );

        REQUIRE( v.size() == 5 );
        REQUIRE( v.capacity() >= 10 );
    }
    SECTION( "reserving smaller does not change size or capacity" ) {
        v.reserve( 0 );

        REQUIRE( v.size() == 5 );
        REQUIRE( v.capacity() >= 5 );
    }
}

: Line 7 std::vector<int> v( 5 );categories are categories (TEST_CASE) a.
The first row 13,19,25,31: a resize()method using different scenarios embodiment, a method (SECTION) Category.

Then you can use the command line argument to specify a certain SECTION execution.

(base) frank@deepin:~/git/Catch2/build/examples$ ./100-Fix-Section -c "resizing bigger changes size and capacity" 
===============================================================================
All tests passed (4 assertions in 1 test case)

BDD style

Overall and SECTION similar, but closer to natural language or behavior, BDD (Behavior Driven Development) - you can put your test cases as requirements documents.
example:

#include <catch2/catch.hpp>

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 );
            }
        }
    }
}
Released eight original articles · won praise 1 · views 161

Guess you like

Origin blog.csdn.net/xk_xx/article/details/104102831