Testing FAQ
Edit pageLast modified: 13 November 2024This page lists a number of common questions/issues and techniques useful for testing plugins.
note
Check out this step-by-step tutorial teaching how to write and run automated tests for your custom language plugin. Also, code samples comparing_string_references_inspection and conditional_operator_intention demonstrate using tests.
Useful Classes
UI
See UI Tests for UI integration tests.
Issues
2024.2+Unresolved test-framework dependencies
tip
Configuring Test Frameworks (2024.2+)All required test-framework dependencies must be declared explicitly.
2021.3+"No Tests Found" targeting 2021.3+
Please see notes.
How to avoid flaky tests?
Always call super.tearDown()
inside finally {..}
block of your test class to avoid leaks and side effects from previously run (failed) tests:
protected void tearDown() throws Exception {
try {
// test specific tear down calls
} catch (Exception e) {
addSuppressedException(e);
} finally {
super.tearDown();
}
}
override fun tearDown() {
try {
// test specific tear down calls
} catch (e: Throwable) {
addSuppressedException(e)
} finally {
super.tearDown()
}
}
Avoid OS-specific assumptions (e.g., filesystem case-sensitivity, hardcoded separator instead of java.io.File.separator
, default encoding, line endings).
Use ordered collections or UsefulTestCase.assertUnorderedCollection()
.
Code deferring execution (e.g., via Application.invokeLater()
) might not run during test execution (and possibly fails in production, too). Use Application.invokeLater(runnable, myProject.getDisposed())
.
When targeting 2024.2 or later, see also How to handle ProjectActivity? .
How to avoid test failure when using resources?
In some situations, added or changed files (e.g. XML DTDs provided by a plugin) are not refreshed in Virtual File System. In such cases, simply delete test-system/caches in your sandbox directory and try again.
How to enable DEBUG/TRACE logging?
Provide JVM system properties idea.log.debug.categories
or idea.log.trace.categories
to specify logger category name, respectively. Multiple categories can be set using a comma separated value list.
Sample Set DEBUG level for categories com.my.plugin.ui
and com.my.plugin.backend
:
tasks {
test {
systemProperty("idea.log.debug.categories", "com.my.plugin.ui,com.my.plugin.backend")
}
}
test {
systemProperty("idea.log.debug.categories", "com.my.plugin.ui,com.my.plugin.backend")
}
2021.3+How to get separate logs for failing tests?
Set system property idea.split.test.logs
to true
to generate separate test log files in splitTestLogs subdirectory for failing tests (WARN/ERROR level messages).
Techniques
How to mark test-only elements in production code?
Annotate with @TestOnly
, usages will be highlighted via inspection JVM languages | Test-only usage in production code.
To mark members whose visibility is higher than necessary to be used from tests, use @VisibleForTesting
How to run tests for all files in a directory?
Use FileBasedTestCaseHelper
, please see its Javadoc for instructions.
How to modify setup on a per-test basis?
Use UsefulTestCase.getTestName()
or create your own annotation(s) which can be checked via UsefulTestCase.annotatedWith()
.
How to run a performance test?
Use PlatformTestUtil.startPerformanceTest()
to assert machine-adjusted metrics.
How to dispatch pending UI events?
Use PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()
.
How to disable stderr logging?
Use DefaultLogger.disableStderrDumping()
passing getTestRootDisposable()
.
How to register a resource (DTD, XSD) temporarily?
Use ExternalResourceManagerExImpl.registerResourceTemporarily()
passing getTestRootDisposable()
.
How to replace component/service in tests?
Provide dedicated test implementation via testServiceImplementation
in service declaration, or use ServiceContainerUtil
.
How to replace extension points in tests?
Use ExtensionTestUtil
.
How to wait for a specified amount of time?
If possible, use How to wait for condition with timeout? approach. Otherwise, call com.intellij.util.TimeoutUtil.sleep()
.
How to wait for condition with timeout?
Use WaitFor
.
How to test a JVM language?
Plugins supporting a JVM language may require JDK and language standard library to be set up in a test project, so that classes like java.lang.String
can be correctly resolved during tests. Tests extending LightJavaCodeInsightFixtureTestCase
use one of the mock JDKs distributed with the IntelliJ Community project sources (notice java/mockJDK-$JAVA_VERSION$ directories). These JAR files are not available in plugin project dependencies, so the IntelliJ Community sources must be checked out to the machine running the tests, and sources' location must be provided to the test framework. It's done by setting the idea.home.path
system property to the absolute path of the checked-out sources in the test
task configuration:
test {
systemProperty("idea.home.path", "/path/to/intellij-community-sources")
}
test {
systemProperty "idea.home.path", "/path/to/intellij-community-sources"
}
The default JDK version used by the test framework depends on the target platform version and is the latest supported version. The easiest way to change the JDK version to a custom one is by overriding LightJavaCodeInsightFixtureTestCase.getProjectDescriptor()
and using one of the predefined project descriptors in LightJavaCodeInsightFixtureTestCase
. If a project descriptor requires more customizations, its getSdk()
method can use one of the IdeaTestUtil.getMockJdk*()
methods.
Sometimes, testing a JVM language requires adding standard or other libraries to a test project. If a required library is available in the Maven repository, use MavenDependencyUtil
, e.g.:
MavenDependencyUtil.addFromMaven(model,
"org.jetbrains.kotlin:kotlin-stdlib:1.6.10");
For light tests, use convenience method DefaultLightProjectDescriptor.withRepositoryLibrary()
and JavaModuleFixtureBuilder.addMavenLibrary()
for heavy tests.
If a required library is an unpublished JAR file, use PsiTestUtil.addLibrary()
or addProjectLibrary()
method and the JAR file path, e.g.:
PsiTestUtil.addLibrary(model,
"internal-library", getTestDataPath(), "internal-library-2.0.jar");
2024.2+How to handle ProjectActivity
?
ProjectActivity
are no longer awaited on project open in tests. If tests depend on some job done in ProjectActivity
(e.g., automatic project re-import), implement a dedicated event/listener and wait for it explicitly. As a workaround, use StartupActivityTestUtil.waitForProjectActivitiesToComplete()
.
2024.2+How to handle indexing?
Indexing is now run asynchronously in a background thread. Use IndexingTestUtil.waitUntilIndexesAreReady()/suspendUntilIndexesAreReady()
to wait for fully populated indexes.
note
Something missing?If a topic you are interested in is not covered in the above sections, let us know via the Was this page helpful? feedback form below or other channels.
Please be specific about the topics and reasons for adding them, and leave your email in case we need more details. Thanks for your feedback!
Thanks for your feedback!