New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
My own implementation of value parameterization (with multiple parameters) #321
Comments
Work on this feature is appreciated! Seems that there is more interest in this feature - it was first requested a few years ago: #38 Some quick thoughts:
I might be able to look into this into more depth in at least a couple of months - for now all I can do is provide some light feedback such as this. |
Haven't looked into generators yet either but, in the meantime, when looking at DOCTEST_VALUE_PARAMETERIZED_DATA in https://github.com/onqtam/doctest/blob/master/doc/markdown/parameterized-tests.md it occurs to me there's got to be a way to implement this with macro iteration and stringification to get an efficient solution without any |
@Trass3r that code was also written back when the |
Quick test using https://github.com/swansontec/map-macro/blob/master/map.h: #define STRINGIZE(arg) STRINGIZE1(arg)
#define STRINGIZE1(arg) STRINGIZE2(arg)
#define STRINGIZE2(arg) #arg
#define PARAM_TEST(type, name, ...) type name; \
static constexpr const char* s[] = {MAP_LIST(STRINGIZE, __VA_ARGS__)}; \
static constexpr type d[] = {__VA_ARGS__}; \
int i = 0; \
for (auto&& e : d) { \
SUBCASE(s[i++]) { name= e; } \
}
int foo() {
PARAM_TEST(int, data, 1, 2, 3);
return data;
} |
Playground with improved version: https://godbolt.org/z/1s6dbo Also I guess the message could be improved:
I have no clue what the "CURRENT ONE" is and how it's different. Looks like implementation details to me.
|
Just fixed the links in my original post. I haven't looked at @Trass3r's code yet. But for single-use parameterization (not many tests with the same parameters), sometimes I just write a for loop, then call
I'll have to look into whether I can simplify my macros and stop interning strings. |
Description
Value parameterization appears to be on the roadmap for doctest 2.4.0. After much difficulty, I have managed to add my own implementation of value parameterization.
pytest.mark.parameterize
(https://docs.pytest.org/en/latest/parametrize.html).range_0_3 = pytest.mark.parameterize("range_0_3", [0, 1, 2])
.@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
k, v
withk_eq_v
, and#k " = " #v
with#k_eq_v
.Usage
https://gitlab.com/nyanpasu64/exotracker-cpp/blob/b16d63e9427da8f6b9966b407cae0c874c116a58/tests/test_utils/test_parameterize.cpp
I've posted a shortened "usage example" here:
My implementation is here: https://gitlab.com/nyanpasu64/exotracker-cpp/tree/b16d63e9427da8f6b9966b407cae0c874c116a58/tests/test_utils.
My parameterization implementation is built off subcases, and if you use multiple parameters in one TEST_CASE, doctest's support for nested subcases. doctest distinguishes subcases via
(name, filename, line number)
tuples. If I construct a subcase tree, filename and line number are not unique. To ensure doctest distinguishes each subcase, for each point on the subcase tree, I pass in a uniquename
based on the stringified form of eachOPTION
between the root and the current node.The
PICK
macro takes the "leaf" subcase name (AKA the current parameter values) and logs it viaINFO()
. The subcase name will show up in failed assertions until the object created byINFO()
is destroyed (when its scope ends). My subcase name generation is a bit ugly and adds a trailing", "
after the final subcase; it's good enough for my own use case, but should be fixed before upstreaming to doctest.The macros are very fiddly and I am not confident they are free of undefined behavior.
My initial implementation had a use-after-free in
PARAMETERIZE
whereinner
(stack variable) was captured by reference, and the resulting function returned a lambda with a stale reference. This UB produced no visible signs on GCC, and std::bad_function_call on MSVC. I fixed this (https://gitlab.com/nyanpasu64/exotracker-cpp/blob/cycle-skip/tests/test_utils/parameterize.h#L52-56) by capturing[&, inner]
instead. I still don't know what happens when you captureT & parameter
via[&]
. Do you get a reference, not a reference to a reference?I developed my implementation based on doctest 2.3.4. Since then, #282 seems to have changed how SUBCASE works. My implementation seems to works fine on 2.3.6, but it was not what I studied while building my implementation.
Extra information
The text was updated successfully, but these errors were encountered: