plugins/github-copilot-modernization/skills/modernization-integration-tests/SKILL.md
Run multi-layer integration tests for modernized Java applications. Supports 4 layers - Layer 1 (TestContainers), Layer 2 (Smoke Tests), Layer 3 (Azure Integration), Layer 4 (Behavioral Comparison). Java projects only - skip if source code is not Java. Triggers: "generate integration tests", "add integration tests", "create Layer 1 tests", "create Layer 2 tests" NOT for: unit tests, performance tests, load tests.
npx skillsauth add microsoft/github-copilot-modernization modernization-integration-testsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill supports Java projects only. If the source code is not Java (e.g., .NET, Python, Node.js), skip test generation and report that integration tests are not supported for this language.
./infra/infra-config.md or use request tool to obtain configuration..githubRead references/layer1-local-integration.md first, then create TestContainers-based integration test classes.
Read references/layer2-smoke-tests.md first. Layer 2 uses shell-based smoke tests with docker-compose, NOT JUnit test classes. Follow the exact multi-commit workflow (artifacts → auth → restore) documented in the reference file.
Read references/layer3-azure-integration.md first, then create integration test classes that connect to real Azure services.
Read references/layer4-behavioral-comparison.md first, then create comparison tests that validate behavior matches between old and new implementations.
{modernization-work-folder}/integration-tests/integration-test-plan.md that outlines:{modernization-work-folder}/integration-tests/integration-test-summary.md that documents:CRITICAL - Read Reference Docs First:
Analyze the project if integration tests have covered all components, if not DO ADD new integration tests by the following principles:
L1Test for Layer 1, L3Test for Layer 3, L4Test for Layer 4). Layer 2 does not use test classes.mvn verify (or equivalent build command) discovers and runs all tests without extra flags. If tests require -Dtest=... to be found, the build configuration is wrong.@Test annotation must be on a working test method.Add Layer 1 local integration tests). Generate runner scripts and include them in the same commit.When multiple layers coexist in the same project, tests must be distinguishable. Every layer MUST use a distinct class name suffix AND tag/category so tests from different layers never interfere with each other.
| Layer | Class Name Suffix | Example Class Name |
|-------|-------------------|--------------------|
| 1 | L1Test | BlobStorageL1Test, OrderServiceL1Test |
| 2 | N/A - No test classes | Layer 2 uses shell-based smoke tests, not test classes. See layer2-smoke-tests.md |
| 3 | L3Test | AzureSqlL3Test, BlobStorageL3Test |
| 4 | L4Test | OrderApiL4Test, UserServiceL4Test |
Test classes for Layers 1, 3, 4 MUST be annotated with a layer-specific tag so the runner script can filter precisely. Layer 2 does not use test classes (see layer2-smoke-tests.md).
| Layer | JUnit 5 | JUnit 4 |
|-------|---------|---------|
| 1 | @Tag("Layer1") | @Category(Layer1.class) |
| 2 | N/A - Shell-based | N/A - Shell-based |
| 3 | @Tag("Layer3") | @Category(Layer3.class) |
| 4 | @Tag("Layer4") | @Category(Layer4.class) |
Rule: Never rely solely on class name patterns for filtering. Always use tags/categories as the primary filter mechanism.
This is the most important rule in this entire skill — it applies to ALL layers.
Integration tests MUST use real TestContainers for layer 1 and 2 and real cloud services for Layer 3 for every migrated dependency. Do NOT mock or @MockBean the SDK client that the migrated code uses (e.g., ServiceBusTemplate, ServiceBusSenderClient, BlobServiceClient, RedisTemplate, DataSource). Instead, spin up a real container and wire the application's own service to it.
// ❌ WRONG — mocks the migrated service and SDK clients, tests unchanged code instead
@SpringBootTest
@ActiveProfiles("test")
class MyAppL1Test {
@MockBean private MessageService messageService; // THE MIGRATED CLASS — never tested!
@MockBean private ServiceBusSenderClient senderClient; // should be from real emulator
@MockBean private TokenCredential tokenCredential; // should be from emulator config
@Autowired private UserRepository userRepo; // unchanged code
@Test void testUserCrud() {
userRepo.save(new User("test")); // tests unchanged code, NOT the migration
}
}
// ✅ RIGHT — uses real Service Bus emulator, ALL beans wired from containers, tests through migrated service
@SpringBootTest
@ActiveProfiles("test")
@Testcontainers
class MyAppL1Test {
@Container static final GenericContainer<?> SERVICE_BUS = ...; // real emulator
// No @MockBean at all — all beans come from containers + @DynamicPropertySource
@Autowired private MessageService messageService; // THE MIGRATED CLASS — tested for real!
@DynamicPropertySource
static void props(DynamicPropertyRegistry registry) {
registry.add("spring.cloud.azure.servicebus.connection-string", () -> getConnectionString());
// ... other container-derived properties
}
@Test void testSendMessage() {
messageService.sendMessage("queue", "Hello"); // exercises the actual migrated code
}
}
When integration tests fail during execution, use this framework to determine whether to fix the test code or the source code:
Business Logic Violations
Test Implementation Issues
Test Failure
│
├─ Does test model realistic business scenario?
│ ├─ No → Fix Test Code
│ └─ Yes ↓
│
├─ Does source code violate business rules?
│ ├─ Yes → Fix Source Code
│ └─ No ↓
│
├─ Is test setup and environment correct?
│ ├─ No → Fix Test Code
│ └─ Yes ↓
│
└─ Does error show integration/logic problem?
├─ Yes → Fix Source Code
└─ No → Fix Test Code
After all tests are written, executed, and fixed to pass, generate a fixed runner script so users can re-run integration tests with a single command regardless of project type.
| Layer | Script Path | Command (Unix) | Command (Windows) |
|-------|-------------|----------------|--------------------||
| 1 | {modernization-work-folder}/integration-tests/run-layer1-tests.sh / .ps1 | bash {modernization-work-folder}/integration-tests/run-layer1-tests.sh | powershell {modernization-work-folder}/integration-tests/run-layer1-tests.ps1 |
| 2 | {modernization-work-folder}/integration-tests/run-layer2-tests.sh / .ps1 | bash {modernization-work-folder}/integration-tests/run-layer2-tests.sh | powershell {modernization-work-folder}/integration-tests/run-layer2-tests.ps1 |
| 3 | {modernization-work-folder}/integration-tests/run-layer3-tests.sh / .ps1 | bash {modernization-work-folder}/integration-tests/run-layer3-tests.sh | powershell {modernization-work-folder}/integration-tests/run-layer3-tests.ps1 |
| 4 | {modernization-work-folder}/integration-tests/run-layer4-tests.sh / .ps1 | bash {modernization-work-folder}/integration-tests/run-layer4-tests.sh | powershell {modernization-work-folder}/integration-tests/run-layer4-tests.ps1 |
.sh and .ps1 variants for cross-platform support.✅ Layer 1 integration tests PASSED❌ Layer 1 integration tests FAILEDLayers 1, 3, 4 use tag/category filters to execute test classes. Layer 2 uses shell commands (see layer2-runner-script-templates.md).
| Layer | Maven | Gradle |
|-------|-------|--------|
| 1 | mvn verify -Dgroups=Layer1 | ./gradlew test -Dgroups=Layer1 |
| 2 | Shell-based smoke tests | Shell-based smoke tests |
| 3 | mvn verify -Dgroups=Layer3 | ./gradlew test -Dgroups=Layer3 |
| 4 | mvn verify -Dgroups=Layer4 | ./gradlew test -Dgroups=Layer4 |
#!/bin/bash
set -euo pipefail
# --- Auto-generated integration test runner ---
# Project type: <detected>
# Generated on: <date>
# Verify prerequisites
if ! docker info > /dev/null 2>&1; then
echo "ERROR: Docker is not running. Please start Docker and try again."
exit 1
fi
# Run integration tests (project-specific command is embedded here)
# IMPORTANT: Always filter by the layer-specific tag to avoid running other layers' tests
# Test output (including any failure logs) goes directly to the console.
cd "$(dirname "$0")/../.."
<project-specific-test-command>
# e.g., mvn verify -Dgroups=Layer1, ./gradlew test -Dgroups=Layer1
TEST_EXIT=$?
# --- Print summary ---
echo ""
echo "========================================"
if [ $TEST_EXIT -eq 0 ]; then
echo "✅ Layer 1 integration tests PASSED"
else
echo "❌ Layer 1 integration tests FAILED"
fi
echo "========================================"
exit $TEST_EXIT
Note to implementers: Replace
<project-specific-test-command>with the real test command for the detected project type (Maven/Gradle). The test runner's own console output already includes detailed results — the script just appends a clear pass/fail signal at the end.
Integration Test Plan: Create and output a plan file at {modernization-work-folder}/integration-tests/integration-test-plan.md that includes:
All tests for the requested layer run and pass, show the running results to the user
Test results are reported with clear pass/fail status
Any failures are properly analyzed and resolved (see Handling Test Failures section)
Test artifacts (logs, screenshots, comparison reports) are saved
Version Control: Commit changes separately for each layer with meaningful commit messages. Do not combine changes from different layers into a single commit.
Add Layer 1 local integration tests)git add commands. Do not force-add files. If files in {modernization-work-folder} are ignored by the project's .gitignore, respect that.Integration Test Summary: Create and output a summary file at {modernization-work-folder}/integration-tests/integration-test-summary.md that documents:
Runner Scripts: Generate standardized runner scripts at {modernization-work-folder}/integration-tests/run-layer{N}-tests.sh and .ps1 (see Standardized Runner Scripts section). The scripts must embed all project-specific commands so users always run the same fixed command. Include runner scripts in the layer's commit (for Layer 2, in the artifacts commit).
testing
Generate and run post-migration tests from the frozen baseline specification.
devops
How team members request infrastructure connection info and handle secrets in team mode
testing
Create a test baseline for the project to be modernized. The baseline will be used for later verification of modernization tasks.
tools
Convert an arbitrary CSV report (e.g. a Black Duck export or a custom migration-issue inventory) into a schema-valid assessment `report.json` the modernization pipeline can consume — so it appears in the assessment UI and migration solutions resolve automatically. This skill is LLM-driven: you read and interpret the CSV yourself and author `report.json` by hand against the schema. A small helper script only does deterministic lookups (migration solutions, the ruleId for a solution) and validates the finished report. There is NO "convert everything" script and NO assumed column layout. Triggers: "convert csv to assessment report", "import csv report", "turn this spreadsheet into a report.json", "Black Duck csv to report", "build report.json from csv", "migrate a third-party assessment export". NOT for: AppCAT-style analysis from source (use `assessment`), generating a modernization plan (use `create-modernization-plan`), or editing a report.json the pipeline already produced.