Stream: general

Topic: Unit testing proc macros


Arlie Davis (May 06 2020 at 20:00, on Zulip):

Hello! I'm working on a proc macro, and I'm writing unit tests for it (yay for proc_macro2). I'm writing tests for my error cases, so I'm trying to scan through a TokenStream and find all invocations of compile_error!{...}. Is there any easy way to do that?

To be more specific, my proc macro tries to check as many conditions as it can in a single invocation, so it returns a TokenStream that contains numerous syn::Error objects, which get translated to compile_error!{...} invocations. This way, the developer sees all of the errors for their code at once, rather than fixing one error, recompiling, then finding the next error, etc.

So in my unit tests, I have a bunch of known-bad inputs, I run them through my macro code, and now I need to find the compile_error! invocations. I'm a bit stuck at finding an easy / attractive way to scan through a TokenStream, looking for a particular sequence of tokens, though. All of the parsing APIs are structured around matching and consuming tokens, not skipping through a TokenStream looking for a pattern.

This sounds like something someone has probably already done, so I thought I would ask.

RalfJ (May 06 2020 at 20:26, on Zulip):

I am not sure about the specific details of what you said, but when the question is "testing errors of proc macros" my first thought is https://crates.io/crates/trybuild

RalfJ (May 06 2020 at 20:27, on Zulip):

I haven't used that crate myself (not a proc macro author) but it looks pretty cool, and it's by dtolnay so I'm sure it's going to work very well

Arlie Davis (May 06 2020 at 20:27, on Zulip):

Interesting. I'll take a look.

Jake Goulding (May 06 2020 at 22:15, on Zulip):

Yes this is what I do. https://github.com/shepmaster/snafu/tree/master/compatibility-tests/compile-fail

Jake Goulding (May 06 2020 at 22:15, on Zulip):

So it’s definitely not unit tests.

Arlie Davis (May 06 2020 at 22:16, on Zulip):

I found that to be too heavy-weight: writing files to disk, spinning up the entire compiler. I found a way to quickly find the compile_error!(...) invocations in my token stream, which, for my purposes, is all I need.

pksunkara (May 07 2020 at 09:06, on Zulip):

You might want to check proc-macro-error crate. It is great instead of directly using compile_error

pksunkara (May 07 2020 at 09:06, on Zulip):

We are using it in clap and structopt

Last update: Jun 05 2020 at 23:15UTC