I get into trouble while I try to run my JUnit test through Gradle test task. While I run the test in eclipse directly with Run As -> JUnit test, everything is ok, the test succeeds. But through test task, test always fails. Probably some trouble with the encoding of my resource txt file. So I would like to enable debug while I am launching the test with Gradle
in build.gradle, my test task now looks like:
test {
tasks.withType(Compile) {
options.encoding = 'UTF-8'
}
}
So what should I do to enable debug? I run Gradle tasks from Gradle panel in Eclipse, not from the console. Thanks!
To debug tests the following argument should be used: --debug-jvm
For example: gradle test --debug-jvm
Gradle will suspend execution right before running tests and wait for debugger connection on port 5005.
For executing only specific tests see Simple name pattern
For additional options see Debugging when running tests.
As explained under 23.12. Test in the Gradle User Guide, executing gradle test -Dtest.single=MyTestClass -Dtest.debug will suspend the test JVM upon start, and allows to connect an external debugger (such as the Eclipse debugger) on port 5005.
Putting this here as --debug-jvm did not work for me, I was able to do this by setting:
org.gradle.daemon=true
org.gradle.jvmargs=... -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=10999
in
~/.gradle/gradle.properties
But when I connect with eclipse debugger for the project none of the breakpoints I've set compile/trigger... I am connected via the debugger, I can see action in the Debug view, whenever I run gradle test from command line, like new threads starting/stopping, but can't get breakpoints to trigger, trying to resolve this now...
Fyi to stop deamon run gradle --stop
Other solution
Leaving above as reference, this worked for triggering break points in tests, I turned off deamon as I could not get it to work properly:
Using directions from this article: http://blogs.steeplesoft.com/posts/2013/gradle-tip-attaching-a-debugger.html
test {
if (System.getProperty('DEBUG', 'false') == 'true') {
jvmArgs '-Xdebug',
'-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=10999'
}
}
Executed via gradle test -DDEBUG=true
Solution when using the JUnit Platform Gradle plugin
The solution above won't work when using org.junit.platform.gradle.plugin.
Instead it should be replaced by:
junitPlatformTest {
if (System.getProperty('DEBUG', 'false') == 'true') {
jvmArgs '-Xdebug',
'-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=10999'
}
}
I'm on 4.6 (gradle) and I'm able to debug my tests when I have this in my build.gradle file:
test {
debug true
}
Link - https://docs.gradle.org/4.6/userguide/userguide_single.html#sec:java_test
Related
I'm introducing a Github actions pipeline to an existing project to run ./gradlew test. Unsurprisingly, I've run into cases where tests pass locally but not on the build machine, due to various things like mismatching timezones.
By default, gradle doesn't print the stdout for these tests. I am aware that it will do so if passed --info, however the test suite is some 1500 tests in size which makes the pipeline output extremely verbose (it actually makes my browser lag if I turn it on for the full suite and try to view the resulting output in Github).
To fix the initial teething problems, I've resorted to also targeting the suites that are failing (e.g. ./gradlew test --tests "foo.bar.AppTest" --info). This is a bit of a faff, though. Is there a way to tell gradle to print the stdout contents just for tests that have failed? This would put me in a much better position going forward!
This page contains what you are looking for.
It boils down to configuring the test task like so:
test {
testLogging {
// set options for log level LIFECYCLE
events "failed"
}
}
There are more options to finely control logging if you read that page.
Since you probably only need this for github actions, you can use the CI environmental variable to enable your configurations on CI environments only:
test {
doFirst {
if (System.getenv('CI')) {
testLogging {
// set options for log level LIFECYCLE
events "failed"
}
}
}
}
Other CI providers also set this environmental variable
As mentioned in this related answer when dealing with a multi-module android app the following can be used (root build.gradle)
// Call from root build.gradle
setupTestLogging()
fun Project.setupTestLogging() {
for (sub in subprojects) {
sub.tasks.withType<Test> {
testLogging {
exceptionFormat = TestExceptionFormat.FULL
}
}
}
}
(note that while exceptionFormat alone should be enough to get the wanted outcome, the events("standardOut" ...) mentioned above can be specified in the same way).
For mono-module android projects the same solution will work by dropping the part that iterates on the submodules
I am building an Elasticsearch plugin based on this example. The plugin uses Gradle for building, testing, integration testing, etc. I want to use IntelliJ to set a breakpoint in an Elasticsearch integration test and debug it. I don't care if I run the Gradle build from within IntelliJ or outside of IntelliJ, but right now in both cases I'm running into issues. I'll describe my setup and the problems below:
First I download and build/test the example project via CLI:
$ pip install cookiecutter
$ cookiecutter gh:spinscale/cookiecutter-elasticsearch-ingest-processor
$ # keep all default settings when prompted...
$ gradle build # (also runs the test and integTest tasks)
This runs fine and the tests pass. I generate the IntelliJ project using Gradle ($ gradle idea) and open it in IntelliJ (shows a green Gradle icon on the directory). I use the default gradle-wrapper option and keep all other defaults when opening.
First problem: I open IntelliJ's Gradle window (view > Tool Windows > Gradle), but I don't see any of the Gradle tasks which I know are defined in the project. This doesn't seem to be a huge deal, but it would be nice to have them.
Now I want to run the tests within IntelliJ, so I open the tests in org.elasticsearch.plugin.ingest.awesome.AwesomeProcessorTests. This class extends the ESTestCase class from Elasticsearch but doesn't directly test any Elasticsearch API interaction.
Second problem: I run this test class using the little green triangles next to the class name. This fails with the error java.lang.RuntimeException: unable to install test security manager.
I figured out I can get around this by editing the run configuration and adding the VM argument -Dtests.security.manager=false. Now the simple tests run and pass, and I can also set breakpoints and debug them.
Now I want to directly test some Elasticsearch functionality, so I write a new integration test class that extends the class ESIntegTestCase. The test should hit the Elasticsearch _cat/plugins endpoint and check that the response string is non-empty.
public class SimpleIT extends ESIntegTestCase {
private RestClient restClient;
#Before
public void setUp() throws Exception {
super.setUp();
this.restClient = getRestClient();
}
#Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Collections.singletonList(IngestAwesomePlugin.class);
}
public void testPluginInstallation() throws IOException {
Response response = restClient.performRequest("GET", "_cat/plugins");
String body = EntityUtils.toString(response.getEntity());
assertTrue(body.length() > 0);
}
}
When I run this via CLI (gradle integTest), the test passes. If I add a purposely-failing assertion (e.g. assertTrue(body.length() < 0), then the test fails. So that seems to work.
Third problem: When I run the same test from within IntelliJ (little green triangles), I get the error:
java.lang.IllegalArgumentException: no hosts provided
at __randomizedtesting.SeedInfo.seed([6F620686489164F5:270C27B7060A2BA1]:0)
at org.elasticsearch.client.RestClientBuilder.<init>(RestClientBuilder.java:68)
at org.elasticsearch.client.RestClient.builder(RestClient.java:124)
at org.elasticsearch.test.ESIntegTestCase.createRestClient(ESIntegTestCase.java:2261)
at org.elasticsearch.test.ESIntegTestCase.createRestClient(ESIntegTestCase.java:2248)
at org.elasticsearch.test.ESIntegTestCase.createRestClient(ESIntegTestCase.java:2242)
at org.elasticsearch.test.ESIntegTestCase.getRestClient(ESIntegTestCase.java:2236)
at org.elasticsearch.plugin.ingest.awesome.SimpleIT.setUp(SimpleIT.java:36)
This maps to the line where I call getRestClient(), meaning IntelliJ is blocking the Gradle/Elasticsearch integration testing setup which otherwise works from the CLI.
FWIW, I can still set a breakpoint on this line and debug the test class in IntelliJ and it will stop at the line.
Now I try to run the integration tests via CLI, set a breakpoint in IntelliJ, and use IntelliJ's remote debugger to attach to the tests.
I setup a new "Remote" run configuration, keeping the defaults (transport socket, debugger mode attach, host localhost, port 5005). On the "Search sources using module's classpath" option, I've tried all the possible settings.
I set a breakpoint on the getRestClient() line, and run Gradle with remote debugging options via CLI:
$ GRADLE_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005" gradle integTest
Fourth problem: As expected, the Gradle process suspends, showing Listening for transport dt_socket at address: 5005. I start the new remote task in IntelliJ, and then the Gradle process continues running. Unfortunately it runs all the way through and doesn't stop at the breakpoint. The tests still pass.
I've searched online extensively for different ways to attach to the Gradle debugger. I've seen many things about disabling the daemon, and I've also tried using --system-prop to pass the debug parameters, but nothing solves this problem so far.
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'm using gradle to build my android project and am not able to run single local unit test. I have several test classes and one of them is MockServerTest and I only want to run test methods in this class.
I tried using gradle -Dtest.single=MockServerTest test but it turned out running all my tests, including these in other test classes.
I also tried gradle test --tests MockServerTest but an error occurred said
Test filtering is not supported for given version of junit. Please upgrade junit version to at least 4.6.
But I'm using junit 4.12 in my gradle file
testCompile 'junit:junit:4.12'
I'm using gradle 2.4 with com.android.tools.build:gradle:1.2.3.
Also, how can I run a single test method inside a single test class?
BTW, I'm able to run single test method inside Android Studio, by right clicking on the test method and select run targetTestMethod() from the menu. But how can I achieve this in the terminal? I guess Android Studio also trigger a certain command to do this. How can I see what that command is?
Figured it out myself. I have to run
gradle testDebug --tests com.my.package.TestClassName
There are two things to note here.
1. You have to use gradle testDebug or gradle testRelease instead of just gradle test. If you have build variant, you have to use gradle testVariantNameDebug or gradle testVariantNameRelease
2. You have to specify the whole qualified class name, means including the package name.
You can use Android Gradle plugin DSL to set up test tasks filters like this:
android {
testOptions {
unitTests.all {
it.testNameIncludePattern = "*.SomeTest"
}
}
}
You can find more information on testOptions here and filters here.
Have you tried running gradle test -Dtest.single=MockServerTest? More information can be found here.
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