assertj / assertj-assertions-generator

Custom assertions generator
http://joel-costigliola.github.io/assertj/assertj-assertions-generator.html
Apache License 2.0
61 stars 42 forks source link

Use annotation processor #110

Open sheepdreamofandroids opened 7 years ago

sheepdreamofandroids commented 7 years ago

Not an issue but an idea which probably has been looked into before...

An annotation processor which runs while testclasses are being compiled could look at annotations on the testclasses that specify for which runtime classes assertions are needed. That way you don't have to generate anything separately and all the generation knowledge is right next to the test code.

joel-costigliola commented 7 years ago

Interesting, I don't we have considered that, although if you have lot of classes to generate assertions for it can be tedious.

filiphr commented 7 years ago

I have already proposed using an annotation processor in #96. It was a different proposal than this one. I like this proposal more 😄.

@sheepdreamofandroids I don't know what you had in mind for doing this. One approach could be to have one class/interface where the assertions are configured. The configuration can be really similar to the current configuration (the options can be translated into the annotations and their values).

For example it could look like:


@AssertJGenerator(hiearchical = true, entryPointClassPackage = "com.example", generateAssertions=true, generateBddAssertions = true) // this annotation would be handled by the processor
@GeneratorPackage(value = "org.assertj.examples.rpg", excludes = {
    @GeneratorExclude(".*google.*HostSpecifier"),
    @GeneratorExclude(".*google.*Escaper.*")
}, includes = {
    @GeneratorInclude(".*DTO")
})
@GeneratorPackage("org.assertj.examples.data")
@GeneratorClass("java.nio.file.Path")
@GeneratorClass("com.fake.UnknownClass")
@GeneratorInclude("org\\.assertj\\.examples\\.rpg.*")
@GeneratorExclude(".*google.*HostSpecifier")
@GeneratorExclude(".*google.*Headers")
@Templates // more complex config here
public interface MyAssertJGeneratorConfig {
}

@joel-costigliola how would it be tedious? The setup will look like the setup of the maven plugin. The only thing that could not be configured is the targetDir as that is configured in the compiler

sheepdreamofandroids commented 7 years ago

Actually my idea was not to have one central place where you configure the generator but to collect classes from many places.

Each testmethod could have an annotation with just the one or two classes that you need right there. Or the testclass could hold an annotation for all methods. The annotation processor would combine all those into a large set of classes that are then generated at once.

Essential is that the annotation is in the test code that needs the class. You don't touch any production code. I haven't tested it yet but this should also make the code appear in the test classpath of an IDE instead of the main classpath.

I'm working on a proof of concept, but it's progressing slowly... ;-)

filiphr commented 7 years ago

That is a really good idea as well.

How would you configure the base options for the entry point and the other things which are independent of creating asserts for classes. Theoretically those options could be configured via an SPI.

If you need some help with the processor let me know. I have some experience with them.

sheepdreamofandroids commented 7 years ago

I'm very new to assertj and as far as I could tell from the cli generator, the only option is to generate flat or hierarchical assertions. I've seen that there is also the possibility to add or override templates but I'll look into that later.

At this time I only have an annotation to add classes to be generated:

@AssertFor({ Model.class, Controller.class, View.class })
public class Test {
    @AssertFor({ YetAnother.class })
    public void someTest() {
    }
}

which causes 4 assertion classes to be generated.

Unfortunately the generator isn't very comfortable in the annotation processing environment. The environment expects to be asked to create a source file while the generator expects a base directory and goes from there. I may have to fork to make them work together.