Agent SkillsDetachHead/rebased › driver-ui-tests

driver-ui-tests

GitHub

提供基于IDE Starter和UI Driver框架编写UI测试的指南,涵盖导入、结构及页面对象模式。

.claude/skills/driver-ui-tests/SKILL.md DetachHead/rebased

触发场景

创建或修改UI测试 实现来自testops的用例

安装

npx skills add DetachHead/rebased --skill driver-ui-tests -g -y
更多选项

非标准路径

npx skills add https://github.com/DetachHead/rebased/tree/master/.claude/skills/driver-ui-tests -g -y

不安装直接使用

npx skills use DetachHead/rebased@driver-ui-tests

指定 Agent (Claude Code)

npx skills add DetachHead/rebased --skill driver-ui-tests -a claude-code -g -y

安装 repo 全部 skill

npx skills add DetachHead/rebased --all -g -y

预览 repo 内 skill

npx skills add DetachHead/rebased --list

SKILL.md

Frontmatter
{
    "name": "driver-ui-tests",
    "description": "Guide for writing UI tests using IDE Starter and UI Driver frameworks. Use when creating or modifying UI tests or when user ask to implement test case from testops."
}

Driver UI Tests Guide

Guidelines for writing UI tests using IDE Starter and UI Driver frameworks.

Common Imports

// Driver core
import com.intellij.driver.client.Driver
import com.intellij.driver.sdk.waitForProjectOpen
import com.intellij.driver.sdk.advancedSettings

// Test utilities
import com.intellij.driver.tests.utils.waitForIndicators
import com.intellij.driver.tests.utils.Plugin
import com.intellij.driver.tests.utils.PluginInstaller
import com.intellij.driver.tests.utils.Plugins

// IDE Starter framework
import com.intellij.ide.starter.driver.runIdeTest
import com.intellij.ide.starter.ide.IDETestContext
import com.intellij.ide.starter.models.IDEStartResult
import com.intellij.ide.starter.models.VMOptions
import com.intellij.ide.starter.runner.IDERunContext
import com.intellij.ide.starter.runner.Starter
import com.intellij.ide.starter.utils.catchAll

// Extended test infrastructure
import com.intellij.ide.starter.extended.allure.AllureHelperExtended.step
import com.intellij.ide.starter.extended.allure.Subsystems
import com.intellij.ide.starter.extended.engine.newTestContainerExtended
import com.intellij.ide.starter.extended.engine.TestContainerExtended
import com.intellij.ide.starter.extended.license.StagingLicenseGenerator.licenseProductCode
import com.intellij.ide.starter.extended.loadMetadataFromServer
import com.intellij.ide.starter.extended.setupTestMetadataSchemeWithGroupsFromCode

// Test framework
import com.intellij.testFramework.TestApplicationManager

Test Structure

  • Tests use JUnit 5 with an IDE Starter framework and UI Driver framework (community/platform/remote-driver)
  • Test case projects are represented by the com.intellij.ide.starter.models.TestCase see src/com/intellij/ide/starter/project
  • Tests run against specific IDE (community/tools/intellij.tools.ide.starter/src/com/intellij/ide/starter/ide/IdeProductProvider.kt)

Test project examples

See tests/intellij.ide.starter.extended/src/com/intellij/ide/starter/extended/data/cases

Page Object Pattern or UiComponent

Page objects extend UiComponent with ComponentData constructor:

class MyPageObject(data: ComponentData) : UiComponent(data) {
    val myButton = x { byAccessibleName("Button Name") }
    val myPanel = x { byClass("PanelClassName") }

    fun clickMyButton() {
        myButton.click()
    }
}

// Extension function on Finder to create the page object
fun Finder.myPageObject(): MyPageObject = x(
    xQuery { byAccessibleName("Root Element Name") }, MyPageObject::class.java
)

// Use specific ui component to specify the context of the search
fun AnotherPageObject.myPageObject(): MyPageObject = x(
  xQuery { byAccessibleName("Root Element Name") }, MyPageObject::class.java
)

Element Selectors

Selector Usage
byAccessibleName("name") Find by accessible name attribute
byClass("ClassName") Find by Swing/AWT class name
byVisibleText("text") Find by visible text content

UI test examples

See directory tests/remote-driver-tests

Common UI Components

See directory community/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui

Scoping Element Searches

When multiple elements match a selector, scope to a parent element:

// BAD - will fail if multiple InstallButtons exist
ui.x { byClass("InstallButton") }.click()

// GOOD - scope to a parent element first
val detailPane = ui.x { byClass("PluginDetailsPageComponent") }
detailPane.x { byClass("InstallButton") }.click()

Keyboard Interactions

element.keyboard { typeText("search text") }
ui.keyboard { key(KeyEvent.VK_ENTER) }
ui.keyboard { hotKey(KeyEvent.VK_META, KeyEvent.VK_COMMA) }  // Cmd+,

Writing Tests

Required Annotations

Every UI test must have the following annotations at the class level:

Annotation Purpose TestOps Custom Field
@Subsystems.* Categorizes the test by subsystem Subsystem
@Features.* Specifies the feature being tested Feature
@Components.* Identifies the component under test Component

For tests linked to TestOps test cases, also add:

  • @AllureId("test_case_id") - Links the test to the TestOps test case ID

The annotation values should match the corresponding TestOps custom fields (Subsystem, Feature, Component).

Available annotations: See tests/intellij.ide.starter.extended.allure/src/com/intellij/ide/starter/extended/allure/Annotations.kt

Example with TestOps test case:

@Subsystems.Java
@Features.Completion
@Components.Editor
class MyTestFromTestOps {

    @Test
    @AllureId("318541")  // Required when test case exists in TestOps
    fun `my test from testops`(testInfo: TestInfo) {
        // ...
    }
}

Example for new test (not yet in TestOps):

@Subsystems.UI
@Features.PluginManager
@Components.Miscellaneous
class MyNewTest {

    @Test
    fun `my new test`(testInfo: TestInfo) {
        // ...
    }
}

Basic Test Structure

@Subsystems.Java
@Features.Completion
@Components.Editor
class MyTest {
    val testCase = TestCase(IdeProductProvider.IU, myProject)

    @Test
    @AllureId("123456")  // Required if test case exists in TestOps
    fun `my test name`(testInfo: TestInfo) {
        val context = Starter.newContext(testName = "TestName", testCase = testCase)

        context.applyVMOptionsPatch {
            addSystemProperty("ide.ui.non.modal.settings.window", "true")
        }

        context.runIdeTest(testName = testInfo.displayName) {
            waitForIndicators(5.minutes)  // Wait for indexing to complete

            step("Step description") {
                // Test actions here
            }
        }
    }
}

Waiting for Project Import and Indexing

Always wait for indicators at the start of your test:

waitForIndicators()

This ensures the project is fully imported and indexed before interacting with the IDE.

Opening Files

Use openFile instead of UI-based file navigation:

// GOOD - Direct and reliable
openFile(relativePath = "src/Main.java")

// AVOID - UI-based approach is slower and more fragile
invokeAction("GotoFile", now = false)
ui.keyboard { typeText("Main.java") }
ui.keyboard { key(KeyEvent.VK_ENTER) }

invokeAction: now Parameter

The now parameter controls whether the action completes before continuing:

// now = true: Waits for action to complete (use when keyboard input follows)
invokeAction("ToggleBookmarkWithMnemonic", now = true)
ui.keyboard { key(KeyEvent.VK_1) }  // This input goes to the bookmark dialog

// now = false: Returns immediately (use when waiting for UI to appear)
invokeAction("ShowSettings", now = false)
ui.x { byClass("SettingsDialog") }.shouldBe { present() }

Rule: Use now = true when the next step is keyboard input to prevent input going to the wrong component. Rule: Use now = false when you expect to the UI dialog to appear.

Custom Wait Conditions

Use waitFor to wait for specific conditions:

waitFor("description of what we're waiting for", 30.seconds) {
    ui.x { byClass("MyComponent") }.present()
}

waitFor("text to appear", 10.seconds) {
    ui.x { byClass("Tree") }.hasText("expected text")
}

Running Tests from Terminal

Driver tests require a fully built IDE. There are several ways to run them:

Option 1: Using tests.cmd (Recommended)

The tests.cmd script builds the IDE from sources and runs tests. Recommended for dev server mode.

Example:

./tests.cmd \
  --module intellij.driver.tests \
  --test com.intellij.driver.tests.idea.java.FindAndGoToTest

Key parameters:

  • --test - fully qualified test class name (or pattern)
  • --module intellij.driver.tests - required for driver tests

Example with specific test:

./tests.cmd \
  --module intellij.driver.tests \
  --test com.intellij.driver.tests.idea.ultimate.httpclient.BuiltInHttpClientBrotliCompressionUiTest

Debugging Test Failures

Output Locations

After test failure, check:

  • UI hierarchy: out/ide-tests/tests/{IDE-version}/{TestName}/{test-method}/log/ui-hierarchy/ui.html
  • IDE log: out/ide-tests/tests/{IDE-version}/{TestName}/{test-method}/log/idea.log
  • Screenshots: out/ide-tests/tests/{IDE-version}/{TestName}/{test-method}/log/screenshots/
  • Exceptions: out/ide-tests/tests/{IDE-version}/{TestName}/{test-method}/error/

Common Issues

  1. Element Not Found: Check UI hierarchy HTML for the correct accessible name or class
  2. Multiple Elements Match: Scope search to parent element

Critical Rules

  • Never use Thread.sleep() or delay() - Driver framework automatically waits for UI elements
  • Wrap test logic in step("description") { } for better logs
  • Verify assertions actually fail – Comment out the action being tested and confirm the test fails. If it still passes, your assertion is too weak.
  • Use common UI components – create new if necessary
  • Always check UI hierarchy to understand the UI state when a test fails

版本历史

  • 1f8708d 当前 2026-08-16 15:39

同 Skill 集合

.agents/skills/actions/SKILL.md
.agents/skills/code-style/SKILL.md
.agents/skills/commits/SKILL.md
.agents/skills/debugging/SKILL.md
.agents/skills/driver-ui-tests/SKILL.md
.agents/skills/eel/SKILL.md
.agents/skills/extract-module/SKILL.md
.agents/skills/module-dependencies/SKILL.md
.agents/skills/module-set-pluginization/SKILL.md
.agents/skills/notebook-for-experiment/SKILL.md
.agents/skills/pseudo-kmp/SKILL.md
.agents/skills/registry/SKILL.md
.agents/skills/remote-dev/SKILL.md
.agents/skills/safe-push/SKILL.md
.agents/skills/ssr/SKILL.md
.agents/skills/testing-internals/SKILL.md
.agents/skills/testing/SKILL.md
.agents/skills/ui-accessibility/SKILL.md
.agents/skills/writing-tests/SKILL.md
.claude/skills/actions/SKILL.md
.claude/skills/code-style/SKILL.md
.claude/skills/commits/SKILL.md
.claude/skills/debugging/SKILL.md
.claude/skills/eel/SKILL.md
.claude/skills/extract-module/SKILL.md
.claude/skills/jewel-pr-preparer/SKILL.md
.claude/skills/jewel-release-helper/SKILL.md
.claude/skills/managing-youtrack/SKILL.md
.claude/skills/module-dependencies/SKILL.md
.claude/skills/module-set-pluginization/SKILL.md
.claude/skills/notebook-for-experiment/SKILL.md
.claude/skills/pseudo-kmp/SKILL.md
.claude/skills/registry/SKILL.md
.claude/skills/remote-dev/SKILL.md
.claude/skills/safe-push/SKILL.md
.claude/skills/ssr/SKILL.md
.claude/skills/testing-internals/SKILL.md
.claude/skills/testing/SKILL.md
.claude/skills/ui-accessibility/SKILL.md
.claude/skills/writing-tests/SKILL.md

元信息

文件数
0
版本
1f8708d
Hash
1240a6cc
收录时间
2026-08-16 15:39

首页 - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-17 06:19
浙ICP备14020137号-1 $访客地图$