diff --git a/docs/command-line.md b/docs/command-line.md
index ce489070..e641de47 100644
--- a/docs/command-line.md
+++ b/docs/command-line.md
@@ -12,7 +12,7 @@ Note that options are described according to the following pattern:
` -e, --nothrow`
` -h, -?, --help`
-
+
## Specifying which tests to run
<test-spec> ...@@ -49,7 +49,7 @@ A series of tags form an AND expression wheras a comma seperated sequence forms This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]` - + ## Choosing a reporter to use
-r, --reporter <reporter>@@ -64,21 +64,21 @@ The bundled reporters are: The JUnit reporter is an xml format that follows the structure of the JUnit XML Report ANT task, as consumed by a number of third-party tools, including Continuous Integration servers such as Hudson. If not otherwise needed, the standard XML reporter is preferred as this is a streaming reporter, whereas the Junit reporter needs to hold all its results until the end so it can write the overall results into attributes of the root node. - + ## Breaking into the debugger
-b, --breakIn some IDEs (currently XCode and Visual Studio) it is possible for Catch to break into the debugger on a test failure. This can be very helpful during debug sessions - especially when there is more than one path through a particular test. In addition to the command line option, ensure you have built your code with the DEBUG preprocessor symbol - + ## Showing results for successful tests
-s, --successUsually you only want to see reporting for failed tests. Sometimes it's useful to see *all* the output (especially when you don't trust that that test you just added worked first time!). To see successul, as well as failing, test results just pass this option. Note that each reporter may treat this option differently. The Junit reporter, for example, logs all results regardless. - + ## Aborting after a certain number of failures
-a, --abort -x, --abortx [<failure threshold>] @@ -89,7 +89,7 @@ If a ```CHECK``` assertion fails even the current test case is not aborted. Sometimes this results in a flood of failure messages and you'd rather just see the first few. Specifying ```-a``` or ```--abort``` on its own will abort the whole test run on the first failed assertion of any kind. Use ```-x``` or ```--abortx``` followed by a number to abort after that number of assertion failures. - + ## Listing available tests, tags or reporters-l, --list-tests -t, --list-tags @@ -103,20 +103,20 @@ If one or more test-specs have been supplied too then only the matching tests wi ```--list-reporters``` lists the available reporters. - + ## Sending output to a file-o, --out <filename>Use this option to send all output to a file. By default output is sent to stdout (note that uses of stdout and stderr *from within test cases* are redirected and included in the report - so even stderr will effectively end up on stdout). - + ## Naming a test run-n, --name <name for test run>If a name is supplied it will be used by the reporter to provide an overall name for the test run. This can be useful if you are sending to a file, for example, and need to distinguish different test runs - either from different Catch executables or runs of the same executable with different options. If not supplied the name is defaulted to the name of the executable. - + ## Eliding assertions expected to throw-e, --nothrow@@ -126,7 +126,7 @@ These can be a nuisance in certain debugging environments that may break when ex When running with this option any throw checking assertions are skipped so as not to contribute additional noise. Be careful if this affects the behaviour of subsequent tests. - + ## Usage-h, -?, --helpdiff --git a/docs/test-cases-and-sections.md b/docs/test-cases-and-sections.md new file mode 100644 index 00000000..39dc7e82 --- /dev/null +++ b/docs/test-cases-and-sections.md @@ -0,0 +1,30 @@ +# Test cases and sections + +While Catch fully supports the traditional, *x*Unit, style of class-based fixtures containing test case methods this is not the preferred style. + +Instead Catch provides a powerful mechanism for nesting test case sections within a test case. For a more detailed discussion see the [tutorial](tutorial.md#testCasesAndSections). + +Test cases and sections are very easy to use in practice: + +**TEST_CASE(** _test name_ [**,** _tags_ ] **)** +**SECTION(** _section name_ **)** + +_test name_ and _section name_ are free form, quoted, strings. The optional _tags_ argument is a quoted string containing one or more tags enclosed in square brackets. Tags are discussed below. Test names must be unique within the Catch executable. + +For examples see the [Tutorial](tutorial.md) + +## Tags + +-{placeholder for documentation of tags}- + +## User Story/ BDD-style test cases + +In addition to Catch's take on the classic style of test cases, Catch supports an alternative syntax that allow tests to be written as "executable specifications" (one of the early goals of BDD). This set of macros map on to TEST_CASEs and SECTIONs, with a little internal support to make them smoother to work with. + +**SCENARIO(** _scenario name_ ) + +-{placeholder for given-when-then docs}- + +--- + +[Home](../README.md) \ No newline at end of file diff --git a/docs/tutorial.md b/docs/tutorial.md index 24857081..12f838d9 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -87,10 +87,61 @@ 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 two arguments - a hierarchical test name (forward slash separated, by convention) and a free-form description. The test name should be unique - and ideally will logically group related tests together like folders in a file system. You can run sets of tests by specifying a wildcarded test name. -3. The name and description 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. +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 Test cases and Sections, 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. + +## 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). + +While Catch fully supports this way of working there are a few problems with the approach. In particular the way your code must be split up, and the blunt granularity (you can only have one setup/ teardown pair across a set of methods - sometimes you want slightly different setup in each method - or you may want several levels of setup. We'll revisit that concept shortly and, hopefully, make it clearer). It was problems like these that led James Newkirk, who led the team that built NUnit, to start again from scratch and build xUnit). + +Catch takes a different approach (to both NUnut and xUnit) that is a more natural fit for C++ and the C family of languages. This is best explaned through an example: + +```c++ +TEST_CASE( "vectors can be sized and resized", "[vector]" ) { + + std::vectorv( 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``` the ```TEST_CASE``` is executed from the start - so as we enter each section we know that size is 5 and capacity is at least 5. We enforced those requirements with the ```REQUIRE```s at the top level so we can be confident in them. +This works because the ```SECTION``` macro contains an if statement that calls back into Catch to see if the section should be executed. One leaf section is executed on each run through a ```TEST_CASE```. The other sections are skipped. Next time through the next section is executed, and so on until no new sections are encountered. + +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}- + ## Next steps For more specific information see the [Reference pages](reference-index.md)