From f9d83e3548909b424305aa21e011b50a57b9128f Mon Sep 17 00:00:00 2001 From: Maxim Kolmakov Date: Wed, 2 Apr 2025 11:37:55 +0200 Subject: [PATCH] Integration tests: API interaction (#1448) * Integration tests: API interaction * Review fixes * Remove image * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Update topics/basics/testing_plugins/integration_tests/integration_tests_api.md Co-authored-by: Karol Lewandowski * Make list ordered * Fix each sentence on a new line style * Change package and plugin name to com.example.demo * Change PluginStorage to object * Update image --------- Co-authored-by: Karol Lewandowski --- ijs.tree | 1 + .../integration_tests/remote-support.png | Bin 0 -> 25729 bytes .../integration_tests/integration_tests.md | 2 +- .../integration_tests_api.md | 198 ++++++++++++++++++ 4 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 images/basics/testing_plugins/integration_tests/remote-support.png create mode 100644 topics/basics/testing_plugins/integration_tests/integration_tests_api.md diff --git a/ijs.tree b/ijs.tree index e4d8ce383..0c1016747 100644 --- a/ijs.tree +++ b/ijs.tree @@ -244,6 +244,7 @@ + diff --git a/images/basics/testing_plugins/integration_tests/remote-support.png b/images/basics/testing_plugins/integration_tests/remote-support.png new file mode 100644 index 0000000000000000000000000000000000000000..5d013892943b226289cc84ae606eca994b2cc69f GIT binary patch literal 25729 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 literal 0 HcmV?d00001 diff --git a/topics/basics/testing_plugins/integration_tests/integration_tests.md b/topics/basics/testing_plugins/integration_tests/integration_tests.md index 99fa4688e..fbeb32e3b 100644 --- a/topics/basics/testing_plugins/integration_tests/integration_tests.md +++ b/topics/basics/testing_plugins/integration_tests/integration_tests.md @@ -15,5 +15,5 @@ There are several important reasons to create integration tests, including: 1. [](integration_tests_intro.md) 2. [](integration_tests_ui.md) -3. API Interaction (will be available soon) +3. [](integration_tests_api.md) diff --git a/topics/basics/testing_plugins/integration_tests/integration_tests_api.md b/topics/basics/testing_plugins/integration_tests/integration_tests_api.md new file mode 100644 index 000000000..ef58f14a6 --- /dev/null +++ b/topics/basics/testing_plugins/integration_tests/integration_tests_api.md @@ -0,0 +1,198 @@ + + +# Integration Tests: API Interaction + + + +Walkthrough how to interact with API in integration tests. + +> This page is part of the [](integration_tests.md) tutorial. + +For introduction and setting up dependencies, refer to [](integration_tests_intro.md). + +## Java Management Extension + +The IDE and tests are running in different processes, which means some way to communicate between them is required. + +Driver framework uses Java Management Extensions (or JMX for short). +JMX supports different connectors to manage the state of the JVM. +Driver framework uses a standard Java Remote Method Invocation (RMI) protocol. +This protocol allows tests to access objects and invoke methods in the JVM running the IDE. + +The architecture of RMI protocol is as follows: +```mermaid +sequenceDiagram + box rgb(240,240,240) Test Process + participant Test as Test (Client) + end + + box rgb(240,240,240) IDE Process + participant IDE as IDE (Server) + participant Registry as RMI registry + end + + Test->>Registry: 1. Look up remote object + Registry-->>Test: 2. Return stub reference + + Note over Test: Stub is obtained
for remote reference + + activate Test + Test->>IDE: 3. Remote method call via stub + IDE->>IDE: 4. Process request and invoke actual method + IDE-->>Test: 5. Return serialized result + deactivate Test + + Note over IDE,Test: Each remote call involves:
- Serialization of parameters
- Network transfer
- Deserialization
- Method invocation
- Serialization of result +``` + +When a test needs to invoke a method on a remote object: + +1. The test looks up the remote object in the RMI registry (the IDE). +2. The IDE returns a reference to the stub, which implements the same interface as the remote object. +3. When the client calls a method on the stub: + 1. The stub serializes the method call, including any parameters. + 2. It sends the serialized data over the network to the remote server. + 3. The RMI runtime inside the IDE unmarshals the request and invokes the corresponding method on the actual remote object. + 4. The method executes, and the result is serialized and sent back to the client via the stub. + 5. The stub unmarshals the response and returns the result to the caller. + +Thus, the stub makes remote calls feel like local method calls, without the caller worrying about low-level networking, data conversion, or request handling. + +## Creating Stubs + +To demonstrate how this works in practice, add the following code to the plugin: + +```kotlin +package com.example.demo + +object PluginStorage { + @JvmStatic + fun getPluginStorage() = Storage("static method", listOf("static1", "static2")) +} + +@Service +class PluginService { + fun someMethod(): Unit = Unit + fun getAnswer(): Int = 42 +} + +@Service(Service.Level.PROJECT) +class PluginProjectService { + fun getStrings(): Array = arrayOf("foo", "bar") +} + +data class Storage(val key: String, val attributes: List) +``` + +This file contains one class with the static method `getPluginStorage`, and two [light services](plugin_services.md#light_services) – one application-level `PluginService` and one project-level `PluginProjectService`. + +The test needs to call the methods of these classes and verify their return values. +To do this, the following stubs have to be created: + +```kotlin +import com.intellij.driver.client.Remote + +@Remote("com.example.demo.PluginStorage", plugin = "com.example.demo") +interface PluginStorage { + fun getPluginStorage(): Storage +} + +@Remote("com.example.demo.PluginService", plugin = "com.example.demo") +interface PluginService { + fun getAnswer(): Int +} + +@Remote("com.example.demo.PluginProjectService", plugin = "com.example.demo") +interface PluginProjectService { + fun getStrings(): Array +} + +@Remote("com.example.demo.Storage", plugin = "com.example.demo") +interface Storage { + fun getAttributes(): List + fun getKey(): String +} +``` + +As seen above, a stub is an interface for the class with methods that will be used in the test. +Stubs shouldn't be created for methods not used in tests. + +The first parameter is the fully qualified name of the class that will correspond to the stub using the [`Remote`](%gh-ic%/platform/remote-driver/client/src/com/intellij/driver/client/Remote.kt) annotation. +Strings are used to avoid introducing dependency between production and test code. + +The `plugin` parameter specifies the ID of a plugin, where classes are located. +This parameter is required since IntelliJ-based IDEs use separate [class loaders](plugin_class_loaders.md) for each plugin, and the code that will call methods on the IDE side (Invoker) needs to know where to search for them. + +There is built-in support for `@Remote` annotation inside IntelliJ IDEA: +![](remote-support.png){width="717"} + +Rename and move the target class refactorings will update the annotation accordingly. +Gutter icons can be used to navigate to the target class from a stub. + +## Calling IDE Methods from Tests + +The complete API test: + +```kotlin +@Test +fun testStubs() { + Starter.newContext( + "testExample", + TestCase( + IdeProductProvider.IC, + GitHubProject.fromGithub( + branchName = "master", + repoRelativeUrl = "JetBrains/ij-perf-report-aggregator" + ) + ) + .withVersion("2024.3") + ) + .apply { + val pathToPlugin = System.getProperty("path.to.build.plugin") + PluginConfigurator(this).installPluginFromFolder(File(pathToPlugin)) + }.runIdeWithDriver().useDriverAndCloseIde { + val storage = utility().getPluginStorage() + val key = storage.getKey() + val attributes = storage.getAttributes() + Assertions.assertEquals("static method", key) + Assertions.assertEquals(listOf("static1", "static2"), attributes) + val answer = service().getAnswer() + Assertions.assertEquals(42, answer) + waitForProjectOpen() + val project = singleProject() + val strings = service(project).getStrings() + Assertions.assertArrayEquals(arrayOf("foo", "bar"), strings) + } +} +``` + +There are two methods that allow invoking methods: `service` and `utility`. +The first one will return an instance of a service, and the second will return an instance of any class. + +Project-level services require a `Project` stub. +To get it, use the `singleProject` method, which is implemented in the same way as demonstrated above: + +```kotlin +service().getOpenProjects().singleOrNull() +``` + +> Service and utility proxies can be acquired on each call, there is no need to cache them in clients. +> +{style="note"} + +## JMX/RMI Limitations + +The main inconvenience of using JMX/RMI is that stubs need to be created for all objects which are used in tests. +On the other hand, they don't require modification of the production code. + +As with any protocol, JMX/RMI has its limitations: + +* Parameters and return values can only be: + * Primitives and their wrappers: `Integer`, `Short`, `Long`, `Double`, `Float`, and `Byte`. + * `String`. + * `@Remote` references. + * An array of primitive values or `String` or `@Remote` references. + * Lists of primitive values or `String` or `@Remote` references. +* Only public methods can be called. +* JMX/RMI can’t interact with suspend methods. +