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