Catch introductory tutorial

Catch Tutorial (Getting Started, official document translation)

  1. Catch obtained
  2. how to use?
  3. Write test cases
  4. Test cases and test zone
  5. BDD-Style
  6. summary
  7. Parameter type of test
  8. Subsequent learning and use

Catch obtained

The easiest way is to download the latest SINGLE header Version . This header file merger of several other independent header files.

You can also use other methods to obtain Catch, such as using CMake to build compiled version of Catch, which can speed up compilation software.

Catch contain complete test, indicating that the contents of documents, etc., can download the complete Catch2 from GitHub. Catch2 official link is: http://catch-lib.net , this link will be redirected to GitHub.

How to use the Catch?

Catch is a header-only. You only need to Catch header files into the compiler can find the path to both.

The following tutorial default compiler you can find and use Catch.

* If you use precompiled form Catch, that has been compiled and generate a Catch-link library (.lib or .a file), your form should contain Catch header file like this:#include <catch2/catch.hpp>

Write test cases

Let's start with a simple example (examples / 010-TestCase.cpp). Suppose you've written a function used to calculate the factorial, is now ready to test it. (Basic principles of TDD is to write test code, regardless of where this first)

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

To keep things simple, we put all the code into a file.

#define CATCH_CONFIG_MAIN  // 当前宏强制Catch2在当前编译单元中创建 main(),这个宏只能出现在一个CPP文件中,一个项目只能有一个有效的main函数
#include "catch.hpp"

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

TEST_CASE( "Factorials are computed", "[factorial]" ) {
    REQUIRE( Factorial(1) == 1 );
    REQUIRE( Factorial(2) == 2 );
    REQUIRE( Factorial(3) == 6 );
    REQUIRE( Factorial(10) == 3628800 );
}

After the end of the compiler generates an executable file can accept parameters, please refer to the specific parameters available command-line.md. If the executable file to execute without any arguments, all of the test cases will be executed. Detailed test report is output to the terminal, the test case, the number of failed test cases, for example, the number of successful test failure and the like.

The implementation of the above executable code generation, all test cases will be passed. Really no error code? No, the above factorial function is wrong, I wrote the first version of this tutorial there Bug, thanks CTMacUser help me point out this mistake.

What this error is it? 0 factorial is how much? --0 factorial is 1 instead of 0, which is wrong at the top of the factorial function.
Factorial of 0 is 1

Let us write the above rules to the test case:

TEST_CASE( "Factorials are computed", "[factorial]" ) {
    REQUIRE( Factorial(0) == 1 );
    REQUIRE( Factorial(1) == 1 );
    REQUIRE( Factorial(2) == 2 );
    REQUIRE( Factorial(3) == 6 );
    REQUIRE( Factorial(10) == 3628800 );
}

Now test fails, Catch2 probably will output:

Example.cpp:9: FAILED:
  REQUIRE( Factorial(0) == 1 )
with expansion:
  0 == 1

Catch2 output Factorial (0) value of 0, so that we can easily find the error.

Let us amend the factorial function:

unsigned int Factorial( unsigned int number ) {
  return number > 1 ? Factorial(number-1)*number : 1;
}

Now all the test cases have passed.

Of course, the above factorial function still have many problems, such as the calculation result when a large number of overflow, we temporarily regardless.

What have we done?

Although the above test is relatively simple, but enough to show how to use the Catch2. Before going further, let explain.

  1. We define a macro that contains the header files Catch2, and then compile the compilation unit and generates an executable file that accepts parameters. Usually recommended is defined in a separate compilation unit comprising macro file header (does not contain any test code), the other contains only the header file in the test file. You can write your own main function (refer own-main.md).

  2. We macros TEST_CASEwritten test case. This macro can contain one or two parameters, a parameter is not a fixed format name of the test, another parameter comprises one or more tags (described below). Test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. Reference command-line.md For more information on the implementation of the executable file to obtain.

  3. Test names and labels are strings. (Translator's Note: This section also original text, has little effect on the use, it is not translated)

  4. We use a macro REQUIREto write test assertions. Catch2 without using discrete function represents a different assertion (e.g. greater than, less than, etc.), but directly using the result of the true value of C ++ expressions. Further Catch2 expression capture template using the left and right test expression (e.g. exp_a == exp_b), thereby displaying calculation results on both sides in the test report.

Test cases and test zone

Most of the testing framework has class-based mechanism. For example, the frame number (e.g., the JUnit) to setup()create a phase of the test objects can be used with the other embodiments, the teardown()destruction of these target stages, thereby avoiding creation and destruction of the test object (or mock objects) in each test case.

For the Catch, the use of the above conventional testing methods have certain drawbacks, for example, you can create the same number of test cases with a test object, in this case a test particle size is relatively large. (Translator's Note: other defects referred to the original)

Catch use the new way to solve the above problems, as follows:

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

    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 );
    }
}

For each SECTION, TEST_CASEwill again from TEST_CASEthe initial part of the start of execution and ignore the other SECTION. (Translator's Note: This simple text explains why, Catch use the if statement and the section seen as child nodes, each execution Catch select a child node and execute TEST_CASE time).

So far, Catch has been achieved using the above test mechanism based on class (setup & teardown) most of the testing framework.

SECTIONCan be nested to any depth, each SECTIONchild node is executed only once, a large number of nested SECTIONform a "tree", the parent node fails will no longer execute the corresponding child:

    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 );
        }
    }

BDD-Style

Catch BDD-Style may be used in the form of the test, specifically refer to: test-cases-and-sections.md, following is a simple example:

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 );
            }
        }
    }
}

Running the above test the following output:

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

to sum up

In order to ensure simplicity tutorial we put all the code in a file, this is not a good way in the actual project.

Better way is to write the following code in a separate source file, the file contains other tests Catch header files and test code. Do not repeat in the other tests included the following documents #definestatement.

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

Do not write test code in the header file!

Type parametric test

Catch2 type of support parameterized test, macro TEMPLATE_TEST_CASEand TEMPLATE_PRODUCT_TEST_CASEbehavior and TEST_CASEsimilar, but each of the specified type of test cases will be executed again.

For more information see: test-cases-and-sections.md in type-parametrised-test-cases section

Subsequent learning and use

The current document provides an overview of the Catch, Catch also pointed out some differences and other testing frameworks. Such knowledge you can already write some actual test cases.

Of course, there are many things to learn, but you only need to learn when to use those new features. Catch all the features you can find in Readme.md in.

Guess you like

Origin www.cnblogs.com/jiahu-Blog/p/11323868.html