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
Better ways of dealing with snapshots in loops or helper functions #313
Comments
It could be changed so that it only complains if the assertion fails, but I'm not convinced that is a good idea. A snapshot test that should be consistent across multiple runs smells. What if the runs are not consistent and you get three different results? Particularly with |
I guess I don't feel the same way. This is the only kind of snapshot that
The idea is that once Update/clarification: This is not super-important, but to add on to my last sentence: ideally, the first time However, it would be OK if |
For instance to detect all potential runs of a snapshot test it would require functionality that rust-test just does not provide. I'm not sure what it can realistically do in that scenario. |
I'm not sure I understand your concern, forgive me if I'm missing some obvious flaw in my design. I wasn't suggesting that By the way, I'm not trying to present this as a particularly serious or urgent problem. In the one case this was a problem for me, it was just a small annoyance. The workaround of replacing Also, thanks for making |
@ilyagr the proposal if I understand it correctly is that Jinja collects all (or at least two) snapshots that diverge:
The way inline snapshots work is that they append themselves to a pending snapshots log file where the latest ones one. Previous snapshots cannot be distinguished form previous runs or previous invocations in the same run reliably due to lack of hooks in rust-test.
In a way there is an easier solution I believe which is to have the helper add to a |
You are correct about my proposal. I didn't quite understand your explanation (I didn't experience
That's a good point. I don't actually know how to use snapshots that are HashSet-s or vectors, as opposed to strings, but I'll look at the docs. If that's easy enough, I like this approach. Update: On second thought, using a HashSet would lose the information of which call to the function failed. Using a Vector is just a more complicated version of returning the string from the helper function and asserting on that. (In my case, I wanted to avoid that because the error message had little to do with the purpose of a function, but it wouldn't be the end of the world either). Thanks again! |
A hypothetical solution would be to explicitly handle this. eg such a system could be added: insta::multi_snapshots! {
helper(1);
helper(2);
} Since we control the scope, the end of the |
I was wondering about the exact same thing while rewriting our test suite with more insta everywhere. At meilisearch, we use insta a lot to ensure we return the expected error message. Since both routes are supposed to work similarly, we apply the same asserts. #[actix_rt::test]
async fn search_unexisting_index() {
let server = Server::new().await;
let index = server.index("test");
let expected_response = json!({
"message": "Index `test` not found.",
"code": "index_not_found",
"type": "invalid_request",
"link": "https://docs.meilisearch.com/errors#index_not_found"
});
index
.search(json!({"q": "hello"}), |response, code| {
assert_eq!(code, 404);
assert_eq!(response, expected_response);
})
.await;
} And what I would like to write instead; #[actix_rt::test]
async fn search_unexisting_index() {
let server = Server::new().await;
let index = server.index("test");
index
.search(json!({"q": "hello"}), |response, code| {
assert_display_snapshot!(code, @"404");
assert_json_snapshot!(response, @"...");
})
.await;
} |
If that functionality were to be added, would this be an acceptable way to express that desire? #[actix_rt::test]
async fn search_unexisting_index() {
let server = Server::new().await;
let index = server.index("test");
insta::multi_snapshots! {
index
.search(json!({"q": "hello"}), |response, code| {
assert_display_snapshot!(code, @"404");
assert_json_snapshot!(response, @"...");
})
.await;
}
} Or alternatively probably that could be a setting: #[actix_rt::test]
async fn search_unexisting_index() {
let server = Server::new().await;
let index = server.index("test");
let mut settings = Settings::clone_current();
settings.set_multi_snapshot(true);
let _guard = settings.bind_to_scope()
index
.search(json!({"q": "hello"}), |response, code| {
assert_display_snapshot!(code, @"404");
assert_json_snapshot!(response, @"...");
})
.await;
} |
Yep definitely, both would work, I just wanted to share another "real" use case we encountered while using insta 😁 |
For what it's worth, I just ran into the same issue. I have two tests that I want to be clear have the same first part of setup but a different conclusion. So, I had them both call the same helper to start out with, to show the difference is only toward the end. However, that helper setup uses |
I want to implement this but I cannot come up with a good name for the macro that explains what it's actually doing. Here some options: Option Ainsta::assert_perfect_duplicates! {
for x in (0..10).step_by(2) {
let is_even = x % 2 == 0;
insta::assert_debug_snapshot!(is_even, @"true");
}
} Option Binsta::assert_multi_snapshots! {
for x in (0..10).step_by(2) {
let is_even = x % 2 == 0;
insta::assert_debug_snapshot!(is_even, @"true");
}
} Option Cinsta::multi_snapshots! {
for x in (0..10).step_by(2) {
let is_even = x % 2 == 0;
insta::assert_debug_snapshot!(is_even, @"true");
}
} Option Dinsta::allow_matching_duplicates! {
for x in (0..10).step_by(2) {
let is_even = x % 2 == 0;
insta::assert_debug_snapshot!(is_even, @"true");
}
} Option Einsta::allow_duplicates! {
for x in (0..10).step_by(2) {
let is_even = x % 2 == 0;
insta::assert_debug_snapshot!(is_even, @"true");
}
} |
Personally, I would say that since this macro isn't doing the I'm not a fan of the word Hope that helps 😂 |
I'm a bit conflicted on the naming still. I at the moment think prefer |
Naive question — would using the existing |
It maintains a stack of previous run results. I would not want to abuse the settings for that since they are not necessarily scope bound. |
|
@ilyagr reentrancy means that a function can be invoked again before it finished. This is not what is happening here so I think the name would not be correct. |
|
I have a few thoughts about 745b45b.
Firstly, the error message saying
Insta does not allow inline snapshot assertions in loops
isn't quite right. The new panic can happen without any loops:Here's how I encountered this situation.
Secondly, a friendlier behavior would be to not have an error merely because the snapshot at the same line was encountered twice. Rather,
insta
could error out only if , when this snapshot is repeatedly encountered,insta
sees a different string compared to it than it saw before. Then, tests that were correct before wouldn't start failing because of upgradinginsta
.In other words, the example above would have
insta
abort and report an error. But if we replacehelper
withthe test should be valid. Ideally (but not if it's too much trouble to implement), if
mission_report()
is modified to report "Complete success" both times,insta
could handle that kind of change and allow the user to use the normalcargo insta review
functionality to fix the test.It's hard for me to tell how much effort it would take to make this happen. Is this the kind of thing you would accept a PR for? (No promises at this point, though) Do you think it's not worth the effort?
The text was updated successfully, but these errors were encountered: