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
Allow awaiting futures automatically in parameters #170
Conversation
First of all thanks too much for your effort and ... WOW it's a lot of work!!!! Please be patient.... I've not too much time to look into it. I hope to find some times in the next days (1 or 2 weeks ... sorry :() |
No problem, I know what it is to manage an open source project, no pressure :) Initially I just did it for fun and to discover how macro worked in Rust, then it become something more serious ^^ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, maybe I've lost the big plan... What's the real difference between #[future]
and#[future_awit]
? Just add the await call on fixture resolution?
In this case I guess that the code cold be really simplified and I handle this case as a special case of the first one. (I'm writing this by mobile)
Anyway... follow my review of this code.
Great and huge work!!! But we should fix some things to this draft
- Rebase it to main
- Avoid to mix render and parse: parse should add all information to enable render to write the correct code
- Use
Resolver
composability instead of add new field toArgumentResolver
struct - Add tests for catching error in parsing
- Find a way to don't spread
async_args
in all function signature
Thanks again for your effort. I'll try to support your work by doing my best and give you a fast (I hope) feedback.
rstest_macros/src/parse/future.rs
Outdated
Group(_) | ImplTrait(_) | Infer(_) | Macro(_) | Never(_) | Slice(_) | ||
| TraitObject(_) | Verbatim(_) => { | ||
self.errors.push(syn::Error::new_spanned( | ||
ty.into_token_stream(), | ||
"This type cannot be awaited.".to_owned(), | ||
)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about extract this check in a function and use matches!()
?
rstest_macros/src/render/mod.rs
Outdated
.map(|case| case.render(&test, &attributes)) | ||
.map(|case| case.render(&test, &await_args, &attributes)) | ||
.collect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm quite sure that we can avoid to spread await_args
in all functions signature... I think that test
and attributes
can contains all information. I we start to add a new argument for each feature the code will become a mess (more than it already is :) ).
Thanks for the review! I'm a bit busy too, I'll try to apply the changes this weekend.
Yes, that's it, just the await call. The rationale is that if I need to write #[rstest]
async fn it_can_return_its_ip(#[future] client: Client) {
let client = client.await;
client.doThis();
client.doThat();
} I might as well write #[rstest]
async fn it_can_return_its_ip() {
let client = make_client().await;
client.doThis();
client.doThat();
} and not use rstest at all, it's the same number of lines.
I can't remember exactly but I couldn't reuse the |
OOOHHHHH!!! You're right ... also the code that handle Ok, we can start to include your version and after refactor them. In parsing stage we should just identify the attributes, |
4c5814d
to
cbac743
Compare
Ok, I managed to work something out! I need some feedback though. As usual, no hurry :) When you have some time, I'd like you to check the commit 51d626c . This is something I needed to use a resolver to add the await expression. I moved the decision to use a fixture in the parsing stage instead of the end of the injection stage. There is one downside to this, it's that the Then, you can just review the Also note that all integration tests pass, but I broke a lot of unit tests, so no need to review in too much detail, this is far from the final version. And I didn't apply all the changes you requested yet ^^ |
Ok, I spend all the morning to try to recover from my mind what I was doing in my code 😄. I also started to write something new from scratch.... #[derive(PartialEq, Debug, Clone)]
pub(crate) enum AsyncType {
Plain(Type),
Await(Type),
} Ok, it's simple to add it to We need an exit strategy: Forget all my comments about don't mix parser and render phases and also for resolver part. I'll merge your PR when you'll fix all comments and later I'll open a ticket for refactor all code and remove this mess. I'm sorry .... we're paying an hack that I did to introduce |
This avoids the fallback in inject.rs where we inject a default fixture if we couldn't find any attribute describing the parameter. We need this because when we go through that fallback, no resolver is called and we can't inject code to handle #[await_future].
cbac743
to
eac60cf
Compare
eac60cf
to
8530852
Compare
Here it is. I kept the last version with the resolvers, fixed all the tests and addressed your comments. I didn't write new unit tests since you're going to refactor and they'll probably be more pain to refactor.
That's an option, but it will change a lot of code, much like my first solution. I let you experiment with that and be the judge ^^ Tell me if you need some more changes before merging :) Also, if I can add one more controversial opinion: I know I'm the one who chose it but |
Also I don't like this name and I don't like that is another kind of |
I just started using your library for integration tests and I absolutely do not understand for what cases we need to always manually |
At worst, I would prefer a single modifier before the test_case function instead of writing For example: #[rstest]
#[await_futures]
async fn it_can_return_its_ip(
#[future] di_container: RootModule,
#[future] client: Client,
) {
let foo: Box<dyn FooPort> = di_container.provide().unwrap();
client.doThis();
client.doThat();
foo.execute();
} |
There are a lot of cases where the code that you should test take a non awaited future bu just a future: fixture can provide this kind of references and Ok... |
Or maybe we're approaching this problem from the wrong side. What if we add a macro for
|
I think this approach would also solve issue #141 |
I close this PR in favor to #186 |
Thank you for your work on this! <3 |
Async fixture are kind of hard to use currently as reported in #157 . This PR adds a syntax to make tests with async fixtures easier to write.
Before:
After:
This PR is ready code-wise, but it still lacks some tests and documentation. I wanted to get feedback for this approach before going further, please tell me what you think :)