diff --git a/docs/reference/testing.md b/docs/reference/testing.md index ea43721e..ae8a079f 100644 --- a/docs/reference/testing.md +++ b/docs/reference/testing.md @@ -103,14 +103,15 @@ namespace: -| Parameter Generator | Behavior | -| ------------------- | ---------------------------------------------------- | -| `Range(begin, end [, step])` | Yields values `{begin, begin+step, begin+step+step, ...}`. The values do not include `end`. `step` defaults to 1. | -| `Values(v1, v2, ..., vN)` | Yields values `{v1, v2, ..., vN}`. | -| `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(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. | +| Parameter Generator | Behavior | +|---------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Range(begin, end [, step])` | Yields values `{begin, begin+step, begin+step+step, ...}`. The values do not include `end`. `step` defaults to 1. | +| `Values(v1, v2, ..., vN)` | Yields values `{v1, v2, ..., vN}`. | +| `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`. | +| `CombineAs(g1, g2, ..., gN)` | Yields as `R` *n*-instances all combinations (Cartesian product) of the values generated by the given *n* generators `g1`, `g2`, ..., `gN`. | +| `ConvertGenerator(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 @@ -234,6 +235,24 @@ To overcome this problem you can specify the generated type explicitly: dangling reference because the type deduction strips off the reference and the `const`). +###### Using `CombineAs` + +If you think the code above is too complicated, and you do not want to deal +with tuples, you may want to use `CombineAs()` which works like a combination +of `Combine()` + `ConvertGenerator()` + tuple unpacking function. + +```cpp +// The fixture's parameter type. +class MyParam { + public: + MyParam(int, bool); + ... +}; + +INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite, + CombineAs(Values(1, 1.2), Bool())); +``` + ### TYPED_TEST_SUITE {#TYPED_TEST_SUITE} `TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`)` diff --git a/docs/samples.md b/docs/samples.md index dedc5909..e75323e1 100644 --- a/docs/samples.md +++ b/docs/samples.md @@ -15,7 +15,7 @@ variety of googletest features. derived fixtures. * Sample #6 demonstrates type-parameterized tests. * Sample #7 teaches the basics of value-parameterized tests. -* Sample #8 shows using `Combine()` in value-parameterized tests. +* Sample #8 shows using `Combine()` and `CombineAs()` in value-parameterized tests. * Sample #9 shows use of the listener API to modify Google Test's console output and the use of its reflection API to inspect test results. * Sample #10 shows use of the listener API to implement a primitive memory diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index 69994ee9..8beb45f5 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -61,15 +61,15 @@ #include #include "gtest/gtest-assertion-result.h" // IWYU pragma: export -#include "gtest/gtest-death-test.h" // IWYU pragma: export -#include "gtest/gtest-matchers.h" // IWYU pragma: export -#include "gtest/gtest-message.h" // IWYU pragma: export -#include "gtest/gtest-param-test.h" // IWYU pragma: export -#include "gtest/gtest-printers.h" // IWYU pragma: export -#include "gtest/gtest-test-part.h" // IWYU pragma: export -#include "gtest/gtest-typed-test.h" // IWYU pragma: export -#include "gtest/gtest_pred_impl.h" // IWYU pragma: export -#include "gtest/gtest_prod.h" // IWYU pragma: export +#include "gtest/gtest-death-test.h" // IWYU pragma: export +#include "gtest/gtest-matchers.h" // IWYU pragma: export +#include "gtest/gtest-message.h" // IWYU pragma: export +#include "gtest/gtest-param-test.h" // IWYU pragma: export +#include "gtest/gtest-printers.h" // IWYU pragma: export +#include "gtest/gtest-test-part.h" // IWYU pragma: export +#include "gtest/gtest-typed-test.h" // IWYU pragma: export +#include "gtest/gtest_pred_impl.h" // IWYU pragma: export +#include "gtest/gtest_prod.h" // IWYU pragma: export #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-string.h" @@ -1664,7 +1664,8 @@ class GTEST_API_ AssertHelper { // the GetParam() method. // // Use it with one of the parameter generator defining functions, like Range(), -// Values(), ValuesIn(), Bool(), Combine(), and ConvertGenerator(). +// Values(), ValuesIn(), Bool(), Combine(), CombineAs(), and +// ConvertGenerator(). // // class FooTest : public ::testing::TestWithParam { // protected: diff --git a/googletest/samples/sample8_unittest.cc b/googletest/samples/sample8_unittest.cc index 4df81df0..009338b0 100644 --- a/googletest/samples/sample8_unittest.cc +++ b/googletest/samples/sample8_unittest.cc @@ -81,6 +81,7 @@ class HybridPrimeTable : public PrimeTable { using ::testing::Bool; using ::testing::Combine; +using ::testing::CombineAs; using ::testing::TestWithParam; using ::testing::Values; @@ -151,4 +152,45 @@ TEST_P(PrimeTableTest, CanGetNextPrime) { INSTANTIATE_TEST_SUITE_P(MeaningfulTestParameters, PrimeTableTest, Combine(Bool(), Values(1, 10))); +// But now you look at the PrimeTableTest and you think dealing with std::tuple +// requires some boilerplate to unwrap it. You can use combined parameters of +// custom types easily with help of CombineAs(). +struct WellTypedPrimeTableTestParams { + bool force_on_the_fly; + int max_precalculated; +}; + +class WellTypedPrimeTableTest + : public TestWithParam { + protected: + void SetUp() override { + // It is possible to avoid destructuring of the std::tuple if we use struct + // as the test parameter type. + table_ = new HybridPrimeTable(GetParam().force_on_the_fly, + GetParam().max_precalculated); + } + void TearDown() override { + delete table_; + table_ = nullptr; + } + HybridPrimeTable* table_ = nullptr; +}; + +// The tests are made the same way as above +TEST_P(WellTypedPrimeTableTest, CanGetNextPrime) { + EXPECT_EQ(2, table_->GetNextPrime(0)); + EXPECT_EQ(3, table_->GetNextPrime(2)); + EXPECT_EQ(5, table_->GetNextPrime(3)); + EXPECT_EQ(7, table_->GetNextPrime(5)); + EXPECT_EQ(11, table_->GetNextPrime(7)); + EXPECT_EQ(131, table_->GetNextPrime(128)); +} + +// Here we instantiate our tests with combined parameters and straightforward +// typing. CombineAs() allows you to generate all possible combinations of +// values the same way as Combine() does, but also converts them to the desired +// type. +INSTANTIATE_TEST_SUITE_P(MeaningfulTestParameters, WellTypedPrimeTableTest, + CombineAs(Bool(), Values(1, 10))); + } // namespace