Rust [or Cargo?] parametrised tests?


#1

So this is something very popular in other languages and is to have parametrised tests. Having 200 lines of code for 10 tests, when all of that can be written as a list of arguments (10 lines) and one function (20 lines) is much cleaner, makes sense for code reuse and understanding of it. Also I know this can also be written as a single test, but this is not so informative as having all of them. Does anyone know if there is any such functionality currently?


#2

You could do it as a macro.


#3

Hm, does this differ significantly from writing, say,

fn do_the_test(foo: u32, bar: &str) {
     // ... test things
}

#[test]
fn abc() { do_the_test(1, "foo") }
#[test]
fn mno() { do_the_test(5, "bar") }
#[test]
fn xyz() { do_the_test(10, "baz") }

(As @steveklabnik said, a macro can be used to reduce the amount of typing required.)


#4

Unfortunately, to achieve this I need the macro to be able to concatenate identifiers together (e.g. to generate test_1, test_2, …), but currently you can not do this inside macros, due to the way that var is matched. It would in fact be nice if the macros can represent similar to the unix system and accept as well {var} in which case it would be easier to do such concatenation.


#5

EDIT: Sorry, I guess it was too late here, if you also provide the name of the test to the macro it works! Thanks anyway, got a bit educated on macros for the past few hours like this!


#6

One thing you can do here is to put tests inside of a module inside your macro. You use the base name of the test as the name of your module, and then define your tests like #[test] fn test_1() { ... } and so on within the module.


#7

Good point! That is in fact probably what the doc’s tests do. Btw do you know any easy way to generate the names test_1, test_2 … inside the macro? E.g. how to get something like the index of the current match of arguments for the test?


#8

You may want to use concat_idents! macro.


#9

Good point, but currently that doesn’t work. I researched around it and there are plenty of RFC proposal about resolving this. At the moment it works only if you pass to identifiers to it, thus you cant do concat_idents!(bar_,2). If you also want to read about it https://github.com/rust-lang/rust/issues/12249, https://github.com/rust-lang/rust/issues/12249#issuecomment-49827702, https://github.com/rust-lang/rfcs/pull/215


#10

Of cause I know it all. I just wanted to point out currently available solution, you can use now. And you can do concat_idents!(test, _1). I know it’s not exactly what you want, but you can use it for the moment, until better solution becomes available.


#11

yeah, but would not need that (e.g. you can write just test_1), and in my case you would need something like this:
concat_idents!(test, count_expressions!($($expr),*)) which sort of to count how many “parametrised” arguments you have, count them and generate a test with that number.