Repository: quarkusio/quarkus
Issue: Gradle Unit Tests Don't Work Since 2.7.1

### Describe the bug

After moving to Quarkus 2.7.1 from 2.7.0 unit tests in Gradle no longer run. 

Quarkus says "No tests found" even though there tests.

### Expected behavior

Unit tests run and fail because my code is trash

### Actual behavior

Unit tests pass saying "No tests found" so I push it to prod and my boss gets angri :fearful: 

### How to Reproduce?

_No response_

### Output of `uname -a` or `ver`

_No response_

### Output of `java -version`

OpenJDK Runtime Environment 18.9 (build 11.0.14+9)

### GraalVM version (if different from Java)

_No response_

### Quarkus version or git rev

2.7.1

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

Gradle 7.3

### Additional information

_No response_

Changed files:
independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/ArtifactSources.java
integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java
independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java
devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/GradleApplicationModelBuilder.java
independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/WorkspaceModule.java
devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java
devtools/maven/src/main/java/io/quarkus/maven/QuarkusMavenWorkspaceBuilder.java
independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/DefaultWorkspaceModule.java

diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java
index 7dcd4e9de5e..c2e481183a7 100644
--- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java
+++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java
@@ -487,7 +487,7 @@ private void addLocalProject(ResolvedDependency project, GradleDevModeLauncher.B
             if (testClassesDir != null && (!testSourcePaths.isEmpty()
                     || (testResourcesOutputDir != null && Files.exists(testResourcesOutputDir)))) {
                 final String testResourcesOutputPath;
-                if (Files.exists(testResourcesOutputDir)) {
+                if (testResourcesOutputDir != null && Files.exists(testResourcesOutputDir)) {
                     testResourcesOutputPath = testResourcesOutputDir.toString();
                     if (!Files.exists(testClassesDir)) {
                         // currently classesDir can't be null and is expected to exist
diff --git a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/GradleApplicationModelBuilder.java b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/GradleApplicationModelBuilder.java
index c7ad440963b..17ecf361f7e 100644
--- a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/GradleApplicationModelBuilder.java
+++ b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/GradleApplicationModelBuilder.java
@@ -43,6 +43,7 @@
 import io.quarkus.bootstrap.model.gradle.ModelParameter;
 import io.quarkus.bootstrap.model.gradle.impl.ModelParameterImpl;
 import io.quarkus.bootstrap.resolver.AppModelResolverException;
+import io.quarkus.bootstrap.workspace.ArtifactSources;
 import io.quarkus.bootstrap.workspace.DefaultArtifactSources;
 import io.quarkus.bootstrap.workspace.DefaultSourceDir;
 import io.quarkus.bootstrap.workspace.DefaultWorkspaceModule;
@@ -139,10 +140,10 @@ public static ResolvedDependency getProjectArtifact(Project project, LaunchMode
                 .setBuildFile(project.getBuildFile().toPath());
 
         initProjectModule(project, mainModule, javaConvention.getSourceSets().findByName(SourceSet.MAIN_SOURCE_SET_NAME),
-                SourceSet.MAIN_SOURCE_SET_NAME, "");
-        if (mode.equals(LaunchMode.TEST)) {
+                SourceSet.MAIN_SOURCE_SET_NAME, ArtifactSources.MAIN);
+        if (mode.equals(LaunchMode.TEST) || mode.equals(LaunchMode.DEVELOPMENT)) {
             initProjectModule(project, mainModule, javaConvention.getSourceSets().findByName(SourceSet.TEST_SOURCE_SET_NAME),
-                    SourceSet.TEST_SOURCE_SET_NAME, "tests");
+                    SourceSet.TEST_SOURCE_SET_NAME, ArtifactSources.TEST);
         }
 
         final PathList.Builder paths = PathList.builder();
@@ -553,11 +554,6 @@ private void addSubstitutedProject(PathList.Builder paths, File projectFile) {
         }
     }
 
-    private static byte setFlag(byte flags, byte flag) {
-        flags |= flag;
-        return flags;
-    }
-
     private static boolean isFlagOn(byte walkingFlags, byte flag) {
         return (walkingFlags & flag) > 0;
     }
diff --git a/devtools/maven/src/main/java/io/quarkus/maven/QuarkusMavenWorkspaceBuilder.java b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusMavenWorkspaceBuilder.java
index 8cc651d413f..80fa1f1e896 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/QuarkusMavenWorkspaceBuilder.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusMavenWorkspaceBuilder.java
@@ -9,9 +9,9 @@
 import org.apache.maven.project.MavenProject;
 
 import io.quarkus.bootstrap.model.ApplicationModelBuilder;
+import io.quarkus.bootstrap.workspace.ArtifactSources;
 import io.quarkus.bootstrap.workspace.DefaultArtifactSources;
 import io.quarkus.bootstrap.workspace.DefaultSourceDir;
-import io.quarkus.bootstrap.workspace.DefaultWorkspaceModule;
 import io.quarkus.bootstrap.workspace.SourceDir;
 import io.quarkus.bootstrap.workspace.WorkspaceModule;
 import io.quarkus.bootstrap.workspace.WorkspaceModuleId;
@@ -38,7 +38,7 @@ static WorkspaceModule toProjectModule(MavenProject project) {
             resources.add(new DefaultSourceDir(Path.of(r.getDirectory()),
                     r.getTargetPath() == null ? classesDir : Path.of(r.getTargetPath())));
         }
-        moduleBuilder.addArtifactSources(new DefaultArtifactSources(DefaultWorkspaceModule.MAIN, sources, resources));
+        moduleBuilder.addArtifactSources(new DefaultArtifactSources(ArtifactSources.MAIN, sources, resources));
 
         final Path testClassesDir = Path.of(build.getTestOutputDirectory());
         final List<SourceDir> testSources = new ArrayList<>(project.getCompileSourceRoots().size());
@@ -48,7 +48,7 @@ static WorkspaceModule toProjectModule(MavenProject project) {
             testResources.add(new DefaultSourceDir(Path.of(r.getDirectory()),
                     r.getTargetPath() == null ? testClassesDir : Path.of(r.getTargetPath())));
         }
-        moduleBuilder.addArtifactSources(new DefaultArtifactSources(DefaultWorkspaceModule.TEST, testSources, testResources));
+        moduleBuilder.addArtifactSources(new DefaultArtifactSources(ArtifactSources.TEST, testSources, testResources));
 
         moduleBuilder.setBuildFile(project.getFile().toPath());
 
diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/ArtifactSources.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/ArtifactSources.java
index 5091476bba7..f4016b2dd50 100644
--- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/ArtifactSources.java
+++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/ArtifactSources.java
@@ -9,12 +9,15 @@
 
 public interface ArtifactSources {
 
+    String MAIN = "";
+    String TEST = "tests";
+
     static ArtifactSources main(SourceDir sources, SourceDir resources) {
-        return new DefaultArtifactSources(DefaultWorkspaceModule.MAIN, List.of(sources), List.of(resources));
+        return new DefaultArtifactSources(MAIN, List.of(sources), List.of(resources));
     }
 
     static ArtifactSources test(SourceDir sources, SourceDir resources) {
-        return new DefaultArtifactSources(DefaultWorkspaceModule.TEST, List.of(sources), List.of(resources));
+        return new DefaultArtifactSources(TEST, List.of(sources), List.of(resources));
     }
 
     String getClassifier();
diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/DefaultWorkspaceModule.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/DefaultWorkspaceModule.java
index e7ec6096fdd..5a530b56126 100644
--- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/DefaultWorkspaceModule.java
+++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/DefaultWorkspaceModule.java
@@ -17,9 +17,6 @@ public class DefaultWorkspaceModule implements WorkspaceModule, Serializable {
 
     private static final long serialVersionUID = 6906903256002107806L;
 
-    public static final String MAIN = "";
-    public static final String TEST = "tests";
-
     public static Builder builder() {
         return new DefaultWorkspaceModule().new Builder();
     }
@@ -91,12 +88,12 @@ public Builder addArtifactSources(ArtifactSources sources) {
 
         @Override
         public boolean hasMainSources() {
-            return DefaultWorkspaceModule.this.sourcesSets.containsKey(DefaultWorkspaceModule.MAIN);
+            return DefaultWorkspaceModule.this.sourcesSets.containsKey(ArtifactSources.MAIN);
         }
 
         @Override
         public boolean hasTestSources() {
-            return DefaultWorkspaceModule.this.sourcesSets.containsKey(DefaultWorkspaceModule.TEST);
+            return DefaultWorkspaceModule.this.sourcesSets.containsKey(ArtifactSources.TEST);
         }
 
         @Override
diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/WorkspaceModule.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/WorkspaceModule.java
index efe2a69638d..4e7ebda086f 100644
--- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/WorkspaceModule.java
+++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/workspace/WorkspaceModule.java
@@ -28,19 +28,19 @@ static Mutable builder() {
     ArtifactSources getSources(String classifier);
 
     default boolean hasMainSources() {
-        return hasSources(DefaultWorkspaceModule.MAIN);
+        return hasSources(ArtifactSources.MAIN);
     }
 
     default boolean hasTestSources() {
-        return hasSources(DefaultWorkspaceModule.TEST);
+        return hasSources(ArtifactSources.TEST);
     }
 
     default ArtifactSources getMainSources() {
-        return getSources(DefaultWorkspaceModule.MAIN);
+        return getSources(ArtifactSources.MAIN);
     }
 
     default ArtifactSources getTestSources() {
-        return getSources(DefaultWorkspaceModule.TEST);
+        return getSources(ArtifactSources.TEST);
     }
 
     PathCollection getBuildFiles();
diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java
index 887447a01bc..25cd99bc9c5 100644
--- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java
+++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/workspace/LocalProject.java
@@ -2,9 +2,9 @@
 
 import io.quarkus.bootstrap.resolver.maven.BootstrapMavenContext;
 import io.quarkus.bootstrap.resolver.maven.BootstrapMavenException;
+import io.quarkus.bootstrap.workspace.ArtifactSources;
 import io.quarkus.bootstrap.workspace.DefaultArtifactSources;
 import io.quarkus.bootstrap.workspace.DefaultSourceDir;
-import io.quarkus.bootstrap.workspace.DefaultWorkspaceModule;
 import io.quarkus.bootstrap.workspace.SourceDir;
 import io.quarkus.bootstrap.workspace.WorkspaceModule;
 import io.quarkus.maven.dependency.ArtifactCoords;
@@ -359,12 +359,12 @@ public WorkspaceModule toWorkspaceModule() {
         }
 
         if (!moduleBuilder.hasMainSources()) {
-            moduleBuilder.addArtifactSources(new DefaultArtifactSources(DefaultWorkspaceModule.MAIN,
+            moduleBuilder.addArtifactSources(new DefaultArtifactSources(ArtifactSources.MAIN,
                     Collections.singletonList(new DefaultSourceDir(getSourcesSourcesDir(), getClassesDir())),
                     collectMainResources(null)));
         }
         if (!moduleBuilder.hasTestSources()) {
-            moduleBuilder.addArtifactSources(new DefaultArtifactSources(DefaultWorkspaceModule.TEST,
+            moduleBuilder.addArtifactSources(new DefaultArtifactSources(ArtifactSources.TEST,
                     Collections.singletonList(
                             new DefaultSourceDir(getTestSourcesSourcesDir(), getTestClassesDir())),
                     collectTestResources(null)));
@@ -435,7 +435,7 @@ private List<String> collectChildValues(final Xpp3Dom container) {
 
     private static String getClassifier(Xpp3Dom dom, boolean test) {
         final Xpp3Dom classifier = dom.getChild("classifier");
-        return classifier == null ? (test ? DefaultWorkspaceModule.TEST : DefaultWorkspaceModule.MAIN) : classifier.getValue();
+        return classifier == null ? (test ? ArtifactSources.TEST : ArtifactSources.MAIN) : classifier.getValue();
     }
 
     private Collection<SourceDir> collectMainResources(PathFilter filter) {
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java
index 5b2e2e81559..15d1cec60f3 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java
@@ -19,24 +19,48 @@
 
 import io.quarkus.bootstrap.model.ApplicationModel;
 import io.quarkus.bootstrap.resolver.QuarkusGradleModelFactory;
+import io.quarkus.bootstrap.workspace.ArtifactSources;
 import io.quarkus.bootstrap.workspace.SourceDir;
 import io.quarkus.bootstrap.workspace.WorkspaceModule;
+import io.quarkus.maven.dependency.ResolvedDependency;
 import io.quarkus.paths.PathTree;
 
 class QuarkusModelBuilderTest {
 
     @Test
-    public void shouldLoadSimpleModuleModel() throws URISyntaxException, IOException {
+    public void shouldLoadSimpleModuleTestModel() throws URISyntaxException, IOException {
         File projectDir = getResourcesProject("builder/simple-module-project");
         final ApplicationModel quarkusModel = QuarkusGradleModelFactory.create(projectDir, "TEST");
 
         assertNotNull(quarkusModel);
         assertNotNull(quarkusModel.getApplicationModule());
         assertThat(quarkusModel.getWorkspaceModules()).isEmpty();
+
+        final ResolvedDependency appArtifact = quarkusModel.getAppArtifact();
+        assertThat(appArtifact).isNotNull();
+        assertThat(appArtifact.getWorkspaceModule()).isNotNull();
+        final ArtifactSources testSources = appArtifact.getWorkspaceModule().getTestSources();
+        assertThat(testSources).isNotNull();
+    }
+
+    @Test
+    public void shouldLoadSimpleModuleDevModel() throws URISyntaxException, IOException {
+        File projectDir = getResourcesProject("builder/simple-module-project");
+        final ApplicationModel quarkusModel = QuarkusGradleModelFactory.create(projectDir, "DEVELOPMENT");
+
+        assertNotNull(quarkusModel);
+        assertNotNull(quarkusModel.getApplicationModule());
+        assertThat(quarkusModel.getWorkspaceModules()).isEmpty();
+
+        final ResolvedDependency appArtifact = quarkusModel.getAppArtifact();
+        assertThat(appArtifact).isNotNull();
+        assertThat(appArtifact.getWorkspaceModule()).isNotNull();
+        final ArtifactSources testSources = appArtifact.getWorkspaceModule().getTestSources();
+        assertThat(testSources).isNotNull();
     }
 
     @Test
-    public void shouldLoadMultiModuleModel() throws URISyntaxException, IOException {
+    public void shouldLoadMultiModuleTestModel() throws URISyntaxException, IOException {
         File projectDir = getResourcesProject("builder/multi-module-project");
 
         final ApplicationModel quarkusModel = QuarkusGradleModelFactory.create(new File(projectDir, "application"), "TEST");
@@ -51,6 +75,53 @@ public void shouldLoadMultiModuleModel() throws URISyntaxException, IOException
         for (WorkspaceModule p : projectModules) {
             assertProjectModule(p, new File(projectDir, p.getId().getArtifactId()), false);
         }
+
+        final ResolvedDependency appArtifact = quarkusModel.getAppArtifact();
+        assertThat(appArtifact).isNotNull();
+        assertThat(appArtifact.getWorkspaceModule()).isNotNull();
+        final ArtifactSources testSources = appArtifact.getWorkspaceModule().getTestSources();
+        assertThat(testSources).isNotNull();
+        assertThat(testSources.getSourceDirs().size()).isEqualTo(1);
+        final SourceDir testSrcDir = testSources.getSourceDirs().iterator().next();
+        assertThat(testSrcDir.getDir())
+                .isEqualTo(projectDir.toPath().resolve("application").resolve("src").resolve("test").resolve("java"));
+        assertThat(testSources.getResourceDirs().size()).isEqualTo(1);
+        final SourceDir testResourcesDir = testSources.getResourceDirs().iterator().next();
+        assertThat(testResourcesDir.getDir())
+                .isEqualTo(projectDir.toPath().resolve("application").resolve("src").resolve("test").resolve("resources"));
+    }
+
+    @Test
+    public void shouldLoadMultiModuleDevModel() throws URISyntaxException, IOException {
+        File projectDir = getResourcesProject("builder/multi-module-project");
+
+        final ApplicationModel quarkusModel = QuarkusGradleModelFactory.create(new File(projectDir, "application"),
+                "DEVELOPMENT");
+
+        assertNotNull(quarkusModel);
+
+        assertProjectModule(quarkusModel.getApplicationModule(),
+                new File(projectDir, quarkusModel.getApplicationModule().getId().getArtifactId()), true);
+
+        final Collection<WorkspaceModule> projectModules = quarkusModel.getWorkspaceModules();
+        assertEquals(projectModules.size(), 1);
+        for (WorkspaceModule p : projectModules) {
+            assertProjectModule(p, new File(projectDir, p.getId().getArtifactId()), false);
+        }
+
+        final ResolvedDependency appArtifact = quarkusModel.getAppArtifact();
+        assertThat(appArtifact).isNotNull();
+        assertThat(appArtifact.getWorkspaceModule()).isNotNull();
+        final ArtifactSources testSources = appArtifact.getWorkspaceModule().getTestSources();
+        assertThat(testSources).isNotNull();
+        assertThat(testSources.getSourceDirs().size()).isEqualTo(1);
+        final SourceDir testSrcDir = testSources.getSourceDirs().iterator().next();
+        assertThat(testSrcDir.getDir())
+                .isEqualTo(projectDir.toPath().resolve("application").resolve("src").resolve("test").resolve("java"));
+        assertThat(testSources.getResourceDirs().size()).isEqualTo(1);
+        final SourceDir testResourcesDir = testSources.getResourceDirs().iterator().next();
+        assertThat(testResourcesDir.getDir())
+                .isEqualTo(projectDir.toPath().resolve("application").resolve("src").resolve("test").resolve("resources"));
     }
 
     private void assertProjectModule(WorkspaceModule projectModule, File projectDir, boolean withTests) {