Maven
  1. Maven
  2. MNG-3559

Multi-Module Project: module that depends on sibling test jar cannot execute test-compile without install of sibling first

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 2.0.8, 2.0.9
    • Fix Version/s: 3.2.3
    • Component/s: Bootstrap & Build
    • Labels:
      None
    • Complexity:
      Intermediate
    • Testcase included:
      yes
    • Number of attachments :
      4

      Description

      We have project with a few sibling modules:

      • Project
        ----moduleA
        +-- /src/main/java (Common Code)
        +-- /src/test/java (Common Test Framework)
        ----moduleB
        ----moduleC
        +-- /src/main/java (Production Code, depends on moduleA Common code)
        +-- /src/test/java (Production Test Framework, depends on moduleA Common Test Framework)

      I dont think there is anything wrong with this project in concept. moduleC's "main" code depends son moduleA's "main" code, and moduleC's test code depends on moduleA's test code.

      This works if I run 'mvn install', but for rapid development, we often run single unit tests and need to be able to run "mvn test" from the top level project, which fails.

      For an example, download the attached project and run "mvn test" from the trunk directory. It will fail with the error pasted below. Then, run "mvn install" and everything works ok. We should be able to run our unit tests without having to install first.

      [INFO] ------------------------------------------------------------------------
      [ERROR] BUILD ERROR
      [INFO] ------------------------------------------------------------------------
      [INFO] Failed to resolve artifact.

      Missing:
      ----------
      1) com.kiva.demoPom:moduleA:test-jar:tests:0.0.1-SNAPSHOT

      Try downloading the file manually from the project website.

      Then, install it using the command:
      mvn install:install-file -DgroupId=com.kiva.demoPom -DartifactId=moduleA -Dversion=0.0.1-SNAPSHOT -Dclassifier=tests -Dpackaging=test-jar -Dfile=/path/to/file

      Alternatively, if you host your own repository you can deploy the file there:
      mvn deploy:deploy-file -DgroupId=com.kiva.demoPom -DartifactId=moduleA -Dversion=0.0.1-SNAPSHOT -Dclassifier=tests -Dpackaging=test-jar -Dfile=/path/to/file -Durl=[url] -DrepositoryId=[id]

      Path to dependency:
      1) com.kiva.demoPom:moduleC:jar:0.0.1-SNAPSHOT
      2) com.kiva.demoPom:moduleA:test-jar:tests:0.0.1-SNAPSHOT

      ----------
      1 required artifact is missing.

      for artifact:
      com.kiva.demoPom:moduleC:jar:0.0.1-SNAPSHOT

      from the specified remote repositories:
      central (http://repo1.maven.org/maven2)

      1. ActiveProjectTestJar-2.0.9.patch
        2 kB
        Joshua Pollak
      2. ActiveProjectTestJar-r2-2.0.9.patch
        3 kB
        Joshua Pollak
      3. demoPom.tgz
        68 kB
        Joshua Pollak
      4. demoPom-0.0.2-src.tgz
        68 kB
        Joshua Pollak

        Issue Links

          Activity

          Hide
          Joshua Pollak added a comment -

          Here is a patch I think fixes the problem. The patch is against 2.0.9.

          The problem turns out to be that MavenProject.replaceWithActiveArtifact() doesn't recognize the "test-jar" dependency as a active project artifact because moduleA's packaging is "jar", not "test-jar" (obviously). What I've done is added a specific case to check if the dependency is of type test-jar and the scope of the dependency is "test". If so, the patch creates and ActiveProjectArtifact() and replaces the File inside with:

          new File(ref.getModelBuild().getTestOutputDirectory())

          This doesn't allow production code to depend on another modules test's, but it does allow sibling tests to depend on another modules tests.

          Show
          Joshua Pollak added a comment - Here is a patch I think fixes the problem. The patch is against 2.0.9. The problem turns out to be that MavenProject.replaceWithActiveArtifact() doesn't recognize the "test-jar" dependency as a active project artifact because moduleA's packaging is "jar", not "test-jar" (obviously). What I've done is added a specific case to check if the dependency is of type test-jar and the scope of the dependency is "test". If so, the patch creates and ActiveProjectArtifact() and replaces the File inside with: new File(ref.getModelBuild().getTestOutputDirectory()) This doesn't allow production code to depend on another modules test's, but it does allow sibling tests to depend on another modules tests.
          Hide
          Joshua Pollak added a comment - - edited

          The previous patch prevented the moduleC's production code from depending on moduleA's production code. This patch corrects this problem and replaces (obsoletes) the previous patch.

          Show
          Joshua Pollak added a comment - - edited The previous patch prevented the moduleC's production code from depending on moduleA's production code. This patch corrects this problem and replaces (obsoletes) the previous patch.
          Hide
          Joshua Pollak added a comment -

          This updated demo project demonstrates the problem the -r2 patch corrects, and replaces the previously uploaded demoPom project.

          Show
          Joshua Pollak added a comment - This updated demo project demonstrates the problem the -r2 patch corrects, and replaces the previously uploaded demoPom project.
          Hide
          Nicholas Williams added a comment -

          [Copied my comment from MEXEC-91, which I suspect might actually be the same bug as this.]
          Is there any update on this? It has been a year since anyone said anything about it. I have what I thought was a simple project structure, but I cannot get it to build:

          core
          licensor-base depends on core:jar (compile) and core:test-jar (test)
          licensor-ui-core depends on core:jar (compile), licensor-base:jar (compile) and core:test-jar (test)
          licensor-ui-cli depends on core:jar (compile), licensor-base:jar (compile), licensor-ui-core:jar (compile) and core:test-jar (test)
          licensor-ui-desktop depends on core:jar (compile), licensor-base:jar (compile), licensor-ui-core:jar (compile) and core:test-jar (test)

          [ERROR] Failed to execute goal on project licensor-base: Could not resolve dependencies for project net.nicholaswilliams.java.licensing:licensor-base:jar:1.1.0-SNAPSHOT: Could not find artifact net.nicholaswilliams.java.licensing:core:jar:tests:1.1.0-SNAPSHOT -> [Help 1]

          I have tried the following executions:

          Original:

          mvn package javadoc:aggregate-jar assembly:single checksum:files

          Added to original:

          mvn test-compile package javadoc:aggregate-jar assembly:single checksum:files

          Tried simpler (skip Javadoc, assembly, checksum):

          mvn test-compile package

          Tried compile only:

          mvn test-compile

          Only the last one worked. But this is useless, because I need to test, package, document, assemble and checksum my projects.

          IMO, this is NOT a feature request, it is a serious bug.

          Can somebody provide some insight? Is there some workaround I have not tried yet?
          [End copy from MEXEC-91]

          I noticed that a patch was provided for this bug five years ago, and the bug was last updated two and a half years ago. Why has this not been fixed yet???

          Update: I also tried running `mvn test-compile` and THEN immediately running `mvn package javadoc:aggregate-jar assembly:single checksum:files` after that succeeds, but the second step fails with the same message.

          Show
          Nicholas Williams added a comment - [Copied my comment from MEXEC-91, which I suspect might actually be the same bug as this.] Is there any update on this? It has been a year since anyone said anything about it. I have what I thought was a simple project structure, but I cannot get it to build: core licensor-base depends on core:jar (compile) and core:test-jar (test) licensor-ui-core depends on core:jar (compile), licensor-base:jar (compile) and core:test-jar (test) licensor-ui-cli depends on core:jar (compile), licensor-base:jar (compile), licensor-ui-core:jar (compile) and core:test-jar (test) licensor-ui-desktop depends on core:jar (compile), licensor-base:jar (compile), licensor-ui-core:jar (compile) and core:test-jar (test) [ERROR] Failed to execute goal on project licensor-base: Could not resolve dependencies for project net.nicholaswilliams.java.licensing:licensor-base:jar:1.1.0-SNAPSHOT: Could not find artifact net.nicholaswilliams.java.licensing:core:jar:tests:1.1.0-SNAPSHOT -> [Help 1] I have tried the following executions: Original: mvn package javadoc:aggregate-jar assembly:single checksum:files Added to original: mvn test-compile package javadoc:aggregate-jar assembly:single checksum:files Tried simpler (skip Javadoc, assembly, checksum): mvn test-compile package Tried compile only: mvn test-compile Only the last one worked. But this is useless, because I need to test, package, document, assemble and checksum my projects. IMO, this is NOT a feature request, it is a serious bug. Can somebody provide some insight? Is there some workaround I have not tried yet? [End copy from MEXEC-91] I noticed that a patch was provided for this bug five years ago, and the bug was last updated two and a half years ago. Why has this not been fixed yet??? Update: I also tried running `mvn test-compile` and THEN immediately running `mvn package javadoc:aggregate-jar assembly:single checksum:files` after that succeeds, but the second step fails with the same message.
          Hide
          Robert Scholte added a comment -

          @Nicholas: the short answer is https://twitter.com/jasondillon/status/290628687202754561, the more detailed answer is http://rfscholte.wordpress.com/2010/09/05/how-to-create-a-jar-containing-reusableabstract-testclasses-with-maven/
          To me this issue is more of an anti-pattern and the blog explains why: you will loose dependency management. The patch assumes a way too simple usecase.

          Show
          Robert Scholte added a comment - @Nicholas: the short answer is https://twitter.com/jasondillon/status/290628687202754561 , the more detailed answer is http://rfscholte.wordpress.com/2010/09/05/how-to-create-a-jar-containing-reusableabstract-testclasses-with-maven/ To me this issue is more of an anti-pattern and the blog explains why: you will loose dependency management. The patch assumes a way too simple usecase.
          Hide
          Nicholas Williams added a comment -

          I don't understand how I'm losing dependency management here. I have a set of "helper" classes used to make certain testing operations easier in my project. These cannot be abstracted out of the project, because they depend on the project core. However, the tests for the project core rely on them for the testing. Putting them in the compile scope of a separate module would introduce a circular dependency; therefore, that is automatically not an option.

          What I want seems pretty simple. I want the test code for one module to be able to depend on the test code from another module. If we can make the main code from one module depend on the test code from another module, it seems we should be able to do the same thing for test code. And, indeed, there's this magical feature in Maven that is supposed to be able to do that, except it's broken.

          Whether or not this is a good feature in Maven is an entirely different discussion that I'd be happy to have with you. But the fact of the matter is that the feature exists in Maven and is documented as serving this purpose (http://maven.apache.org/guides/mini/guide-attached-tests.html). In fact, the documentation even says:

          Note that previous editions of this guide suggested to use <classifier>tests</classifier> instead of <type>test-jar</type>. While this currently works for some cases, it does not properly work during a reactor build of the test JAR module and any consumer if a lifecycle phase prior to install is invoked.

          The problem, however, is that not even <type> works during a reactor build of the test JAR module and any consumer. Not unless you run test-compile. But Even if you run test-compile, if you invoke subsequent goals it stil doesn't work.

          If it's not a good feature, then maybe it should be removed. I would argue that it needs to be fixed.

          Show
          Nicholas Williams added a comment - I don't understand how I'm losing dependency management here. I have a set of "helper" classes used to make certain testing operations easier in my project. These cannot be abstracted out of the project, because they depend on the project core. However, the tests for the project core rely on them for the testing. Putting them in the compile scope of a separate module would introduce a circular dependency; therefore, that is automatically not an option. What I want seems pretty simple. I want the test code for one module to be able to depend on the test code from another module. If we can make the main code from one module depend on the test code from another module, it seems we should be able to do the same thing for test code. And, indeed, there's this magical feature in Maven that is supposed to be able to do that, except it's broken. Whether or not this is a good feature in Maven is an entirely different discussion that I'd be happy to have with you. But the fact of the matter is that the feature exists in Maven and is documented as serving this purpose ( http://maven.apache.org/guides/mini/guide-attached-tests.html ). In fact, the documentation even says: Note that previous editions of this guide suggested to use <classifier>tests</classifier> instead of <type>test-jar</type>. While this currently works for some cases, it does not properly work during a reactor build of the test JAR module and any consumer if a lifecycle phase prior to install is invoked. The problem, however, is that not even <type> works during a reactor build of the test JAR module and any consumer. Not unless you run test-compile. But Even if you run test-compile, if you invoke subsequent goals it stil doesn't work. If it's not a good feature, then maybe it should be removed. I would argue that it needs to be fixed.
          Hide
          Nicholas Williams added a comment -

          My problem, it would appear, is that I now have the following options:

          • Duplicate the shared classes in every module.
          • Have a separate module that contains all of the unit tests for all modules; do not put unit tests in the modules they belong in.
          • Don't use modules.
          • Don't use Maven.

          I don't really like my choices here. :-/

          Show
          Nicholas Williams added a comment - My problem, it would appear, is that I now have the following options: Duplicate the shared classes in every module. Have a separate module that contains all of the unit tests for all modules; do not put unit tests in the modules they belong in. Don't use modules. Don't use Maven. I don't really like my choices here. :-/
          Hide
          David H Vree added a comment -

          Wish there was a better workaround for this. As it is I just want with Nicholas's option #1 and duplicated the shared classes in every module. What a pain.

          Show
          David H Vree added a comment - Wish there was a better workaround for this. As it is I just want with Nicholas's option #1 and duplicated the shared classes in every module. What a pain.
          Hide
          Jason van Zyl added a comment -

          I fixed this in an implementation of the ReactorReader for a customer so this one migth be relatively easy to fix.

          Show
          Jason van Zyl added a comment - I fixed this in an implementation of the ReactorReader for a customer so this one migth be relatively easy to fix.

            People

            • Assignee:
              Jason van Zyl
              Reporter:
              Joshua Pollak
            • Votes:
              20 Vote for this issue
              Watchers:
              24 Start watching this issue

              Dates

              • Created:
                Updated: