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