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