Skip to content
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

Best practice unit test module structure #108

Merged

Conversation

kabutz
Copy link
Contributor

@kabutz kabutz commented Sep 27, 2021

Following what I believe are "best practices" for JPMS, I believe that the unit tests should not be in a module, and should be in the same package as what is being tested. Furthermore, the module-info.java file should not refer to test modules. I base this belief that this is the best practice on the OpenJDK/jdk not exporting to test modules in any of their modules. I also base it on my own experience in creating the framework for my Dynamic Proxies in Java book samples. When I created those sample, I had input from folks from Jetty and Maven, and I believe that my structure is a better approach than what is currently used in gctoolkit. Lastly, I looked at the structure of Jetty this morning, particularly the server module and that also follows the same structure I am proposing here.

Note that the module-info.java files now only export to other non-test modules in our project. Where we need to access non-exported packages, we do so with an added --add-opens inside the pom.xml file. This also follows best practices of the Jetty project and my book samples.

@karianna karianna added the enhancement New feature or request label Sep 27, 2021
@karianna karianna requested review from dsgrieve, brunoborges and a user September 27, 2021 10:27
Copy link
Member

@dsgrieve dsgrieve left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a hard time finding an example or documentation on the best practice here. I followed an example from https://github.com/apache/maven-surefire.git under maven-multimodule-project-with-jpms.

@kabutz
Copy link
Contributor Author

kabutz commented Sep 27, 2021

Yes, we spent an inordinate amount of time trying to get this right for my book. I'm still not sure that my suggestion is the best way, but it feels so, based on the projects that I know have spent a lot of time thinking about this (Jetty & OpenJDK)

@karianna
Copy link
Member

The code changes are fine at the micro level. It does feel a little bit awkward to have to introduce --opens syntax just to run tests though. I wonder if we should run this via jigsaw-dev for their opinion?

@kabutz
Copy link
Contributor Author

kabutz commented Sep 27, 2021

That's why we have --add-opens etc.

@dsgrieve
Copy link
Member

It does feel a little bit awkward to have to introduce --opens syntax just to run tests though

Not as awkward as the code it replaces.

@kabutz
Copy link
Contributor Author

kabutz commented Sep 27, 2021

The thinking is basically that we don't want our shipped modules (api, parser, etc.) to have any reference to our tests. The tests are external to that code and once we have built and tested our modules, then we ship them without the tests (of course).

@ghost
Copy link

ghost commented Sep 27, 2021

The testing practice followed was best practice a few years ago.. following guidelines set by Kevlin Henny. The thinking is that by not having tests in the same package you are forced to test via public APIs. This tends to keep the tests away from implementation details which may offer an impedance to refactoring.. and indeed, this is something that we have experienced in the past, having large number of tests need to be modified and expediency just having them removed with the idea that they would be added back in... I'd call that a failure. Thing is, the tests that seemed to have survived were those that didn't muck around with the internals where as those that did died in the todo: list.

As it stands, there is nothing that I know of in the code base that is there specifically to support tests. Well, I lie... sort of, there is one method that I use to help debug the parse rules.. but it's not used in testing.

I'm all for removing test code from modules.. however, I think we should have a deeper think about all the implications backing away from tests in a different package structure.

@kabutz
Copy link
Contributor Author

kabutz commented Sep 27, 2021 via email

@karianna
Copy link
Member

I couldn't quite tell from @kirk-microsoft message whether he thinks this PR is OK, but I'm assuming since there's no requested changes in his review we can land this.

@karianna karianna merged commit 3250252 into microsoft:main Sep 28, 2021
@ghost
Copy link

ghost commented Sep 28, 2021

Sorry but I didn't ok this PR.. I was trying to sort out what best practices are and how they might be applied to this project given that there is a difference of opinion here.

@karianna
Copy link
Member

Ah apologies - let's use the Review and Request changes option next time so there's a clear -1 on the PR until we're aligned.

@brunoborges
Copy link
Member

@kirk-microsoft I just tested the project on VS Code, IntelliJ, and Eclipse, and I was finally able to have a proper developer environment with full IDE capabilities. This was only possible with this change.

I believe this is the right path and wouldn't go back to any of the previous structures.

PS: only NetBeans still has some problems.

@ghost
Copy link

ghost commented Sep 28, 2021 via email

@brunoborges
Copy link
Member

@kirk-microsoft what is the problem of having tests in the same package of the classes they are testing?

@kabutz
Copy link
Contributor Author

kabutz commented Sep 28, 2021

I don't know of any well-known OSS project out there that has the test classes in separate packages. Just checked now and that's even how JUnit does it:

https://github.com/junit-team/junit5/tree/main/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine
https://github.com/junit-team/junit5/tree/main/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine

It's how Jetty is set up.

Spring Boot seems to do the same:

https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate
https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate

I would not be surprised if you heard Kevlin Henney say this in a talk - he's a great philosopher and speaker. And he is correct on quite a few levels. However, by doing things differently we are going against what everyone else is doing, causing confusion with the IDEs and tools out there. We certainly shouldn't have our core modules export their packages to the test modules, that feels wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants