Giter VIP home page Giter VIP logo

sprinter-idea-plugin's Introduction

The Sprinter Plugin for IntelliJ IDEA

What problem does it try to solve?

Tests may take some time to initialize before the actual run. Depending on a project and the tools you are using, initialization time can be significant — from a few seconds to several minutes.

During local development, you may run tests a lot, and every time you run a test, you have to wait for test initialization. This plugin simply allows you to run tests reusing the JVM and its already initialized state, thus excluding test initialization time for sequential runs.

This plugin utilizes the power of hotswapping, so it's recommended to use it with DCEVM. You can see how to configure the plugin for working with DCEVM in the related section called DCEVM configuration

It is tested with Spring Framework, but it should work with any tool that may take some time to initialize itself and can be easily reused afterward, such as Testcontainers, for example.

Supported technologies

Supported test frameworks:

  • TestNG
  • JUnit

Supported languages:

  • Java
  • Kotlin

Known issues:

  • The plugin will not work if you are using Gradle and if IntelliJ IDEA is configured to run tests using Gradle. In this case IDEA will run a test using this command: gradle test. Unfortunately, I didn't find a way to override test executor when using this command to support plugins functionality. The workaround is simple – just run test by IntelliJ IDEA's runner instead of gradle's one.

How does it work?

First of all, you should choose a test you want to run. You will see a new option added in a dropdown menu with run options (see screenshot below).

"Run in Launched JVM" new option

Just for example’s sake, let's assume that you are using Spring Framework in your project.

When you click it, IntelliJ IDEA will build your project, start up the JVM process in debug mode with a test executor in it, and send a command to the test executor to start tests you selected. This test executor is a part of the plugin, so you don't have to worry about it.

The test executor will run your tests, which will initialize Spring context before the actual run. Spring is caching its context in a static variable so you don't have to do anything additional to cache it.

When the tests are completed, the JVM is still up and running with the test executor, waiting for the next command to run the tests. When you try to run the tests again, the IDE will perform the hotswap to update the code and send the command to run the following tests. This way, new tests will not waste your time with initialization because Spring context is already there.

You can also look at this work schema:

Work Schema

Installation

You can find the Sprinter plugin in the JetBrains Marketplace here. After installing it to your IDE, you are ready to go.

It's recommended to use DCEVM together with this plugin. Get more information here: DCEVM configuration.

DCEVM configuration

DCEVM is a Java HotSpot patch that enables many more cases for hotswapping compared to the default implementation. By default, hotswapping in Java works only with method bodies, which is not enough for comfort development, of course.

It's also recommended to install Hotswap Agent together with DCEVM. It's a Java agent that makes it possible to update the application state when a hotswap is performed. For example, it can update Spring context when the configuration is changed.

You will need to install DCEVM (with Hotswap Agent, if you want). You can follow the official instructions.

After that, you should select the installed DCEVM as a project SDK in IntelliJ IDEA, go to the plugin settings (Settings → Tools → Sprinter Settings), and change the configured JVM from Plain to DCEVM and select the Hotswap Agent jar location (if you also installed the Hotswap Agent plugin).

And that's it — you are ready to go!

You may also notice that there are more settings related to DCEVM, but they are not mandatory to fill in.

More Information

To learn more about the plugins watch the recording of the presentation here or in russian here.

sprinter-idea-plugin's People

Contributors

anton-didenko avatar mugenor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

seregamorph

sprinter-idea-plugin's Issues

Read access is allowed from inside read-action

After clicking "Run in launched VM" for a Gradle based project I get the following error. However, the test is able to run and passes.

Sprinter 1.3.2
IntelliJ IDEA 2023.3.4 (Ultimate Edition)

com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments: Read access is allowed from inside read-action (see Application.runReadAction()); see https://jb.gg/ij-platform-threading for details
Current thread: Thread[ApplicationImpl pooled thread 5,4,main] 423317760 (EventQueue.isDispatchThread()=false)
SystemEventQueueThread: Thread[AWT-EventQueue-0,6,main] 2144334509
	at com.intellij.util.concurrency.ThreadingAssertions.createThreadAccessException(ThreadingAssertions.java:149)
	at com.intellij.util.concurrency.ThreadingAssertions.softAssertReadAccess(ThreadingAssertions.java:107)
	at com.intellij.openapi.application.impl.ApplicationImpl.assertReadAccessAllowed(ApplicationImpl.java:1012)
	at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexDataImpl.ensureIsUpToDate(WorkspaceFileIndexDataImpl.kt:134)
	at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexDataImpl.getFileInfo(WorkspaceFileIndexDataImpl.kt:75)
	at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexImpl.getFileInfo(WorkspaceFileIndexImpl.kt:247)
	at com.intellij.openapi.roots.impl.ProjectFileIndexImpl.getModuleSourceOrLibraryClassesRoot(ProjectFileIndexImpl.java:210)
	at com.intellij.openapi.module.impl.scopes.ModuleWithDependenciesScope.contains(ModuleWithDependenciesScope.java:147)
	at com.intellij.psi.impl.file.PsiPackageImpl.lambda$getAllDirectories$1(PsiPackageImpl.java:67)
	at com.intellij.util.containers.ContainerUtil.findAll(ContainerUtil.java:1030)
	at com.intellij.util.containers.ContainerUtil.filter(ContainerUtil.java:1005)
	at com.intellij.psi.impl.file.PsiPackageImpl.getAllDirectories(PsiPackageImpl.java:67)
	at com.intellij.psi.impl.file.PsiPackageBase.getDirectories(PsiPackageBase.java:63)
	at org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineAgentConnector.getJarVirtualFiles(CoroutineAgentConnector.kt:71)
	at org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineAgentConnector.findKotlinxCoroutinesCoreJar(CoroutineAgentConnector.kt:43)
	at org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineAgentConnector.attachCoroutineAgent(CoroutineAgentConnector.kt:33)
	at org.jetbrains.kotlin.idea.debugger.coroutine.DebuggerConnection.<init>(DebuggerConnection.kt:51)
	at org.jetbrains.kotlin.idea.debugger.coroutine.DebuggerConnection.<init>(DebuggerConnection.kt:31)
	at org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineDebugConfigurationExtension.updateJavaParameters(CoroutineDebugConfigurationExtension.kt:24)
	at com.intellij.execution.RunConfigurationExtension.updateJavaParameters(RunConfigurationExtension.java:27)
	at com.intellij.execution.JavaRunConfigurationExtensionManager.updateJavaParameters(JavaRunConfigurationExtensionManager.kt:42)
	at com.wrike.sprinter.frameworks.AbstractSharedJvmRunnableState.createJavaParameters(AbstractSharedJvmRunnableState.kt:80)
	at com.wrike.sprinter.frameworks.junit.SharedJvmJUnitRunnableState.createJavaParameters(SharedJvmJUnitRunnableState.kt:27)
	at com.intellij.execution.configurations.JavaCommandLineState.getJavaParameters(JavaCommandLineState.java:41)
	at com.intellij.debugger.impl.GenericDebuggerRunner.lambda$doExecute$2(GenericDebuggerRunner.java:82)
	at com.intellij.execution.runners.JavaProgramPatcher.lambda$patchJavaCommandLineParamsUnderProgress$2(JavaProgramPatcher.java:41)
	at com.intellij.openapi.progress.impl.CoreProgressManager$2.run(CoreProgressManager.java:287)
	at com.intellij.openapi.progress.impl.CoreProgressManager.startTask(CoreProgressManager.java:434)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.startTask(ProgressManagerImpl.java:132)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcessWithProgressSynchronously$8(CoreProgressManager.java:518)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$new$0(ProgressRunner.java:84)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$4(ProgressRunner.java:248)
	at com.intellij.openapi.progress.ProgressManager.lambda$runProcess$0(ProgressManager.java:73)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$1(CoreProgressManager.java:192)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$12(CoreProgressManager.java:610)
	at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:685)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:641)
	at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:609)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:78)
	at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:179)
	at com.intellij.openapi.progress.ProgressManager.runProcess(ProgressManager.java:73)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$5(ProgressRunner.java:248)
	at com.intellij.openapi.progress.impl.ProgressRunner$ProgressRunnable.run(ProgressRunner.java:498)
	at com.intellij.util.concurrency.ChildContext$runAsCoroutine$1.invoke(propagation.kt:81)
	at com.intellij.util.concurrency.ChildContext$runAsCoroutine$1.invoke(propagation.kt:81)
	at com.intellij.util.concurrency.ChildContext.runAsCoroutine(propagation.kt:86)
	at com.intellij.util.concurrency.ChildContext.runAsCoroutine(propagation.kt:81)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$launchTask$18(ProgressRunner.java:464)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:702)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:699)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:699)
	at java.base/java.lang.Thread.run(Thread.java:840)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.