I needed to create some tests for my project where a function call would return a vector, and I needed to verify the right items are coming back in that vector (and the right # of items). This was littering my code with really long assert_eq!()
calls.
To make matters worse there were some times when I did not really want to do a full equality check but I actually needed to do a pattern match, including saving off one of the properties. The use case was I needed to check that the 2nd event matched Event::Abc { id: _, ref name} if name == &"hi"
while at the same time saving off the id
value to use in the next step in the check (but I don't want to hardcode what the expected ID value is because it can be anything, it just needs to work for the next stage of the test).
So I spent all day working on (and probably bothered a lot of helpful people on IRC) the following macro to solve this: Shared via Rust Playground ยท GitHub
This allows me to do:
fn main() {
let test1 = Test::Value1 { v1: 5, v2: "test".to_string() };
let test2 = Test::Value1 { v1: 8, v2: "test2".to_string() };
let test3 = Test::Value1 { v1: 8, v2: "test3".to_string() };
let test4 = Test::Value1 { v1: 8, v2: "test4".to_string() };
let vector = vec![test2, test1, test3, test4];
let result;
assert_vec_match!(vector,
Test::Value1 { v1: _, ref v2} if v2 == "test2",
Test::Value1 { v1, ref v2} if v2 == "test" => {result = v1},
Test::Value1 { v1: 8, v2: _} => (),
Test::Value1 { v1: 8, v2: _},
);
println!("{}", result); // prints 5
}
The only issue with this is there is a lot of redundancy in that macro. Each format a pattern may be in one of the 4 formats (as shown in the example) but they can be in any order.
Is there any good way to consolidate the logic in the macro at all?