Skip to content

Conversation

@aepfli
Copy link

@aepfli aepfli commented Sep 9, 2022

Sorry i simply started experimenting out of curiosity regarding #2760 , and I want to share what I tried and what worked and did not work for such modular tests. Please just close this pr, if you do not think it is fitting. Although if you think, this needs just polishing, let me know, i can adapt and help to make it better.

This pr works, but only has one test - so theoretically it is usable :)

BUT... i wanted to experiment a little bit more, and maybe make the original unit tests work within this modular module.

test-jar approach

I tried adding following to the assertj-core to generate a test jar

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>test-jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

and tried to apply it as a dependency within my modular test. Sadly this ended up with a lot of package errors

errors
[ERROR] the unnamed module reads package org.assertj.core.api from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.api.filter from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.api.iterable from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.api.junit.jupiter from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.api.recursive.comparison from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.condition from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.configuration from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.data from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.description from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.error from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.error.future from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.error.uri from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.extractor from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.groups from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.matcher from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.presentation from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.util from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.util.diff from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.util.diff.myers from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.util.introspection from both assertj.core and org.assertj.core
[ERROR] the unnamed module reads package org.assertj.core.util.xml from both assertj.core and org.assertj.core
[ERROR] module assertj.core reads package org.assertj.core.util from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.util.introspection from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.util.diff from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.util.diff.myers from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.util.xml from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.groups from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.configuration from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.condition from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.description from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.extractor from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.api from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.api.filter from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.api.junit.jupiter from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.api.iterable from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.api.recursive.comparison from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.matcher from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.data from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.error from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.error.future from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.error.uri from both org.assertj.core and assertj.core
[ERROR] module assertj.core reads package org.assertj.core.presentation from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.util from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.util.introspection from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.util.diff from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.util.diff.myers from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.util.xml from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.groups from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.configuration from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.condition from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.description from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.extractor from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.api from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.api.filter from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.api.junit.jupiter from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.api.iterable from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.api.recursive.comparison from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.matcher from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.data from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.error from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.error.future from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.error.uri from both org.assertj.core and assertj.core
[ERROR] module org.hamcrest reads package org.assertj.core.presentation from both org.assertj.core and assertj.core
[INFO] 63 errors 
[INFO] -------------------------------------------------------------

additional source directory

Then i thought maybe extracting them into target/test-classes could also do the trick - sadly not
Then i thought maybe i could simply add the test source directory to the modularTest module, but this somehow needed more than 5 minutes and did not finish, so i also stepped away from this approach.

Adding an own module for testing in the modular world.
@aepfli aepfli marked this pull request as draft September 9, 2022 08:49
@aepfli aepfli changed the title Testing Module Testing with Maven for #2760 Draft: Testing Module Testing with Maven for #2760 Sep 9, 2022
@scordio
Copy link
Member

scordio commented Sep 9, 2022

Hi Simon, thanks for the PR! This probably overlaps with #2759, which is already stable from the Maven perspective but:

@scordio
Copy link
Member

scordio commented Sep 9, 2022

make the original unit tests work within this modular module.

This is a cool point I didn't consider yet: it would be much better to re-run our entire test suite in the modular world instead of adding dedicated tests for it.

@aepfli
Copy link
Author

aepfli commented Sep 9, 2022

Hi Simon, thanks for the PR! This probably overlaps with #2759

yes it does, sorry I did not see that one :)

Lacks a test case for #2760 and the Pioneer issue - I'm still looking at your branch and thinking how to reproduce the issue, maybe I'll steal the whole PioneerAnnotationUtils as a test target

I added one specially for this case within this pr.

This is a cool point I didn't consider yet: it would be much better to re-run our entire test suite in the modular world instead of adding dedicated tests for it.

maybe somebody has suggestions for this error the unnamed module reads package org.assertj.core.api from both assertj.core and org.assertj.core and how we can easily fix it, but i have no clue who i can ask here. This error only applies as soon as i add the test-jar as a dependency. Most likely because it does not have a module-info.java but on the other hand, i also did not find a way to produce it with a module-info.java . As i am hooked i will experiment a little bit more. and see what i might discover.

@scordio
Copy link
Member

scordio commented Sep 9, 2022

maybe somebody has suggestions for this error the unnamed module reads package org.assertj.core.api from both assertj.core and org.assertj.core and how we can easily fix it, but i have no clue who i can ask here.

Are you getting this error in the IDE or with Maven?

I'll try to play with it as well this evening.

@aepfli
Copy link
Author

aepfli commented Sep 9, 2022

I pushed the changes to use a test-jar. i get this error with maven during testCompile of the modular-testing module

Copy link
Member

@scordio scordio left a comment

Choose a reason for hiding this comment

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

I'm still checking what could be done in this area. Below are just a few comments but feel free to ignore them until it's clear where we want to go.

About these errors:

the unnamed module reads package org.assertj.core.api from both assertj.core and org.assertj.core

I believe this is caused by these three actors:

  1. The assertj-core multi-release JAR with this module-info
  2. The assertj-core test JAR that has no module descriptor so it becomes an automatic module
  3. The assertj-core-moduletest with the module-info under src/test/java

I assume the unnamed module in the error message is 3, while assertj.core corresponds to 2 and org.assertj.core corresponds to 1.

I believe the assertj-core test JAR should be created with a descriptor, but right now I believe that having a test JAR would be a backup option (see #2347 for the rationale).

I'm trying another strategy with the branch of #2759:

  • Setting the project.build.testSourceDirectory to ../../../assertj-core/src/test/java
  • Defining an additional execution of the maven-compiler-plugin where the module-info under src/test/java gets compiled

This should work when running the maven-surefire-plugin under the assertj-core-module-path module (I'm fixing now the necessary declarations in the local module-info).

Also, it requires a bit of duplication for all the test scoped dependencies of assertj-core and the assertj-core/src/test/java folder is detected by IntelliJ as a test source root for two separate modules, leading to weird IDE errors about imports.

I'm still 100% sure it's the direction we want to take, might be OK but I still need to digest the idea 🙂

Lastly, we'll soon start the development of AssertJ 4 which will drop the multi-release configuration, hopefully simplifying the overall test setup, so we might stay with a basic setup in the 3.x branch to be used ad-hoc for specific investigations.

Comment on lines 318 to 328
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
Copy link
Member

Choose a reason for hiding this comment

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

In general, we'd like to avoid the creation of the test jar, see #2347. If we are really forced to have it, we should prevent its deployment to the Nexus.

Comment on lines 17 to 19
<maven.compiler.release>${java.version}</maven.compiler.release>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
Copy link
Member

Choose a reason for hiding this comment

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

java.version should be enough, all of them are set in assertj-parent

Comment on lines 25 to 44
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M7</version>
<!-- <configuration>-->
<!-- <dependenciesToScan>-->
<!-- <dependency>org.assertj:assertj-core:test-jar</dependency>-->
<!-- </dependenciesToScan>-->
<!-- </configuration>-->

</plugin>
Copy link
Member

Choose a reason for hiding this comment

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

Unless there is a special config for the two plugins, declaration is not necessary as we get already the latest versions from assertj-parent

<bannedDependencies>
<!-- <bannedDependencies>
<includes>
<include>*:*:*:jar:test</include>
Copy link
Member

@scordio scordio Sep 10, 2022

Choose a reason for hiding this comment

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

If we would need to use a test-jar dependency, we could relax this condition while keeping the enforced scope:

Suggested change
<include>*:*:*:jar:test</include>
<include>*:*:*:*:test</include>

@aepfli
Copy link
Author

aepfli commented Sep 10, 2022

I tried the path you want to use, I did not manage to get it to compile. Not sure why but test compile took ages ;)

I even abused the approach from the mutli release jar and patched the jar with a module-info out of the Modulartest module. But as said I had some kind of compile issues, as it tool ages and I was too impatient to wait more than 5 minutes.

I will also try to experiment some more in the evening. Looks really interesting.

Setting the project.build.testSourceDirectory to ../../../assertj-core/src/test/java

Be aware to also set the test resources ;)

@scordio
Copy link
Member

scordio commented Sep 10, 2022

I've pushed my WIP changes in e138460, I'll try to finalize them later in the day.

@aepfli aepfli force-pushed the testing-maven-moduletesting branch from aa9301f to bd71c07 Compare September 10, 2022 14:46
@aepfli
Copy link
Author

aepfli commented Sep 10, 2022

i used part of your code, and I figured out it is just hamcrest - by adding the optional junit dependency and excluding hamcrest, I made it work locally :) with your testdirectory approach. i will check later again, but it looks promising


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
            <exclusions>
                <!-- This has to be excluded because it's subjecting the code to the incorrect version of certain hamcrest packages. -->
                <exclusion>
                    <groupId>org.hamcrest</groupId>
                    <artifactId>hamcrest-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

There are tests failing currently due to missing resources, which I will check later

@aepfli aepfli force-pushed the testing-maven-moduletesting branch from 461a993 to dd3a2db Compare September 10, 2022 19:27
@aepfli
Copy link
Author

aepfli commented Sep 10, 2022

please do not be overwhelmed by my recent changes

I discovered an issue with all files which have been accessed during the test, as the path was always module specific and not loaded via resources, i adapted the tests to do so (most likely there is a good reason for that, i just thought a fast replace in the IDE could do the trick to see which errors are left)

now i am left with 6 errors, and one of those is my test for those methods. strangely enough there has not been a lot of other detections regarding package violations, except the deepdifference tests.

[ERROR] Errors: 
[ERROR]   RecursiveAssertionDriver_JavaClassLibraryRecursionTest.should_assert_over_and_recurse_into_jcl_classes_when_configured_to_recurse_into_JCL:45 » Introspection
[ERROR]   DeepDifference_Test.testBigDecimals:80->assertHaveNoDifferences:327->assertHaveNoDifferences:331 » Introspection
[ERROR]   DeepDifference_Test.testEquivalentCollections:249->assertHaveNoDifferences:327->assertHaveNoDifferences:331 » Introspection
[ERROR]   DeepDifference_Test.testSameObject:66->assertHaveNoDifferences:327->assertHaveNoDifferences:331 » Introspection
[ERROR]   DeepDifference_Test.testUnorderedCollection:140->assertHaveNoDifferences:327->assertHaveNoDifferences:331 » Introspection
[ERROR]   IterableAssert_extracting_Test.should_allow_assertions_on_property_values_extracted_from_given_iterable:36 » IllegalState
[INFO] 
[ERROR] Tests run: 18673, Failures: 0, Errors: 6, Skipped: 16

I know, those changes are now a lot and blew up the whole PR, and they might not be desired, this was again just exploration and fact finding. So please if you do not see those fitting the need, ignore them :), but we would need to find another solution for the tests and the resources. (most likely also doable by switching the working directory)

.. and I always have to run a clean, before I can run the modular tests

@scordio
Copy link
Member

scordio commented Sep 10, 2022

Thank you so much for taking the time to do this already!

I'm using your attempts as inspiration and I'm also trying to take a slightly different direction to avoid the weird IDE behavior I was mentioning: instead of setting testSourceDirectory and testResources, I keep the configuration in the corresponding plugins so the IDE doesn't get influenced (066cc49).

I'm not sure how much time I'll have in the next days but I'll continue on this topic as soon as I can.

@aepfli
Copy link
Author

aepfli commented Sep 12, 2022

if I can support you somehow further, or if there is anything I should test/do, etc. please let me know :) I am glad if I can help you.

@aepfli
Copy link
Author

aepfli commented Sep 12, 2022

just something which popped to my head, instead of recompiling the tests why not just reuse the compiled files?

            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <groupId>org.apache.maven.plugins</groupId>
                <executions>
                    <execution>
                        <id>copy-resource-one</id>
                        <phase>generate-test-resources</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>

                        <configuration>
                            <outputDirectory>${project.build.testOutputDirectory}</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>../../assertj-core/target/test-classes</directory>
                                    <includes>
                                        <include>**/*</include>
                                    </includes>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

this way the test is executed faster, and it should actually not cause any problems? see 1d1af6f

Downsides:

  • it might not be clear to the user that he has to also run testCompile for assertj-core if he changes something
  • it is not 100% clear what is happening and what dependencies we do have on the build
  • awareness of packages, and that there might be an overwrite of a test if package and class name are an exact match within modulartest and assertj-core

Ups:

  • pretty fast, as we don't need to recompile 4k files
  • no IDE issues etc.
  • moduletests will be executed quiet fast, if you only adapt those, as the recompile will be much much faster

@aepfli
Copy link
Author

aepfli commented Sep 22, 2022

also an interesting twitter thread regarding this topic: https://twitter.com/lukaseder/status/1389236184472301583

@scordio scordio added theme: module system An issue related to the Java module system type: enhancement labels Sep 22, 2022
@scordio
Copy link
Member

scordio commented Sep 22, 2022

also an interesting twitter thread regarding this topic: https://twitter.com/lukaseder/status/1389236184472301583

Thanks! I think I've seen it last year and I agree especially with:

Instead, there can be proper test library modules. Modules that are only used by other test modules, and will never be shipped to users.

Perhaps, it's time to let go of the "old" Maven directory layouts?

which is somehow the strategy I'm trying to use with #2424.

It might be we'll go with the approach of moving all the tests to a separate module. I need to digest the idea a bit more 🙂

@scordio
Copy link
Member

scordio commented Sep 23, 2022

One more thought: I'm not really thrilled to move tests to a separate module-based artifact until IDEA-301032 is fixed, otherwise it will be an unpleasant experience for contributors using IDEA (myself included 😄).

@scordio
Copy link
Member

scordio commented Feb 16, 2025

Superseded by #3771.

@scordio scordio closed this Feb 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

theme: module system An issue related to the Java module system

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants