Debugging Elasticsearch Plugin Integration Tests using IntelliJ and Gradle - java

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.

Related

Quarkus tests fail while doing mocking with jmock resulting in "No code generation strategy available"

When running my Quarkus tests in combination with jmock I run into:
java.lang.IllegalStateException: No code generation strategy available
This is what I have setup jmock with:
#QuarkusTest
#Tag("integration")
class MyServiceTest {
#RegisterExtension
JUnit5Mockery mockery = new JUnit5Mockery() {
{
setImposteriser(ByteBuddyClassImposteriser.INSTANCE);
setThreadingPolicy(new Synchroniser());
}
};
To make matters worse: This all works on the command line but not within Eclipse.
This is due to the JRE/JDK that Eclipse selects to run your tests. These tests should be run using a JDK only, the JRE that comes whith most versions of Eclipse will not service.
So: install a full JDK (eg. by using sdkman) and specify & select that to run your tests in this part of the preferences of Eclipse:

How do I load environment variables to load application context before integration test runs

I'm working on multi-module maven project using Spring Boot 2.4.0. I have written integration tests for a module. The test class looks similar to this.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = SpringApplicationClassWithMainMethod.class)
public class XYZServiceIT {
#Test
public void test1() {...}
#Test
public void test2() {...}
}
To run the SpringApplicationClassWithMainMethod.class i.e., in order to load the Application context I need few environment variables that I set in eclipse. So, in order to run the above integration test while loading the SpringApplicationClassWithMainMethod.class I need those environment variables before the Application context is loaded.
Trial-1:
I have tried using #TestPropertySource(properties = {"key1=val1", "key2=val2"}) annotation, that didn't work.
Trial-2:
I have also tried the static block to set environment variables which didnt work.
Trial-3:
I also tried using the #ContextConfiguration with a ApplicationContextInitializer class, that didnt work as well.
All these attempts to build the project using maven only lead to a
IllegalState Failed to load ApplicationContext
error for the above test class. Is there any way I could load the environment variables before the Application context gets loaded?
I think the correct class naming convention for Integration tests in maven would be XYZServiceIT since *Test is reserved for unit tests already which are run before application context. You can change that if needed in your maven pom or simply stick with the conventional naming.
UPDATE
To pass environment variables to maven for your integration test use the following:
make sure you installed M2E from eclipse marketplace (found in menu > help > eclipse marketplace)
right click your project > Run As ... > 4 Maven Build ...
PS: afterwards you can find your run configuration at the top underneath the dropdown of the green arrow and in the run configuration settings if you need to rerun the tests in the future
configure maven environment parameters either inline (for the maven goal command) with verify -Dkey=val or in the bottom variable section. both work for unit and integrationtest. environment typically does NOT work for test stage. (If you don't have an JDK as the runner you will get an error. Follow this post to fix it if needed: No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?)
I hope that helps. You can also change pom.xml profiles if needed but i wouldn't recommend that.

How to run integration task after run task in gradle?

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?

Why is my JUnit test not running in Eclipse?

It's been 3 hours now and I still didn't find a solution, even though I seem to have read all related questions already.
I am building an Android application and I just want to create a couple of simple Unit Tests that test my basic functions. I don't need to test any Android related logic or activity features.
So I have created a new directory in my solution in which I have created a new JUnit Test Case.
To keep things simple my test methods are not testing much yet, but even when doing a Right Click > Run As > JUnit Test, it's not doing anything.
As you can see in my screenshot the JUnit pane on the left shows my test is terminated but does not show any test that has been executed.
I have created a simple Unit Test in a new Java Project and then it's working. If I repeat the same steps in a new Android Application Project it's not working.
What do I need to do to run my simple Unit Tests?!
Thanks!
(My Compiler Compliance Level is 1.6)
Go to Window -> Show View -> Error Log to see what the actual error is.
For my case it was No test found with test runner 'Junit 5'.
Then one can google for respective solution.
You either don't have JUnit on the build path or you don't have the library (jar) at hand. Make sure both are in place.
I think you will need an unit test suite if all else fails:
#RunWith(Suite.class)
#SuiteClasses({ GpsLocationTest.class })
public class AllTests {
}
There is one more thing you can do: check whether you import the right #Test annotation. Restart Eclipse and clean your project if the problem persists.
You may want to refer to the vogella guide about unit testing.
You can use AndroidTestCase, which inherits from junit.framework.TestCase, not org.junit.Test.
This is related to Memory Issue.
Simply add these line in VM argument:
right click on Junit Test -> Run as -> Run Configuration -> Arguments -> add "-XX:MaxPermSize=512m" under VM argument
The java Build path of the project has Junit4.jar lets say and the Run configuration for the test you are running has Junit5 - then it causes to terminate and nothing happens.

How to enable debug on my JUnit through Gradle test task

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

Categories

Resources