-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Implement Property Based Testing/ Data Generators #850
Comments
You asked me this in #558
If you meant that Catch2 is an answer to the query, I suppose that's satisfactory enough. :) |
I found myself needing this, so I made a workaround:
And it is used like so:
This is working because the assertion macros work even inside a function. The error message on where a macro failed is also useful because it shows the file/line of where the lambda is defined, rather than in my utility header. I also know that This might be useful in figuring out how to do parameterized tests. One drawback is that this doesn't allow multiple parameters, but that can be implemented through some heavier TMP, or worked around with tuples and C++17's bind expressions / An implementation of
|
Looking forward to this! Especially now that Catch2 finally surfaces. |
@Quincunx271 Your version doesn't work with SECTIONs, because each section is executed only once. @philsquared Do you have any fuzzy estimation when this feature may be available in Catch2? Is it in a ballpark of a few months or closer to a year? |
If you tell me how to do this with the catch2 branch, I will try it out on my project and contribute fixes and documentation if possible. |
@ArekPiekarz So far most of our estimates were wildly wrong, so I am going to give "when it is done". Sorry. @mlimber You can't yet. |
This is really the one remaining feature I'd love to see in Catch, and I think it would round out the framework really well in terms of the Don't Repeat Yourself (DRY) philosophy. One framework that does parametrizing well is pytest. While Python is a much different beast than C++11 (dynamically typed, monkey patching, etc), the overall API style that they use for parameterization could be helpful to look at. An example: import pytest
@pytest.mark.parametrize("test_input,expected", [
("3+5", 8),
("2+4", 6),
("6*9", 42),
])
def test_eval(test_input, expected):
assert eval(test_input) == expected Properties of this API I like:
|
Any progress here? Might also want to take a look at how GoogleTest does it: https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#how-to-write-value-parameterized-tests |
There are so many approaches to this. Not sure if this was discussed yet: Like |
I know it's been a while, but I've started looking at this again. Here's one of my test cases: TEST_CASE("Generators") {
auto i = GENERATE( values( { "a", "b", "c" } ) );
SECTION( "one" ) {
auto j = GENERATE( range( 8, 11 ) << 2 );
std::cout << "one: " << i << ", " << j << std::endl;
}
SECTION( "two" ) {
auto j = GENERATE( 3.141 << 1.379 );
std::cout << "two: " << i << ", " << j << std::endl;
}
} particular things to note:
|
@philsquared Could you make it clear what is the output of your proposed solution? |
Excellent point, @ArekPiekarz - that would help, wouldn't it - thanks :-)
|
If the generated values have overloads for the ostream operator (for example, user defined types), does this change the behavior? |
No, the
|
@johnthagen no - no change to the table examples |
Should work with any types that are copy/ movable. |
how would the report look like for such testcases? What would be the testcasenames? |
@ekrieger001 currently there is no change to the test names - but this relates to the open question, above, about capturing variable names. I'm thinking that generated variable values should appear like section names. If we capture variable names. too, we could report them as " One complication is that you might want to use the variable in a section name (as in the Cucumber example, earlier). In that case it would be a shame to have the value reported twice. Not sure there's an easy way around that. |
Hi guys, like
Thanks! |
The support is to be considered experimental, that is, the interfaces, the first party generators and helper functions can change or be removed at any point in time. Related to #850
The support is to be considered experimental, that is, the interfaces, the first party generators and helper functions can change or be removed at any point in time. Related to #850
The support is to be considered experimental, that is, the interfaces, the first party generators and helper functions can change or be removed at any point in time. Related to #850
There's currently no built-in generator that just takes something like a I'm imagining something like this: |
Phil, are there plans for the "" bits mentioned above? |
@Quincunx271 That's a good idea that sadly got lost -- I'll give it a try later. @atomgalaxy Not sure which bits you mean. |
@horenmar Sorry, github seems to have eaten the markup. I mean the printing the current value idea that @philsquared details above:
|
There have been no changes to how generators are handled in regards to stringification, so they are still anonymous until the user stringifies them manually (e.g. via |
There are some examples on issue catchorg#850 of using this feature, but they are not easily found from the documentation. Adding them here as an example makes them more findable and ensures they keep working if the API changes.
There are some examples on issue catchorg#850 of using this feature, but they are not easily found from the documentation. Adding them here as an example makes them more findable and ensures they keep working if the API changes.
There are some examples on issue catchorg#850 of using this feature, but they are not easily found from the documentation. Adding them here as an example makes them more findable and ensures they keep working if the API changes.
There are some examples on issue catchorg#850 of using this feature, but they are not easily found from the documentation. Adding them here as an example makes them more findable and ensures they keep working if the API changes.
There are some examples on issue catchorg#850 of using this feature, but they are not easily found from the documentation. Adding them here as an example makes them more findable and ensures they keep working if the API changes.
There are some examples on issue catchorg#850 of using this feature, but they are not easily found from the documentation. Adding them here as an example makes them more findable and ensures they keep working if the API changes.
There are some examples on issue #850 of using this feature, but they are not easily found from the documentation. Adding them here as an example makes them more findable and ensures they keep working if the API changes.
There are some examples on issue #850 of using this feature, but they are not easily found from the documentation. Adding them here as an example makes them more findable and ensures they keep working if the API changes.
@horenmar: Can you identify what is left on this feature request? Seems like it's potentially closable. |
@matthew-limbinar Everything that makes it actually property testing. There is data generation, but no case reduction, and no property testing loop support. |
You cannot address a particular combination that you would like to run. Lets say that I break a particular case in a large set of generated combinations.
|
This has been a long-standing promise/ point of discussion and a number of issues have been raised that amount to this, so I thought I'd write up the definite feature request to direct them all to.
There are two strands to this:
Data generators, or parametrised tests: i.e. you want to re-use the same core set of assertions with a range (possible a wide range) or different inputs - including the cross product of multiple possible inputs. In some cases you want to specifically control the inputs, in others generate it as an increasing range, or randomly. There's a variation where different types are used to parameterise. While strictly speaking that's a different feature I suspect it's all going to get tied up in them same solution, so I'll include that here too. We can always unbundle it later, if necessary.
Building on (1) is the idea of Property-Based Testing. This is a more formally structured approach to working with generated ranges of inputs and also includes features such as shrinking (where failing inputs are automatically reduced to the simplest/ smallest possible failure). The tests themselves are for properties which are usually invariants that should always hold - although sometimes an alternate (e.g. simple or reference) implementation is compared against.
Support for generators was experimentally added in the very early days of Catch, but were never progressed. In fact quite a lot of work was done in support of them, and a few alternate implementations started. The main obstacle was interaction with the
SECTION
tracking infrastructure. That code was reworked with generators in mind a couple of years ago, and a new proof-of-concept generators implementation was successfully written against it. However by that time the goal was full property-based testing and the path there seemed tortuous in a C++03 constrained context, so the effort was deferred to such a time as we could at least rebase on C++11 (and ideally would leverage C++14 and beyond to allow for things like Ranges v3 to be supported in the generators part). C++11 rebasing was decided for Catch2 - with generators/ PBT being one of the main motivators. At time of this writing a proof-of-concept implementation of Catch2 exists which consists of a mostly rewritten core. That work has paused while the "Catch Classic" backlog is tamed but will resume again soon - with generators and PBT being one of the first big features to be worked on next.I'll keep this issue open until the feature is ready so others can be closed in favour of it.
The text was updated successfully, but these errors were encountered: