-
Notifications
You must be signed in to change notification settings - Fork 20
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
[feature suggestion / idea] parameterized tests ? #111
Comments
Also: https://github.com/google/patrick which seems to do this for |
In principle, it shouldn't be a problem to create a fork of
Feel free to explore if you've got the time. Otherwise, I might be able to put something together soon. Best wishes, |
Thanks so much for piping in here!
R being R, and allowing for so many tricks computing on the table of which @markvanderloo has deployed quite a few I have the feeling that is both something we all should do, and could. Then again, takes someone with an itch to scratch and a bit of time... I'll let @markvanderloo answer the mechanics. There is something truly clever going on which is describes in a pair of papers at his arXiv page. Maybe we find a way to "shimmy" the implicit loop in there. |
I think that you can already do much of this with little effort because it is possible to program over tests. For example, you can already do this in addOne <- function(n) n + 1
inputs <- 1:5
outputs <- 2:6
mapply(expect_equal, addOne(inputs), outputs) Or, you can explicitly loop over tests, as for example in this test file from the But I might be misunderstanding the question here, please tell me if I do. |
Yes, I also explicitly loop in some test scripts. I think the idea would be to show / document / help. The |
Yes, it would be a good idea to document 'parameterized tests' in the vignette. Perhaps in the 'tinytest by example' vignette. (I also should move those to |
One problem with the $ tt.r -f param.R ## tt.r is a simple littler wrapper, using run_test_file with -f file
param.R....................... 5 tests 1 fails 52ms
----- FAILED[data]: param.R<8--8>
call| mapply(expect_equal, addOne(inputs), outputs)
call| -->c("(function (...) ", "{", " out <- fun(...)", " if (inherits(out, \"tinytest\")) {", " attr(out, \"file\") <- env$file", " attr(out, \"fst\") <- env$fst", " attr(out, \"lst\") <- env$lst", " attr(out, \"call\") <- env$call", " attr(out, \"trace\") <- sys.calls()", " if (!is.na(out) && env$lst - env$fst >= 3) ", " attr(out, \"call\") <- match.call(fun)", " env$add(out)", " attr(out, \"env\") <- env", " }", " out", "})(dots[[1]][[5]], dots[[2]][[5]])"
call| )
diff| Expected 'NA', got '5'
Showing 1 out of 5 results: 1 fails, 4 passes (52ms)
$ Maybe that's an auxiliary problem and one that's not easy to avoid |
Next question: Michael has a nice and compact 'trigonometrics' example on the README.md of ll <- list(alist("sin", sin(pi/4), 1/sqrt(2)),
alist("cos", cos(pi/4), 1/sqrt(2)),
alist("tan", tan(pi/4), 1)) A very pedestrian of way of working with this is looping and evaluating:
which gets us the usual aggregation: $ tt.r -f /tmp/ttdo-prs/param.R
param.R....................... 3 tests OK 41ms
All ok, 3 results (41ms)
$ Can you think of simpler / nicer / better way to unrool that we could 'hide' in a helper function (to which we may pass the predicate, |
This is pretty similar to the interface in with_parameters <- function(assertions, ..., .calling_env = parent.frame()) {
params <- list(...)
results <- vector("list", length(params))
for (i in seq_along(params)) {
results[[i]] <- eval(
substitute(assertions),
params[[i]],
enclos = .calling_env
)
}
results
}
x <- 3
with_parameters(
{
tinytest::expect_equal(expr, numeric_value, info = info)
},
sin = list(expr = sin(pi / 4) - x, numeric_value = 1 / sqrt(2) - 3, info = "sin"),
cos = list(expr = cos(pi / 4), numeric_value = 1 / sqrt(2), info = "cos"),
tan = list(expr = tan(pi / 4), numeric_value = 1, info = "tan")
)
#> [[1]]
#> ----- PASSED : <-->
#> call| eval(substitute(assertions), params[[i]], enclos = .calling_env)
#> info| sin
#>
#> [[2]]
#> ----- PASSED : <-->
#> call| eval(substitute(assertions), params[[i]], enclos = .calling_env)
#> info| cos
#>
#> [[3]]
#> ----- PASSED : <-->
#> call| eval(substitute(assertions), params[[i]], enclos = .calling_env)
#> info| tan This doesn't play especially nice with the current expression parsing in tinytest, but I think it's something that could be fixed. |
I should putz around more "on the language". I suspected I could help myself with a reference to |
Would it be useful to borrow some ideas from other languages and test framework to automagically loop over sets of parameters? Python's has this 'parametrize' for pytest which has been pointed out as useful. Is that something we can borrow?
The text was updated successfully, but these errors were encountered: