diff options
Diffstat (limited to 'docs/reference')
-rw-r--r-- | docs/reference/actions.md | 7 | ||||
-rw-r--r-- | docs/reference/matchers.md | 38 | ||||
-rw-r--r-- | docs/reference/testing.md | 99 |
3 files changed, 136 insertions, 8 deletions
diff --git a/docs/reference/actions.md b/docs/reference/actions.md index ab81a12..2ca3a9f 100644 --- a/docs/reference/actions.md +++ b/docs/reference/actions.md @@ -24,7 +24,8 @@ provided by GoogleTest. All actions are defined in the `::testing` namespace. | :--------------------------------- | :-------------------------------------- | | `Assign(&variable, value)` | Assign `value` to variable. | | `DeleteArg<N>()` | Delete the `N`-th (0-based) argument, which must be a pointer. | -| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. | +| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer` by copy-assignment. | +| `SaveArgByMove<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer` by move-assignment. | | `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. | | `SetArgReferee<N>(value)` | Assign `value` to the variable referenced by the `N`-th (0-based) argument. | | `SetArgPointee<N>(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. | @@ -47,8 +48,8 @@ functor, or lambda. | `InvokeWithoutArgs(object_pointer, &class::method)` | Invoke the method on the object, which takes no arguments. | | `InvokeArgument<N>(arg1, arg2, ..., argk)` | Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments. | -The return value of the invoked function is used as the return value of the -action. +The return value of the invoked function (except `InvokeArgument`) is used as +the return value of the action. When defining a callable to be used with `Invoke*()`, you can declare any unused parameters as `Unused`: diff --git a/docs/reference/matchers.md b/docs/reference/matchers.md index 243e3f9..8b3d140 100644 --- a/docs/reference/matchers.md +++ b/docs/reference/matchers.md @@ -42,6 +42,8 @@ Matcher | Description | `Lt(value)` | `argument < value` | | `Ne(value)` | `argument != value` | | `IsFalse()` | `argument` evaluates to `false` in a Boolean context. | +| `DistanceFrom(target, m)` | The distance between `argument` and `target` (computed by `abs(argument - target)`) matches `m`. | +| `DistanceFrom(target, get_distance, m)` | The distance between `argument` and `target` (computed by `get_distance(argument, target)`) matches `m`. | | `IsTrue()` | `argument` evaluates to `true` in a Boolean context. | | `IsNull()` | `argument` is a `NULL` pointer (raw or smart). | | `NotNull()` | `argument` is a non-null pointer (raw or smart). | @@ -109,6 +111,33 @@ use the regular expression syntax defined [here](../advanced.md#regular-expression-syntax). All of these matchers, except `ContainsRegex()` and `MatchesRegex()` work for wide strings as well. +## Exception Matchers + +| Matcher | Description | +| :---------------------------------------- | :------------------------------- | +| `Throws<E>()` | The `argument` is a callable object that, when called, throws an exception of the expected type `E`. | +| `Throws<E>(m)` | The `argument` is a callable object that, when called, throws an exception of type `E` that satisfies the matcher `m`. | +| `ThrowsMessage<E>(m)` | The `argument` is a callable object that, when called, throws an exception of type `E` with a message that satisfies the matcher `m`. | + +Examples: + +```cpp +auto argument = [] { throw std::runtime_error("error msg"); }; + +// Checks if the lambda throws a `std::runtime_error`. +EXPECT_THAT(argument, Throws<std::runtime_error>()); + +// Checks if the lambda throws a `std::runtime_error` with a specific message +// that matches "error msg". +EXPECT_THAT(argument, + Throws<std::runtime_error>(Property(&std::runtime_error::what, + Eq("error msg")))); + +// Checks if the lambda throws a `std::runtime_error` with a message that +// contains "msg". +EXPECT_THAT(argument, ThrowsMessage<std::runtime_error>(HasSubstr("msg"))); +``` + ## Container Matchers Most STL-style containers support `==`, so you can use `Eq(expected_container)` @@ -171,6 +200,11 @@ messages, you can use: | `Property(&class::property, m)` | `argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. The method `property()` must take no argument and be declared as `const`. | | `Property(property_name, &class::property, m)` | The same as the two-parameter version, but provides a better error message. +{: .callout .warning} +Warning: Don't use `Property()` against member functions that you do not own, +because taking addresses of functions is fragile and generally not part of the +contract of the function. + **Notes:** * You can use `FieldsAre()` to match any type that supports structured @@ -189,10 +223,6 @@ messages, you can use: EXPECT_THAT(s, FieldsAre(42, "aloha")); ``` -* Don't use `Property()` against member functions that you do not own, because - taking addresses of functions is fragile and generally not part of the - contract of the function. - ## Matching the Result of a Function, Functor, or Callback | Matcher | Description | diff --git a/docs/reference/testing.md b/docs/reference/testing.md index 3ed5211..ea43721 100644 --- a/docs/reference/testing.md +++ b/docs/reference/testing.md @@ -110,7 +110,7 @@ namespace: | `ValuesIn(container)` or `ValuesIn(begin,end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. | | `Bool()` | Yields sequence `{false, true}`. | | `Combine(g1, g2, ..., gN)` | Yields as `std::tuple` *n*-tuples all combinations (Cartesian product) of the values generated by the given *n* generators `g1`, `g2`, ..., `gN`. | -| `ConvertGenerator<T>(g)` | Yields values generated by generator `g`, `static_cast` to `T`. | +| `ConvertGenerator<T>(g)` or `ConvertGenerator(g, func)` | Yields values generated by generator `g`, `static_cast` from `T`. (Note: `T` might not be what you expect. See [*Using ConvertGenerator*](#using-convertgenerator) below.) The second overload uses `func` to perform the conversion. | The optional last argument *`name_generator`* is a function or functor that generates custom test name suffixes based on the test parameters. The function @@ -137,6 +137,103 @@ For more information, see See also [`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST`](#GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST). +###### Using `ConvertGenerator` + +The functions listed in the table above appear to return generators that create +values of the desired types, but this is not generally the case. Rather, they +typically return factory objects that convert to the the desired generators. +This affords some flexibility in allowing you to specify values of types that +are different from, yet implicitly convertible to, the actual parameter type +required by your fixture class. + +For example, you can do the following with a fixture that requires an `int` +parameter: + +```cpp +INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite, + testing::Values(1, 1.2)); // Yes, Values() supports heterogeneous argument types. +``` + +It might seem obvious that `1.2` — a `double` — will be converted to +an `int` but in actuality it requires some template gymnastics involving the +indirection described in the previous paragraph. + +What if your parameter type is not implicitly convertible from the generated +type but is *explicitly* convertible? There will be no automatic conversion, but +you can force it by applying `ConvertGenerator<T>`. The compiler can +automatically deduce the target type (your fixture's parameter type), but +because of the aforementioned indirection it cannot decide what the generated +type should be. You need to tell it, by providing the type `T` explicitly. Thus +`T` should not be your fixture's parameter type, but rather an intermediate type +that is supported by the factory object, and which can be `static_cast` to the +fixture's parameter type: + +```cpp +// The fixture's parameter type. +class MyParam { + public: + // Explicit converting ctor. + explicit MyParam(const std::tuple<int, bool>& t); + ... +}; + +INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite, + ConvertGenerator<std::tuple<int, bool>>(Combine(Values(0.1, 1.2), Bool()))); +``` + +In this example `Combine` supports the generation of `std::tuple<int, bool>>` +objects (even though the provided values for the first tuple element are +`double`s) and those `tuple`s get converted into `MyParam` objects by virtue of +the call to `ConvertGenerator`. + +For parameter types that are not convertible from the generated types you can +provide a callable that does the conversion. The callable accepts an object of +the generated type and returns an object of the fixture's parameter type. The +generated type can often be deduced by the compiler from the callable's call +signature so you do not usually need specify it explicitly (but see a caveat +below). + +```cpp +// The fixture's parameter type. +class MyParam { + public: + MyParam(int, bool); + ... +}; + +INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite, + ConvertGenerator(Combine(Values(1, 1.2), Bool()), + [](const std::tuple<int, bool>& t){ + const auto [i, b] = t; + return MyParam(i, b); + })); +``` + +The callable may be anything that can be used to initialize a `std::function` +with the appropriate call signature. Note the callable's return object gets +`static_cast` to the fixture's parameter type, so it does not have to be of that +exact type, only convertible to it. + +**Caveat:** Consider the following example. + +```cpp +INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite, + ConvertGenerator(Values(std::string("s")), [](std::string_view s) { ... })); +``` + +The `string` argument gets copied into the factory object returned by `Values`. +Then, because the generated type deduced from the lambda is `string_view`, the +factory object spawns a generator that holds a `string_view` referencing that +`string`. Unfortunately, by the time this generator gets invoked, the factory +object is gone and the `string_view` is dangling. + +To overcome this problem you can specify the generated type explicitly: +`ConvertGenerator<std::string>(Values(std::string("s")), [](std::string_view s) +{ ... })`. Alternatively, you can change the lambda's signature to take a +`std::string` or a `const std::string&` (the latter will not leave you with a +dangling reference because the type deduction strips off the reference and the +`const`). + ### TYPED_TEST_SUITE {#TYPED_TEST_SUITE} `TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`)` |