I am new to gradle+java. I a use Intellij to debug a sophisticated unit test case on an algorithm. The problem is every time after I click the 'debug' button, it takes long time (~2min) to start my test case, and from the log as following, it seems gradle is checking dependencies first and there are hundreds of them. Since most of the time I just re-trigger the debugger with no or very little change(no dependency related) to test code. How can I skip the dependency checking and only build the test file when there is a change?
Parallel execution with configuration on demand is an incubating feature.
> Task :corporate:common:processResources NO-SOURCE
...
hundreds tasks
...
> Task :indexing:signals:user:testClasses UP-TO-DATE
> Task :indexing:signals:user:test <= my test case there
The Intellij debug configuration
Press Alt + F12 to open the terminal, and execute the command like the following:
gradlew :indexing:signals:user:test
You can make gradle skip dependency checking by using the --offline parameter.
Related
Hi StackoverFlow folks,
The below error is really eating my head and I am not able to understand whats the mistake I have made. Hence looking forward to communities help.
Command and error
home:tcr-ui-automation sobhit.sharma$ gradle clean build -Denv=QA '-Dcucumber.options=--tags #target/rerun.txt'
Task :test
runners.TestRunner STANDARD_OUT None of the features at [classpath:features] matched the filters: [#target/rerun.txt]
0 Scenarios
0 Steps
0m0.000s
`
The cucumber option is something like this where I have defined my options-
#RunWith(Cucumber.class)
#CucumberOptions(
features = "classpath:features",glue = "stepDefinations",
plugin = { "com.cucumber.listener.ExtentCucumberFormatter:",
"junit:target/cucumber-results.xml",
"rerun:target/rerun.txt"},
tags="#Smoke",
monochrome = true
)
public class TestRunner {
Goal is to run the failed scenarios of a feature file.
File structure-
When dealing with errors that don't seem to make sense, it often helps to read every part of the command and error message out loud and in detail. Think if it as carefully explaining what you are doing to a co-worker.
For example:
gradle clean build -Denv=QA '-Dcucumber.options=--tags #target/rerun.txt'
Here you are telling gradle to clean the build environment. After cleaning the build environment to build the project. When doing so a JVM flag is passed to set the environment to QA and a JVM flag is passed to tell Cucumber to run only scenarios that are tagged with #target/rerun.txt.
When executing this:
None of the features at [classpath:features] matched the filters: [#target/rerun.txt]
Now Cucumber complains that it looked for features on the classpath but none were tagged with #target/rerun.txt.
As a part of a TDD workflow, I want to be able to check if my Java codebase compiles, but not if the tests pass.
Currently, if I run gradle build it runs the compile tasks (for source and tests) and then also executes the test task (and returns a non-zero exit code since the tests fail).
So I find that I have to run gradle build -x test to exclude the test task, and get a successful zero exit code.
What do I add to my build.gradle to define a new task, say compile that is an alias for build x test?
So far I have this, but it doesn't seem like dependsOn takes any arguments to customize the build task I want to execute:
task compile {
dependsOn build
}
I've been reading the docs here, I see different kinds of dependency chaining mechanisms, but not to disable/exclude a particular task. How does the -x flag even work then? I assumed there would be a way to control it programmatically too.
Thanks to Bjørn Vester's answer and reading the docs, I have implemented my task as follows:
task compile {
dependsOn classes
dependsOn testClasses
}
There are lots of different tasks you can run individually. For instance:
gradle classes: Will compile your "main" code.
gradle testClasses: Will compile your "main" code as well as test code.
gradle jar: Will compile your "main" code and assemble it into a jar.
None of the above will run your unit tests. On the other hand, the build task depends on all of the above, as well as the test task and more.
In general, if you like to run a particular set of tasks, you do that by defining a new task and then make dependencies to those other tasks you like to run with it. You tried that already, but instead of build you should have used something like compileJava or classes whatever other tasks you need. But always check if there isn't one already that satisfies your needs, like there are in this case. You can read about what tasks are available in Java projects in the documentation for the Gradle java plugin.
My Application is Spring boot application exposing some rest api
To run my integration tests , , first the application need to be up and running , as my application gradle based , how to make sure when i execute gradle command from command prompt , first application run and the integration tests will run .
task integration(type: Test, description: 'Runs the integration tests.', group: 'Verification') {
testClassesDir = sourceSets.integration.output.classesDir
classpath = sourceSets.integration.runtimeClasspath
outputs.upToDateWhen { false }
}
task appRunAndIntegrtationTest {
dependsOn 'run'
dependsOn 'integration'
tasks.findByName('integration').mustRunAfter 'run'
}
i added above code to build.gradle , but application up and running , thats it , it stayed their only , integration tests are not running , can anyone has idea on this please .
update : #Strelok , as mentioned , the application started up and integration task is not running .
update 1 : i found one gradle plugin
https://github.com/marc0der/gradle-spawn-plugin
i am trying to use like below
task startServer(type: SpawnProcessTask, dependsOn: 'assemble') {
command "java -jar ${projectDir}/build/libs/example.jar"
ready 'Started Application'
}
task stopServer(type: KillProcessTask)
but am getting below exception
*> Could not get unknown property 'SpawnProcessTask' for root project 'example-api' of type org.gradle.api.Project.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.*
please someone please suggest on this
I suggest a different approach: start and stop your application from your test framework. Test frameworks support setup and cleanup steps for your test suite (e.g. BeforeClass and AfterClass in JUnit), start the application in the setup step and stop it in the cleanup step. This approach will make your tests more self-contained, their success/failure will not depend on factors outside the test code.
Even if you prefer to run the application outside the test framework, I suggest wrapping this logic (i.e. starting the app, running the tests, stopping the app) in a Java class, and executing this class from Gradle via a task of type JavaExec. It will be much more clear than handling all this via Gradle tasks.
Finally, if you still insist on Gradle tasks, it's like the commenters said: the "run" task probably blocks execution while the app is running. Tha only sane way to handle this is to have a task that starts the app in the background, and another that stops it after the tests finished (use finalizedBy).
You should declare that the integration test task needs to depend on your app run task.
appRun is just an example please use the name of the task that is the precursor for the integration test.
integration.dependsOn appRun
integration.mustRunAfter appRun
Also, it might be like your app is running and blocking the progress of your Gradle build, does the build actually finish or it just hangs until the app stops running?
I have my grade script set up.
When I execute the Gradle build, everything is working and it runs the jUnit tests.
After that when I run the Gradle test I get the following:
C:\Users\..\..\Project>gradle test
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
When I perform gradle clean, then Gradle build works, of course...
I want to be able to reset only the tests, not build the whole project: how should I do this?
One option would be using the --rerun-tasks flag in the Forcing tasks to execute section. This would rerun all the the test task and all the tasks it depends on.
If you're only interested in rerunning the tests then another option would be to make gradle clean the tests results before executing the tests. This can be done using the cleanTest task.
Some background - the Java plugin defines a clean tasks to each of the other tasks. According to the Tasks documentation:
cleanTaskName - Deletes files created by specified task. cleanJar will delete the JAR file created by the jar task, and cleanTest will delete the test results created by the test task.
Therefore, all you need in order to re-run your tests is to also run the cleanTest task, i.e.:
gradle cleanTest test
Other option would be to add following in your build.gradle:
test.outputs.upToDateWhen {false}
This was recently the topic on Gradle's blog post Stop rerunning your tests. The author shows an example using outputs.upToDateWhen { false } and explains why it is wrong:
This doesn’t actually force reruns
What the author of this snippet probably wanted to say is “Always rerun my tests”. That’s not what this snippet does though. It will only mark the task out-of-date, forcing Gradle to recreate the output. But here’s the thing, if the build cache is enabled, Gradle doesn’t need to run the task to recreate the output. It will find an entry in the cache and unpack the result into the test’s output directory.
The same is true for this snippet:
test.dependsOn cleanTest
Gradle will unpack the test results from the build cache after the output has been cleaned, so nothing will be rerun. In short, these snippets are creating a very expensive no-op.
If you’re now thinking “Okay, I’ll deactivate the cache too”, let me tell you why you shouldn’t.
Then, the author goes on to explain why rerunning some tests is a waste of time:
The vast majority of your tests should be deterministic, i.e. given the same inputs they should produce the same result.
In the few cases where you do want to rerun tests where the code has not changed, you should model them as an input. Here are both examples from the blog post that show adding an input so the task will use it during its up-to-date checks.
task randomizedTest(type: Test) {
systemProperty "random.testing.seed", new Random().nextInt()
}
task systemIntegrationTest(type: Test) {
inputs.property "integration.date", LocalDate.now()
}
I recommend reading the entire blog post.
gradle test --rerun-tasks
Specifies that any task optimization is ignored.
Source: https://gradle.org/docs/current/userguide/gradle_command_line.html
--rerun-tasks works, but is inefficient as it reruns all tasks.
cleanTest by itself may not suffice due to build cache.
so, best way to accomplish this is:
./gradlew --no-build-cache cleanTest test
Here's a solution using the "build.gradle" file, in case you don't want to modify your command line:
test {
dependsOn 'cleanTest'
//Your previous task details (if any)
}
And here's the output. Notice 2 changes from your previous output:
1) A new 'cleanTest' task appears in the output.
2) 'test' is always cleaned (i.e. never 'UP-TO-DATE') so it gets executed every time:
$ gradle build
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:jar
:bootRepackage
:assemble
:cleanTest
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test
:check
:build
Also,
having to add --rerun-tasks is really redundant. Never happens. Create a --no-rerun-tasks and make --rerun-tasks default when cleanTask
TL;DR
test.dependsOn cleanTest
None of the above methods worked for me.
What worked for me was simply removing all items from the cache directory in /Users/<username>/.gradle/caches/build-cache-1/.
I want to execute gradle build without executing the unit tests. I tried:
$ gradle -Dskip.tests build
That doesn't seem to do anything. Is there some other command I could use?
You should use the -x command line argument which excludes any task.
Try:
gradle build -x test
Update:
The link in Peter's comment changed. Here is the diagram from the Gradle user's guide
Try:
gradle assemble
To list all available tasks for your project, try:
gradle tasks
UPDATE:
This may not seem the most correct answer at first, but read carefully gradle tasks output or docs.
Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
You can add the following lines to build.gradle, **/* excludes all the tests.
test {
exclude '**/*'
}
The accepted answer is the correct one.
OTOH, the way I previously solved this was to add the following to all projects:
test.onlyIf { ! Boolean.getBoolean('skip.tests') }
Run the build with -Dskip.tests=true and all test tasks will be skipped.
Every action in gradle is a task, and so is test. And to exclude a task from gradle run, you can use the option --exclude-task or it's shorthand -x followed by the task name which needs to be excluded. Example:
gradle build -x test
The -x option should be repeated for all the tasks that needs to be excluded.
If you have different tasks for different type of tests in your build.gradle file, then you need to skip all those tasks that executes test. Say you have a task test which executes unit-tests and a task testFunctional which executes functional-tests. In this case, you can exclude all tests like below:
gradle build -x test -x testFunctional
Using -x test skip test execution but this also exclude test code compilation.
gradle build -x test
In our case, we have a CI/CD process where one goal is compilation and next goal is testing (Build -> Test).
So, for our first Build goal we wanted to ensure that the whole project compiles well. For this we have used:
./gradlew build testClasses -x test
On the next goal we simply execute tests:
./gradlew test
You can exclude tasks
gradle build --exclude-task test
https://docs.gradle.org/current/userguide/command_line_interface.html#sec:command_line_executing_tasks
the different way to disable test tasks in the project is:
tasks.withType(Test) {enabled = false}
this behavior needed sometimes if you want to disable tests in one of a project(or the group of projects).
This way working for the all kind of test task, not just a java 'tests'. Also, this way is safe. Here's what I mean
let's say: you have a set of projects in different languages:
if we try to add this kind of record in main build.gradle:
subprojects{
.......
tests.enabled=false
.......
}
we will fail in a project when if we have no task called tests
Reference
To exclude any task from gradle use -x command-line option. See the below example
task compile << {
println 'task compile'
}
task compileTest(dependsOn: compile) << {
println 'compile test'
}
task runningTest(dependsOn: compileTest) << {
println 'running test'
}
task dist(dependsOn:[runningTest, compileTest, compile]) << {
println 'running distribution job'
}
Output of: gradle -q dist -x runningTest
task compile
compile test
running distribution job
Hope this would give you the basic
In The Java Plugin:
$ gradle tasks
Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
testClasses - Assembles test classes.
Verification tasks
------------------
test - Runs the unit tests.
Gradle build without test you have two options:
$ gradle assemble
$ gradle build -x test
but if you want compile test:
$ gradle assemble testClasses
$ gradle testClasses
Please try this:
gradlew -DskipTests=true build