Task 'test' not found in project ':app'

Getting the following error trying to run the test task in my gradle java project.

Task 'test' not found in project ':app'.

* Try:
> Run gradle tasks to get a list of available tasks.
> For more on name expansion, please refer to https://docs.gradle.org/8.13/userguide/command_line_interface.html#sec:name_abbreviation in the Gradle documentation.
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
BUILD FAILED in 294ms

My build.gradle file:

import org.gradle.api.tasks.testing.logging.TestLogEvent

buildscript {
    ext {
        jdom_version = '2.0.6.1'
        junit_version = '4.13.2'
        mockito_version = '5.18.0'
    }
}

plugins {
    id 'java-library'
    id 'application'
}

repositories {
    gradlePluginPortal()
    mavenCentral()
}

version = '0.0.1'

java {
    sourceCompatibility = JavaVersion.VERSION_17
    withSourcesJar()
}

dependencies {
    implementation "org.jdom:jdom2:$jdom_version"
    implementation files ('lib/DlpUtilities-1.0.0.jar', 'lib/DiceUtilities-1.0.0.jar')
    testImplementation "junit:junit:$junit_version"
    testImplementation "org.mockito:mockito-core:$mockito_version"
}

sourceSets {
    main {
        java {
            srcDir 'app/src/main'
        }
    }

    test {
        java {
            srcDir 'app/src/test'
        }
    }
}

test {
    maxParallelForks = 1
    testLogging {
        events TestLogEvent.FAILED, TestLogEvent.SKIPPED
    }
}

Output of gradle tasks:

------------------------------------------------------------
Tasks runnable from root project '****'
------------------------------------------------------------

Application tasks
-----------------
run - Runs this project as a JVM application

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the classes of the 'main' feature.
sourcesJar - Assembles a jar archive containing the main sources.
testClasses - Assembles test classes.

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Distribution tasks
------------------
assembleDist - Assembles the main distributions
distTar - Bundles the project as a distribution.
distZip - Bundles the project as a distribution.
installDist - Installs the project as a distribution as-is.

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the 'main' feature.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project '****'.
dependencies - Displays all dependencies declared in root project '****'.
dependencyInsight - Displays the insight into a specific dependency in root project '****'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
outgoingVariants - Displays the outgoing variants of root project '****'.
projects - Displays the sub-projects of root project '****'.
properties - Displays the properties of root project '****'.
resolvableConfigurations - Displays the configurations that can be resolved in root project '****'.
tasks - Displays the tasks runnable from root project '****' (some of the displayed tasks may belong to subprojects).

Verification tasks
------------------
check - Runs all checks.
test - Runs the test suite.

Rules
-----
Pattern: clean<TaskName>: Cleans the output files of a task.
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL in 956ms
1 actionable task: 1 executed

Besides that your build script is packed with all sorts of bad-practices, can you share a build --scan URL?
If not, what exact command did you execute and where is that build.gradle file you showed?

build --scan result

build.gradle is in the project root directory.

Also, if it’s not obvious, I’m new to gradle. Could you provide more detail on the bad practices?

build --scan result

That is not a scan of the failing build, so usually useless.
It shows that you apply the plugins to the root project and that you apply no plugins to the app project though.
Which of course means there is no test task in the app project.
The question is what you do to produce the failing build.
But I guess you try to do ./gradlew app:test which of course does not make sense if there is no test task in the app project as you did not apply any plugin that would add it.

Also, if it’s not obvious, I’m new to gradle. Could you provide more detail on the bad practices?

Sure:

  • more a personal advice, switch to Kotlin DSL. By now it is the default DSL, you immediately get type-safe build scripts, actually helpful errors if you mess up the syntax, and amazingly better IDE support if you use a good IDE like IntelliJ IDEA or Android Studio
  • whenever you use ext or extra properties you should feel dirty. In “almost” your case a local variable (just def jdomVersion = '2.0.6.1 as top–level expressiono or with Kotlin DSL val jdomVersion = "2.0.6.1") would be more appropriate. “almost” your case, because for versions of dependencies and their coordinates, you should better use a version catalog in a TOML file for various reasons
  • applying java-library and application makes little sense, either you are developing a library or an application, so java and application is probably what you intended and then you can also just use application as it applies java for you anyway
  • unless you develop build-logic or a Gradle plugin, using the gradlePluginPortal() repository as dependency repository makes very little sense and just wastes time
  • declaring the mavenCentral() repo after the gradlePluginPortal() never makes sense and is just a waste of time, because the plugin portal redirects to maven central for things it does not serve itself, so if at all, MC should come first, but you should remove the plugin portal anyway
  • you should either use JVM toolchains feature to select a Java 17 toolchain instead of setting the source compatibility, or use the toolchains feature to select a newer toolchain and set the source compatibility to 17, like you have it, you could run Gradle with Java 8 and then the compilation will fail for an unknown source compatibility, with the JVM toolchains feature you decouple the version Gradle is run with from the version used to compile and run your code
  • never use files or fileTree to declare dependencies, this has various quirks, best is to not have local file dependencies at all, but if you really need some because you baught a jar that is not available in some repository or similar, at least define a flatDir repository instead and use normal coordinate dependencies
  • also more a personal recommendation, you should maybe not use an ancient JUnit version, my personal recommendation would be to use Spock instead as that is what makes testing fun again, or if you want to stick with JUnit maybe at least upgrade to Jupiter from JUnit 5
  • if you really want to use the root project but have the sources in the app subfolder for whatever reason, you should remove the app project from your settings script, it is majorly confusing that you have a Gradle project called app with the app directory as project directory, but do not use it but use the files from inside in the root project; my recommendation would be, either have the sources in the app directory, but then also use the app project, or move the sources up to the root project and delete the app project
  • setting maxParallelForks for test is pointless, that is the conventional default anyway, the sense of convention-over-configuration is, that you do not need to do configuration if the convention is fine for you