IntelliJ `AnAction` 클래스를 구현하거나 수정하고 `plugin.xml`에 등록하도록 안내합니다. 표시 이름과 설명은 메시지 번들에 두고, 필요하면 아이콘을 설정하며, 이벤트 코루틴 범위에서 중단 함수를 실행해 동기식 처리로 IDE가 멈추는 일을 방지합니다.
- IDE 메뉴에 새 동작 추가
- 동작 등록이나 아이콘 변경
- 동작 이름과 설명 정리
이 가이드는 IntelliJ 테스트가 `bt.cmd` 또는 `tests.cmd`에서 Bazel과 JUnit을 거쳐 실행되는 경로를 추적합니다. 테스트 누락이나 잘못된 선택, 빌드 실패, 메모리 문제와 디버거 설정을 문서에 나온 실행기 내부 구조와 옵션을 바탕으로 조사합니다.
Debug IntelliJ `bt.cmd` and `tests.cmd` runs, discovery, and runner internals.
실행 점수 미검증
설치 방법 보기이 가이드는 IntelliJ의 bt.cmd와 tests.cmd에서 Bazel과 JUnit을 거쳐 테스트가 실행되는 경로를 따라가며 실행 문제를 조사합니다. 테스트를 찾지 못할 때는 클래스 이름 패턴과 클래스 경로를 확인하고, 예상과 다른 테스트가 실행될 때는 그룹 설정이나 병렬 실행의 분배 방식을 살펴봅니다. 빌드 실패 시 의존성과 BUILD.bazel 동기화를 확인하는 방법, 메모리 부족 시 JVM 설정, 디버거 연결에 쓰는 속성도 설명합니다.
테스트 클래스가 있는데 실행되지 않거나, 지정한 테스트와 다른 테스트가 실행되거나, 테스트 시작 전에 Bazel에서 실패할 때 활용할 수 있습니다. 실행 스크립트부터 테스트 검색과 JVM 시작까지 어느 단계를 확인할지 파악하는 데 도움이 됩니다.
tests.cmd에서 테스트를 찾지 못하는 이유를 조사해 주세요.”IntelliJ 저장소의 테스트 실행 방식을 전제로 합니다. 명령과 설정 속성은 문서에 나온 bt.cmd, tests.cmd, Bazel, JUnit 경로에 해당합니다.
이 소개문은 공개된 SKILL.md를 바탕으로 AI(OpenAI Codex)가 작성했습니다. 정확한 사양은 아래 원문을 확인하세요.
AI가 SKILL.md의 내용에서 주의가 필요한 작업과 도입 전제를 확인했습니다. 점수는 실제로 실행한 결과(실행 검증)만으로 매깁니다.
점수에는 넣지 않았습니다. 2026년 10월 28일 기준으로 AI(OpenAI Codex)가 판정했습니다. 참고용이므로 설치 전에 원문도 확인해 주세요.
설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
This document explains tests.cmd internals and helps troubleshoot test execution issues.
The test execution chains:
bt.cmd → bazel test <jps_test label> → JUnit5BazelRunner
tests.cmd → Bazel → IdeaUltimateRunTestsBuildTarget → TestingTasksImpl → JUnit 5
A module of the migrated list or of a bt.json area runs through bt. Every other module runs through tests.cmd.
Key components:
//build:local_idea_ultimate_run_tests_build_target-Dintellij.build.test.* system propertiesSymptoms:
Causes & Solutions:
Pattern mismatch - Simple class names don't work (see Pattern Matching below):
# WRONG - simple name won't match FQN
-Dintellij.build.test.patterns=MyTest
# CORRECT - use wildcard or FQN
-Dintellij.build.test.patterns=*MyTest
-Dintellij.build.test.patterns=com.example.MyTest
Test not in classpath - The test class must be in a module that's part of the test classpath. Check if the module is included in the build.
Test class not recognized - Ensure class has JUnit annotations.
Solution: Increase heap size:
./tests.cmd \
--module <module> \
--test MyTest \
-Dintellij.build.test.jvm.memory.options=-Xmx8g
Symptoms:
Solutions:
Check module dependencies - Ensure test module has required dependencies in .iml file.
Verify BUILD.bazel is synced - Run ./build/jpsModelToBazel.cmd after changing .iml files.
Note: Bazel incremental builds are always correct. Do not use bazel clean - it won't help.
Symptoms:
Debug steps:
Check test groups - If using groups, verify testGroups.properties configuration.
Check bucketing - For parallel execution, tests are distributed by hash:
# See which bucket a test falls into
-Didea.test.runners.count=4
-Didea.test.runner.index=0 # Run only bucket 0
Check class filters - TestCaseLoader applies pattern matching before test execution.
Enable debug mode to attach a debugger:
./tests.cmd \
--module <module> \
--test MyTest \
-Dintellij.build.test.debug.enabled=true \
-Dintellij.build.test.debug.port=5005 \
-Dintellij.build.test.debug.suspend=true
Then attach debugger to port 5005.
| Property | Purpose |
|---|---|
intellij.build.test.patterns | Test class patterns (semicolon-separated) |
intellij.build.test.groups | Test groups to run |
intellij.build.test.attempt.count | Retry count for flaky tests |
intellij.build.test.jvm.memory.options | JVM memory settings |
intellij.build.test.debug.enabled | Enable remote debugging |
┌─────────────────────────────────────────────────────────────────────────────┐
│ 1. COMMAND LINE │
│ ./tests.cmd --module <module> --test MyTest │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 2. SHELL SCRIPT │
│ tests.cmd → community/build/run_build_target.sh │
│ Maps --module/--test to -D properties, wraps as --jvm_flag=<arg> │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 3. BAZEL │
│ bazel run //build:local_idea_ultimate_run_tests_build_target │
│ (defined in build/BUILD.bazel) │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 4. BUILD TARGET ENTRY POINT │
│ IdeaUltimateRunTestsBuildTarget.main() │
│ → UltimateProjectTestingTasks.runTests() │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 5. TEST OPTIONS PARSING │
│ UltimateProjectTestingOptions (extends TestingOptions) │
│ Reads all -Dintellij.build.test.* system properties │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 6. TEST EXECUTION ORCHESTRATION │
│ TestingTasksImpl.runTests() │
│ - Builds test classpath │
│ - Prepares JVM arguments and system properties │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 7. FORKED TEST PROCESS │
│ TestingTasksImpl.runJUnit5Engine() │
│ Spawns new JVM with bootstrap classpath │
└─────────────────────────────────────────────────────────────────────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌───────────────────────────────────┐ ┌───────────────────────────────────────┐
│ 8a. JUNIT 5 TESTS │ │ 8b. JUNIT 3/4 TESTS (Legacy) │
│ JUnit5TeamCityRunner.main() │ │ JUnit5TeamCityRunner.main() │
│ - Uses JUnit Platform Launcher │ │ - Uses JUnit Platform Launcher │
│ - ClassNameFilter │ │ - ClassNameFilter │
│ - PostDiscoveryFilter │ │ - PostDiscoveryFilter │
└───────────────────────────────────┘ └───────────────────────────────────────┘
│ │
└───────────────┬───────────────┘
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 9. TEST DISCOVERY & FILTERING │
│ TestCaseLoader │
│ - Loads test classes from classpath roots │
│ - Applies pattern/group filters │
│ - Handles bucketing for parallel execution │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 10. TEST EXECUTION │
│ JUnit Platform executes tests │
│ TCExecutionListener reports results to TeamCity │
└─────────────────────────────────────────────────────────────────────────────┘
| Class | Purpose |
|---|---|
IdeaUltimateRunTestsBuildTarget | Ultimate tests entry point, calls UltimateProjectTestingTasks |
CommunityRunTestsBuildTarget | Community tests entry point, calls TestingTasks |
UltimateProjectTestingTasks | Ultimate-specific test orchestration (YourKit, network restrictions) |
TestingTasks | Interface for test execution |
TestingTasksImpl | Core test execution logic |
| Class | Purpose |
|---|---|
TestingOptions | Base class for all test options. Parses -Dintellij.build.test.* properties |
UltimateProjectTestingOptions | Ultimate-specific options (YourKit, skip community tests) |
| Class | Purpose |
|---|---|
JUnit5TeamCityRunner | Runs JUnit 3/4 tests using the JUnit Vintage test engine, or JUnit5 tests using the JUnit Jupiter test engine |
TCExecutionListener | Reports test results to TeamCity via service messages |
| Class | Purpose |
|---|---|
TestCaseLoader | Discovers and filters test classes |
TestAll | JUnit 3 test suite, collects all tests |
TestClassesFilter | Pattern/group-based test filtering |
| Class | Purpose |
|---|---|
BucketingScheme | Interface for test distribution |
HashingBucketingScheme | Default: hash-based distribution |
TestsDurationBucketingScheme | Duration-aware distribution |
| Product | Entry Point | Default mainModule | Source |
|---|---|---|---|
| IDEA Ultimate | IdeaUltimateRunTestsBuildTarget | intellij.idea.ultimate.tests.main | build/src/ |
| Community | CommunityRunTestsBuildTarget | intellij.idea.community.main.tests | community/build/src/ |
| RustRover | RustRoverRunTestsBuildTarget | intellij.idea.ultimate.tests.main | rustrover/build/src/ |
| RubyMine | RubyRunTestsBuildTarget | intellij.idea.ultimate.tests.main | ruby/build/src/ |
| CLion | CLionRunTestsBuildTarget | intellij.idea.ultimate.tests.main | CIDR/clion-build/src/ |
Note: Product entry points (RustRover, RubyMine, CLion) inherit intellij.idea.ultimate.tests.main as the default, but to run product-specific tests, use the dedicated test module via --module. See TESTING.md for the correct module per product.
From intellij-teamcity-config/.teamcity/src/ijplatform/KnownModules.kt:
| CI Constant | Module Name |
|---|---|
ULTIMATE_TESTS | intellij.idea.ultimate.tests.main |
COMMUNITY_MAIN | intellij.idea.community.main.tests |
GOLAND_TESTS | intellij.goland.tests |
PYTHON_TESTS | intellij.python.tests |
PHPSTORM_MAIN | intellij.phpstorm.main.tests |
CLION_MAIN | intellij.clion.main.tests |
RUSTROVER_MAIN | intellij.rustrover.main.tests |
KOTLIN_TESTS | intellij.kotlin.tests |
KOTLIN_ULTIMATE_ALL_TESTS | intellij.kotlin-ultimate.all-tests |
DATABASE_TESTS | intellij.database.tests |
DATABASE_SQL_TESTS | intellij.database.sql.tests |
Default mainModule is set in:
UltimateProjectTestingOptions.kt:36 - Ultimate: intellij.idea.ultimate.tests.mainCommunityRunTestsBuildTarget.kt:28 - Community: intellij.idea.community.main.testsintellij.idea.ultimate.tests.main
├── intellij.idea.ultimate.tests
├── intellij.idea.ultimate.tests.kotlin
├── intellij.platform.tests
├── intellij.java.tests
└── ... (hundreds of test modules)
Separate hierarchies (NOT in .main):
├── intellij.idea.ultimate.tests.kotlin.k2
│ └── intellij.devkit.kotlin.fir.tests
├── intellij.idea.ultimate.tests.devBuildTests
└── intellij.kotlin.tests
Most options use the intellij.build.test.* prefix. Bucketing uses idea.test.* prefix.
// Test selection (mutually exclusive, in priority order)
testConfigurations // -Dintellij.build.test.configurations=<config>
testPatterns // -Dintellij.build.test.patterns=<pattern>
testGroups // -Dintellij.build.test.groups=<group>
// Test execution
mainModule // -Dintellij.build.test.main.module=<module>
attemptCount // -Dintellij.build.test.attempt.count=<n>
// JVM configuration
jvmMemoryOptions // -Dintellij.build.test.jvm.memory.options=<opts>
customRuntimePath // -Dintellij.build.test.jre=<path>
// Debugging
isDebugEnabled // -Dintellij.build.test.debug.enabled=<bool>
debugPort // -Dintellij.build.test.debug.port=<port>
isSuspendDebugProcess // -Dintellij.build.test.debug.suspend=<bool>
// Bucketing (parallel execution) - NOTE: uses idea.test.* prefix
bucketsCount // -Didea.test.runners.count=<n>
bucketIndex // -Didea.test.runner.index=<n>
// Coverage
enableCoverage // -Dintellij.build.test.coverage.enabled=<bool>
coveredClassesPatterns // -Dintellij.build.test.coverage.include.class.patterns=<patterns>
The test target is defined in build/BUILD.bazel:
java_binary(
name = "local_idea_ultimate_run_tests_build_target",
runtime_deps = [":build"],
main_class = "IdeaUltimateRunTestsBuildTarget",
data = ALL_ULTIMATE_TARGETS + [BAZEL_TARGETS_JSON_ULTIMATE],
jvm_flags = [
"-Dintellij.build.console.exporter.to.temp.file=true",
"-Dintellij.build.console.messages.verbose=false",
"-Dintellij.build.clean.output.root=false", # Reuse compiled classes
"-Dintellij.build.use.compiled.classes=true", # Skip recompilation
"-Dintellij.build.bazel.targets.json.file=$(rlocationpath %s)" % BAZEL_TARGETS_JSON_ULTIMATE,
],
add_opens = INTELLIJ_ADD_OPENS,
)
TestingTasksImpl.prepareEnvForTestRun() configures the forked test JVM:
// Key system properties set for test process:
"idea.home.path" → projectHome
"idea.config.path" → tempDir/config
"idea.system.path" → tempDir/system
"java.io.tmpdir" → tempDir
// JVM options:
"-XX:+HeapDumpOnOutOfMemoryError"
"-XX:HeapDumpPath=<snapshotsDir>/intellij-tests-oom-<timestamp>.hprof"
"-Xms750m -Xmx1024m" // or custom from jvmMemoryOptions
// Plus --add-opens for module access
There are two mechanisms for passing JVM arguments to the test JVM process:
intellij.build.test.jvm.memory.options)For JVM memory settings like heap size, use the dedicated property:
./tests.cmd --module <module> --test <pattern> -Dintellij.build.test.jvm.memory.options="-Xmx4g -Xms2g"
Multiple options are space-separated within quotes. These options are added to the beginning of the JVM arguments via VmOptionsGenerator.generate().
Implementation (see TestingTasksImpl.kt, runJUnit5Engine method):
val customMemoryOptions = options.jvmMemoryOptions?.trim()?.split(Regex("\\s+"))?.takeIf { it.isNotEmpty() }
jvmArgs.addAll(
index = 0,
elements = VmOptionsGenerator.generate(
customVmMemoryOptions = if (customMemoryOptions == null) mapOf("-Xms" to "750m", "-Xmx" to "1024m") else emptyMap(),
additionalVmOptions = customMemoryOptions ?: emptyList(),
// ... other parameters omitted
),
)
pass.* prefix)To pass arbitrary system properties to the test JVM, use the pass. prefix. The prefix is stripped before passing to the test process:
./tests.cmd --module <module> --test <pattern> -Dpass.my.custom.property=value -Dpass.some.flag=true
Results in test JVM receiving:
-Dmy.custom.property=value-Dsome.flag=trueImplementation (see TestingTasksImpl.kt, prepareEnvForTestRun method):
for ((key, value) in System.getProperties()) {
key as String
if (key.startsWith("pass.")) {
systemProperties.put(key.substring("pass.".length), value as String)
}
}
This is a TeamCity convention for passing properties to nested processes.
./tests.cmd \
--module <module> \
--test MyTest \
-Dintellij.build.test.jvm.memory.options="-Xmx4g" \
-Dpass.my.test.flag=enabled \
-Dpass.debug.level=verbose
Important: Properties without pass. prefix are consumed by the build scripts, NOT passed to the test JVM.
┌─────────────────────────────────────────────────────────────────────────────┐
│ PATTERN INPUT │
│ -Dintellij.build.test.patterns=*MyTest │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ PATTERN COMPILATION (TestClassesFilter.compilePattern) │
│ filter.replace("$","\\$").replace(".","\\.");replace("*",".*") │
│ "*MyTest" → ".*MyTest" │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ CLASS DISCOVERY (ClassFinder) │
│ Scans JARs for *Test.class files, extracts FQN: │
│ org/example/MyTest.class → "org.example.MyTest" │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ PATTERN MATCHING (PatternListTestClassFilter.matches) │
│ pattern.matcher(className).matches() ← FULL STRING MATCH │
│ ".*MyTest".matches("org.example.MyTest") → true │
└─────────────────────────────────────────────────────────────────────────────┘
| Input Pattern | Compiled Regex | Matches org.example.MyTest? |
|---|---|---|
MyTest | MyTest | ❌ NO (not full match) |
*MyTest | .*MyTest | ✅ YES |
org.example.MyTest | org\.example\.MyTest | ✅ YES |
org.example.* | org\.example\..* | ✅ YES |
* | .* | ✅ YES (matches all) |
Pattern Compilation (TestClassesFilter.compilePattern()):
filter = filter.replace("$", "\\$").replace(".", "\\.").replace("*", ".*");
return Pattern.compile(filter);
Pattern Matching (PatternListTestClassFilter.matches()):
return ContainerUtil.exists(patterns, pattern -> pattern.matcher(className).matches());
matches() NOT find() - requires ENTIRE string to matchClassNameFilter (JUnit 5) - Fast pre-filter on class names
TestCaseLoader.isClassNameIncluded(className)PostDiscoveryFilter (JUnit 5) - Post-discovery filter
TestCaseLoader.isClassIncluded(className)TestCaseLoader.fillTestCases() (JUnit 3/4) - Scans classpath roots
ClassFinder to find all *Test.class filesisPotentiallyTestCase() which calls filter's matches()testGroups.propertiesRoot Cause: Pattern.matches() requires the ENTIRE string to match.
// Pattern: "MyTest" → Regex: "MyTest"
// className: "org.example.MyTest"
"MyTest".matches("org.example.MyTest") // Returns FALSE
// Pattern: "*MyTest" → Regex: ".*MyTest"
".*MyTest".matches("org.example.MyTest") // Returns TRUE
This applies to ALL modules (default and non-default). Always use:
org.example.MyTest*MyTesttests.cmd (quick start, parameters, examples)@TestApplication, fixtures, EDT)아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
IntelliJ `AnAction` 클래스를 구현하거나 수정하고 `plugin.xml`에 등록하도록 안내합니다. 표시 이름과 설명은 메시지 번들에 두고, 필요하면 아이콘을 설정하며, 이벤트 코루틴 범위에서 중단 함수를 실행해 동기식 처리로 IDE가 멈추는 일을 방지합니다.
IntelliJ JPS 테스트 모듈을 Bazel로 옮기고 Bazel에서만 발생하는 실패를 조사하는 안내서입니다. 의존성, 플러그인, 테스트 데이터와 runfiles 문제를 확인하고 생성된 대상과 이전된 테스트를 검증합니다.
IntelliJ 프로젝트 규칙에 맞춰 Kotlin과 Java 코드를 작성하거나 검토합니다. 언어 선택, 서식, 봉인 타입, 스레드 주석, 제어 흐름 예외 처리를 확인합니다.
이 가이드는 IntelliJ 프로젝트의 변경 사항을 목적별로 나누고 프로젝트 형식에 맞는 커밋 메시지를 작성하도록 돕습니다. 티켓이 있으면 번호와 변경 설명을, 없으면 레이블과 하위 시스템명을 사용하며 필요에 따라 이유와 판단을 본문에 담습니다.
여러 Python 타입 검사기로 코드 조각이나 파일의 타입 추론과 오류 판정을 비교합니다. 도구별 결과, 실행 시간, 진단 내용을 Markdown 보고서로 모아 저장할 수 있습니다.
Compose Desktop 화면을 구성할 때 컴포저블은 렌더링을 맡고 프레젠터나 코디네이터는 앱 결정을 맡도록 구조를 정리합니다. 상태 소유권, Effect, 재사용 컴포넌트 API, 지연 목록 키, 애니메이션과 성능을 개별 UI 변경에 맞춰 살펴봅니다.