userver: userver/utest/parameter_names.hpp Source File
Loading...
Searching...
No Matches
parameter_names.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utest/parameter_names.hpp
4/// @brief @copybrief utest::PrintTestName
5/// @ingroup userver_universal
6
7#include <string>
8#include <tuple>
9#include <type_traits>
10
11#include <gtest/gtest.h>
12
13#include <userver/utils/meta_light.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace utest {
18
19namespace impl {
20
21template <typename ParamType>
22std::string TestParamToString(const ParamType& param) {
23 if constexpr (requires { ParamType::test_name; }) {
24 static_assert(std::is_same_v<std::string, decltype(param.test_name)>, "Test name should be a string");
25 return param.test_name;
26 } else {
27 return ::testing::PrintToString(param);
28 }
29}
30
31template <typename... Args>
32std::string TestTupleParamToString(const std::tuple<Args...>& params_tuple) {
33 static_assert((sizeof...(Args) != 0), "Test parameters should have at least one dimension");
34 // Underscore is the only valid non-alphanumeric character that can be used
35 // as a separator, see IsValidParamName in gtest-param-util.h.
36 return std::apply(
37 [](const auto& first, const auto&... rest) {
38 return (TestParamToString(first) + ... + ("_" + TestParamToString(rest)));
39 },
40 params_tuple
41 );
42}
43
44} // namespace impl
45
46// clang-format off
47
48/// @ingroup userver_utest
49///
50/// @brief Test name printer for parameterized tests written in gtest.
51///
52/// ## Example usage:
53///
54/// ### Singly-parameterized test.
55///
56/// Special-purpose field `test_name` of type `std::string` may be used for describing test input in a human-readable form.
57///
58/// @snippet universal/utest/src/utest/parameter_names_test.cpp PrintTestName Example Usage - Singly-Parameterized Test
59///
60/// This should result in printing `test_name` field as a test name during test run.
61///
62/// ```
63/// ParametrizedTest.BasicTest/First
64/// ParametrizedTest.BasicTest/Second
65/// ParametrizedTest.BasicTest/Third
66/// ```
67///
68/// ### Another option to override a test name.
69///
70/// Helper class `::utest::PrintTestName()` also supports conventional `PrintTo` override.
71/// However field `test_name` of a parameters' structure has a higher priority for overriding a test name than a `PrintTo` function.
72///
73/// @snippet universal/utest/src/utest/parameter_names_test.cpp PrintTestName Example Usage - Override PrintTo
74///
75/// ### Doubly-parametrized test.
76///
77/// In case you have more than one dimension for possible test parameters,
78/// you can also use `::utest::PrintTestName()` to combine names for the dimensions of every parameter.
79/// You can mix methods for overriding test names for the dimension of every parameter independently.
80///
81/// @snippet universal/utest/src/utest/parameter_names_test.cpp PrintTestName Example Usage - Doubly-Parameterized Test
82///
83/// This should result in printing concatenated test names for all combined test parameters dimensions.
84///
85/// ```
86/// DoublyParametrizedTest.BasicTest/First_CustomFirst
87/// DoublyParametrizedTest.BasicTest/First_CustomSecond
88/// DoublyParametrizedTest.BasicTest/Second_CustomFirst
89/// DoublyParametrizedTest.BasicTest/Second_CustomSecond
90/// DoublyParametrizedTest.BasicTest/Third_CustomFirst
91/// DoublyParametrizedTest.BasicTest/Third_CustomSecond
92/// ```
93
94// clang-format on
95struct PrintTestName final {
96 template <typename ParamType>
97 std::string operator()(const testing::TestParamInfo<ParamType>& info) const {
98 if constexpr (requires { std::tuple_size<ParamType>::value; }) {
99 return impl::TestTupleParamToString(info.param);
100 } else {
101 return impl::TestParamToString(info.param);
102 }
103 }
104};
105
106} // namespace utest
107
108USERVER_NAMESPACE_END