---
name: jetbrains-bazel-test-migration
description: "Migrate IntelliJ JPS module tests to Bazel; debug Bazel-only failures."
license: "NOASSERTION"
metadata:
  decimalai-skill-id: "3c630848-f6bd-4d53-a707-83d86c398807"
  decimalai-version-id: "ed40a9dd-cf18-448d-9c85-80dc27e3d030"
  decimalai-version: "4"
  decimalai-body-sha256: "197f63a7eefc4ea5c553aaa30d9f9db6de736c3e67597a6253a6652898178e67"
  decimalai-name: "jetbrains/bazel-test-migration"
  decimalai-format: "1"
  decimalai-invocation: "model"
  decimalai-category: "testing"
  decimalai-source: "https://app.decimal.ai/s/jetbrains-bazel-test-migration@4/SKILL.md"
---
<!-- Generated by community/.ai/render-guides.mjs; edit community/.agents/skills/bazel-test-migration/SKILL.md -->

# Bazel Test Migration

Use this skill to migrate a JPS test module, fix a Bazel-only failure, or review a migration.
Migrate the complete module. Keep existing test behavior unless a failure proves that the test depends on an invalid environment assumption.

## Establish the Baseline

- Inspect the current branch, test framework, `.iml`, and generated target. Use earlier migration commits as references, not patches to apply unchanged.
- Identify the module that contains the tests. From Ultimate, use `@community//...` for Community targets. From standalone Community, use `//...`.
- Record known failures and the user's exclusions from the task. Do not fix unrelated failures or silently remove them from the run.
- Use existing CI results or an initial target run to establish the failures. During debugging, use a class or method filter.

For normal test commands, read the [testing skill](../testing/SKILL.md).
During migration, run the Bazel target directly if `bt` refuses a module that is not yet marked as migrated.

## Configure the Target

Keep `.iml` as the dependency source. Follow the [module dependencies skill](../module-dependencies/SKILL.md) for registration and generation.

- Use `scope="RUNTIME"` for plugins needed only for runtime loading, descriptors, extensions, or resources. Do not add them as `TEST` merely because tests need them.
- Keep APIs required to compile test sources in the appropriate compile or `TEST` scope.
- Load the owning plugin or wrapper when its descriptor is required. Do not manually register production extensions in test setup.
- Fix a production descriptor only if its dependency is also wrong in production. An incomplete test product usually needs a test module dependency.
- Keep custom `jps_test` declarations outside generated sections. Preserve the existing `runtime_deps`, `tags`, `timeout`, `env`, `jvm_flags`, and `data`.

Protect a custom test section with the exact module name:

```starlark
### skip generation section `test module.name`
```

Register changed modules and regenerate from the Ultimate root:

```bash
./community/tools/bun.cmd build/jps-module.mjs register path/to/module.iml --fix-iml-eof
./build/jpsModelToBazel.cmd
```

In standalone Community, follow its registration instructions and run `./build/jpsModelToBazelCommunityOnly.cmd`.
Do not patch missing jars or descriptors into runfiles with `copy_file`.

## Resolve Test Inputs

Use all three parts of the test data contract:

1. Declare the required files in a `filegroup`, or reuse an existing one.
2. Add that target to the test's `data`.
3. Resolve the runtime path through an existing helper or `BazelTestUtil.getFileFromBazelRuntime(BazelLabel)`.

Prefer a helper such as `JavaTestUtil.getJavaTestDataPath()` when it already supports Bazel.
Keep the existing non-Bazel behavior. Check static fields, companion properties, and serialization inputs as well as fixture path overrides.

- Keep the path returned by the runfiles resolver, including manifest-based results. Do not use `toRealPath()` to redirect test data back to the checkout.
- Do not construct paths from `PathManager.getHomePath()`, `community+`, or `_main` under Bazel. The resolver handles repository mapping.
- Preserve relative-path API contracts. When a fixture joins a base path to the repository root, override its absolute `getTestDataPath()` instead.
- A filegroup declares files; it does not rename them. Check that the requested label path exists among the runtime inputs.
- Treat test data and downloaded archives as read-only. Copy projects or unpack archives into a unique temporary directory before modifying them.

Read [test data and writable files](references/recipes.md#test-data-and-writable-files) for examples and VFS access handling.
For downloads or child builds, read [external inputs](references/recipes.md#external-inputs) and [nested builds](references/recipes.md#nested-builds).

## Debug Focused Failures

Run the failing class with fresh test results:

```bash
./bazel.cmd test --cache_test_results=no \
  --test_filter='com.example.ExampleTest' \
  @community//path/to/package:target_test
```

Use `com.example.ExampleTest#testMethod` for one method.
Avoid repeated full-module runs while diagnosing a focused failure.

- Read `test.log`, `idea.log`, and JUnit XML. Inspect the actual command, environment, and declared inputs before changing assertions.
- Distinguish missing input or plugin wiring from behavior failures. Use [failure diagnosis](references/recipes.md#failure-diagnosis) for common cases.
- If a test passes alone, check shared state and project reuse. Restore settings and include relevant configuration in fixture cache identity.
- Fix a shared helper when it owns the defect. Avoid repeated test-local patches for the same helper bug.
- Keep broad platform or JDK fixes separate when they need independent review. A temporary test-local workaround must preserve the test's purpose and identify the follow-up.
- Keep existing assertions and coverage. Do not add exclusions, assumptions, or disabled tests merely to make the migration green.
- Use assumptions only for genuine environment restrictions. Declare required environment variables in the target instead of relying on the developer's shell.

## Verify the Complete Target

Remove diagnostic selectors and run the exact target without a test filter:

```bash
./bazel.cmd test --cache_test_results=no @community//path/to/package:target_test
```

- Confirm that tests actually ran. A selected method can pass even when normal discovery misses its class.
- Check the test library and discovery roots before changing placement. Adding a dependency does not guarantee that its tests are discovered.
- Separate framework tests into a dedicated module or Bazel package when their current placement mixes framework code and executable tests.
- Do not use a growing class whitelist to compensate for incorrect placement. Keep the new module with its natural owner.
- Prefer `sandbox = True` once inputs and writable locations are declared. Preserve an existing sandbox; document any remaining exception.
- Check affected JPS or IDE runs when changing shared helpers. Check relevant CI platforms because local success does not prove portable path handling.

See [discovery and sandbox checks](references/recipes.md#discovery-and-sandbox-checks) for details.

## Complete the Switch

- Select complete modules through the target tags and CI configuration. Do not migrate only the convenient classes in a module.
- For a CI rollout, compare actual test coverage before removing the JPS run. Follow [CI coverage comparison](references/recipes.md#ci-coverage-comparison).
- Check CI and Safe-Push selection separately. Update their target lists or selectors within the requested scope; keep JPS coverage for modules not yet migrated.
- Add the module to [the migrated-module list](../../../build/bazel-migrated-test-modules.txt) only after verification and replacement coverage are established.
- The list makes `tests.cmd` refuse migrated modules. Do not assume it configures every CI build or automatically removes every JPS invocation.
- Verify generated metadata, run the required format checks, and run `git diff --check`.
- Report the focused and complete runs, known failures, and any unverified CI coverage. Do not describe a run as green when known failures remain.

Keep test data resolution changes separate from configuration changes when that makes review easier.
Put independently reviewed framework fixes in separate commits when requested.
