Testing proc macros


#1

How would I make tests for a custom derive?


#2

Rust test cases are designed to test correct behaviour, not structural compliance.

A custom derive implements given traits for provided structures. Tests are used to make sure these implementations behave correctly. This boils down to testing trait behaviour through interaction with a dummy struct that derives the mentioned traits.
Code and tests must always compile, so compiling itself is a structural test.


#3

Ok, so i can only test success cases, but not test if a custom derive fails (make sure it fails for some cases)?


#4

To do this in the past I’ve split the logic out of the proc-macro crate into a normal crate. Then you can write tests using quote! to produce an example bit of code to pass to the implementation. For example here’s a test that’s checking for an error if the attribute is applied to an enum instead of a struct.

This is quite an old (abandoned) proc-macro so the logic is all just done as an &str -> Result<String> function, I’m not sure if it’s possible to import the proc_macro crate into a normal crate so that you could do this as a TokenStream -> Result<TokenStream> function and use the more modern APIs.

EDIT: I should note that I already had the separation between proc-macro crate and logic crate for other reasons (the proc-macro used itself in its own definition…), I just noticed that I could re-use it for testing as well when adding that. I’m not sure if the overhead of multiple crates is worth it for most cases.

The other thing you could look into is complietest_rs, this allows you to write Rust source files and check the errors actually coming from the compiler for them. I haven’t tried it out for proc-macros, but I don’t see why it wouldn’t work for them.


#5

Ok, I’ll try that, thanks!


#6

Here’s an example from proptest_derive: https://github.com/AltSysrq/proptest/tree/proptest-derive/proptest-derive (check the tests/ folder).


#7

Thanks that was very helpful