用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/microsoft/github-copilot-modernization --skill verify-test-baseline命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | verify-test-baseline |
| description | Generate and run post-migration tests from the frozen baseline specification. |
Generate executable *PostMigrationIT tests from the frozen baseline specification and run them against the migrated application.
The baseline phase produces no test code — it produces a precise specification, including the test-cases, infra-decision-table, and testdata. This skill is the sole place where integration test code is generated.
When the baseline decision table includes testcontainer rows, verification MUST run those dependencies against containerized emulators/services (not cloud resources and not mocks).
Event-sourced subscriber — any entry point invoked by an external event source rather than by a synchronous caller: message-queue listeners, event-bus / event-hub / event-grid handlers, storage-event triggers (e.g. blob-created or object-deleted handlers), DB change-feed / CDC handlers, inbound-email handlers, file-system watchers. Throughout this document, "event-sourced subscriber" refers to this entire family; the only legitimate trigger for such an entry point is a real event produced on the declared source via its SDK or wire protocol.
Testcontainer dependency — an external dependency marked testcontainer in infra-decision-table.md; verification must instantiate and use a containerized emulator/service for that dependency via the project's Testcontainers stack.
When any dependency is marked testcontainer, read and apply these references before writing tests:
TC-* in test-cases.md. No extra tests, no missing tests. Test method count == TC count. Banned extras include: infrastructure connectivity tests ("can connect to DB", "can create SDK client"), SDK sanity tests ("can send/receive message", "can read secret"), backing-store CRUD tests that have no entry point in the inventory, and authentication/credential validation tests. If it is not a TC-*, it must not exist.TC-* ID in the method name itself (e.g. tcEjb001_collectLocationHappyPath, tc_ejb_001_collect_location_happy_path). A comment or display name alone is insufficient — the method name is the primary index for auditing coverage.Entry Point — for example, one that invokes a cloud SDK, a repository, an internal service, or a private helper instead — is invalid and must be regenerated, even if it passes. If the spec declares an application method as the entry point, the test MUST call that method through its public interface — not re-implement the logic inline using lower-level APIs (e.g. direct DB writes, manual computations). If the spec declares a message-queue listener as the entry point, the test MUST send a message to the queue — not call the listener's handler or an internal service directly.Expected Response, Resource Verification, and Negative Verification. Existence-only or no-throw-only checks (asserting only that a resource exists, that a call did not throw, or that a value is non-null) are insufficient on their own.Inputs (frozen, produced by the setupBaseline task) live under each in-scope module's test source root — the directory the build tool already uses for tests (e.g. src/test/ for Maven/Gradle Java, tests/ for Python / Node / Go, <module>/test/ for multi-module repos). In a multi-module project, each module that was determined to be in-scope during the baseline phase has its own independent test-cases/ folder. Modules that were marked out-of-scope (no migration-relevant resource access) will not have a test-cases/ folder — skip them.
<test-source-root>/
└── test-cases/ # FROZEN folder — created in Phase 1
├── test-cases.md # FROZEN — the behavior spec (scoped to this module only)
├── infra-decision-table.md # FROZEN — mock/real/testcontainer decision per external dependency
└── testdata/ # FROZEN — fixtures referenced by test-cases.md
Outputs of this skill:
${modernization-work-folder}/${taskid}/post-migration-plan.md — the TC→test planning table written in Step 4 (created/overwritten on each run).*PostMigrationIT source files — follow the project's existing test layout conventions.${modernization-work-folder}/${taskid}/verification-summary.md — final report (Step 9).Reused inputs from the baseline phase:
<test-source-root>/test-cases/infra-decision-table.md — mock/real/testcontainer decision per external dependency, produced by create-test-baseline. This skill consumes it as-is.For each in-scope module, locate <module-test-source-root>/test-cases/ and confirm test-cases.md, infra-decision-table.md, and testdata/ are byte-identical to the baseline commit. Any drift → request revert. If test-cases.md is missing entirely for a module that was marked in-scope, abort: the setupBaseline task was supposed to run first — surface this as a plan-ordering bug, do not proceed. Modules without a test-cases/ folder were determined out-of-scope during the baseline phase (no migration-relevant resource access) — skip them.
The mock/real/testcontainer decision for every external dependency is made in the baseline phase, not here. Verification reuses it as-is.
<test-source-root>/test-cases/infra-decision-table.md produced by create-test-baseline. If it is missing, abort and surface this as a plan-ordering bug — do not regenerate it here.infra/.Do not proceed until the table is loaded and the sanity check passes.
Before generating code, audit test-cases.md against the Required Field Checklist defined in Step 5 of the create-test-baseline skill.
testdata/... path referenced exists.Any defect → Step 8 (re-freeze cycle). Do not paper over spec defects in generated code.
Inputs: test-cases.md, the infra decision table loaded in Step 2.
TC-* in test-cases.md, plan exactly one test method. No extra tests. No collapsing two TCs into one. No splitting one TC across multiple test methods (sub-steps go inside the single method body).Trigger field is technology-agnostic; resolve it to the actual mechanism that exists in the migrated codebase. Always trigger via the same outside-in path the entry point is invoked from in production. Pick the most realistic public driver the test framework offers:
triggerJob, manual invocation of the scheduled-task dispatcher). This is framework-driven, not SDK-driven.When in doubt, prefer the mechanism a real external caller or event source would use over a test-only shortcut.
3. Reject in-spec but infeasible decision-mode cases early. If a test case requires failure injection on a dependency marked real or testcontainer (e.g. "storage unavailable", "backend throws IOException", "corrupt object content") and there is no way to trigger that condition from the declared entry point under that mode, do not silently skip and do not silently switch modes — surface the conflict → Step 8 (re-freeze) so the infra-decision-table is amended or the case is reformulated.
4. Close entry-point coverage gaps. Scan production code for orchestration entry points. For each one not present in the Entry-Point Inventory of test-cases.md, surface the gap → Step 8 (re-freeze) so the spec is updated first. Do not silently add post-migration-only cases.
5. Produce a planning table (mandatory artifact). Before writing any code, emit the TC→test mapping table and save it to ${modernization-work-folder}/${taskid}/post-migration-plan.md (create or overwrite). The file MUST contain one row per TC-*; rows whose Trigger Mechanism is anything other than the declared entry point's outside-in driver, or whose Fixtures Loaded is empty while Data References is non-empty, must be revised before proceeding. The same table is later linked from the Step 9 verification summary.
| TC ID | Test Location (class/file → method) | Declared Entry Point | Trigger Mechanism (concrete) | Fixtures Loaded (from Data References) | Non-mock Deps Touched (real/testcontainer) | Config Source | Cleanup Path |
|---|---|---|---|---|---|---|---|
| TC-XXX-001 | e.g. FooPostMigrationIT.uploadHappyPath | e.g. POST /foo/upload | e.g. HTTP test client multipart POST to /foo/upload | testdata/inputs/sample.jpg, testdata/expectations/upload-success.json | e.g. Blob (testcontainer), Queue (real) | e.g. application-integrationtest.yml + env vars mapped from infra/ outputs and Testcontainers runtime properties | e.g. POST /foo/delete/{key} |
The row above is illustrative; use the test-class / method / driver naming conventions of the migrated project's language and framework.
Config Source is mandatory and must name where each non-mock dependency endpoint/identifier comes from. Any row that implies inline literals in test code must be revised before generation.
TC-* in the spec. These are not post-migration integration tests.Before writing any test code, emit a trigger-line pseudocode table for every planned test method. For each row, write the single line of code (or pseudocode) that will serve as the trigger, then self-check it against the Forbidden trigger patterns in Step 4. The table format:
| TC ID | Trigger pseudocode | Entry Point Type (from spec) | Violates Step 4 forbidden patterns? |
|---|---|---|---|
| TC-XXX-001 | serviceBusSender.sendMessage(queue, messageBody) | Message-queue listener | No — publishes real event to declared source |
Any row whose last column is anything other than No MUST be revised until it passes. Do not proceed to code generation with any unresolved row.
Preconditions or Resource Verification requires state on a real or testcontainer-backed resource (object in a container, row in a table, message on a queue) and the application exposes no public entry point to create or read that state, the test setup / verification step MAY call the resource's SDK directly. Seed data comes from testdata/. This is setup/observation, not the trigger.Awaitility-style polling helper in JVM languages, WaitFor / polling loops in .NET, pytest-style retry helpers in Python). Never use a fixed-duration sleep, and never assert immediately after emitting the event.Expected Response, Resource Verification, and Negative Verification bullet-by-bullet. Each bullet maps to at least one assertion in the test body. Missing any bullet → regenerate.Data References. Each path under Data References must be loaded by the test through the language's normal resource-loading mechanism (e.g. classpath resource stream in JVM, embedded resource / file read in .NET, file open in Python/Node/Go) and used either as input or as the expected value for an assertion. Unused fixtures are a planning bug — either the test under-asserts, or the spec lists a fixture it doesn't need (→ Step 8).Resource Verification. Assert content, fields, sizes, statuses, redirect targets, message bodies, and DB column values exactly as the spec states.Negative Verification (e.g. "no new row inserted", "no message published", "no thumbnail created"), the test must perform the observation that proves the negative — not just skip it.@Order, NUnit [Order], xUnit IClassFixture for ordering, pytest fixture ordering tricks). No skip-when-previous-test-passed coupling (e.g. Assumptions.assumeTrue(previousState != null), Skip.If(...)). Every test sets up its own preconditions and tears them down.testcontainer.testcontainer rows with mocks or cloud resources; instantiate and wire the required emulator/service containers.testdata/, assert on outbound requests as well as return values.infra/ for real rows, andtestcontainer rows,
via the project's standard mechanism (Spring profile, .env, appsettings.IntegrationTest.json, env vars). Activated for these tests only; do not modify production config.real rows: cloud credentials are required.testcontainer rows: cloud credentials are NOT required; use emulator/container credentials or anonymous/local auth.mock rows: no cloud credentials required.az login principal (e.g. via DefaultAzureCredential / AzureCliCredential). Do not fabricate a managed-identity client ID, do not point at IMDS, and do not require a service-principal secret for local runs.AZURE_CLIENT_ID / AZURE_TENANT_ID / AZURE_CLIENT_SECRET or federated credentials).Assumptions.assumeTrue(credentialsAvailable), Skip.If(...), JUnit @EnabledIfEnvironmentVariable, early return in @BeforeAll, try/catch that swallows the auth exception) — those let the verification phase complete with zero real assertions executed against the migrated stack.real rows, it must run unconditionally; a missing az login is not a valid reason to skip.finally / teardown; ignore "not found". Never use SDK cleanup as a workaround for a broken application delete path — if the application's delete entry point fails, that is a production bug (Step 7), not a cleanup-strategy choice. For mocked dependencies, cleanup is reset of in-memory state — still required so tests stay independent.Before running, run the pre-run validation checklist against generated code. Any No → regenerate (Step 5) or escalate to Step 8. Do not proceed to execution with a failing checklist.
Coverage & mapping
TC-* count in test-cases.md (no extras, no missing). Zero test classes may exist that are not mapped to at least one TC-*. Infrastructure-only, SDK-sanity, or connectivity test classes are forbidden.TC-* is referenced by exactly one test method whose method name contains the TC-ID (e.g. tcEjb001_...). A comment or @DisplayName alone is insufficient.${modernization-work-folder}/${taskid}/post-migration-plan.md exists and has one row per TC-*.Trigger correctness (per test)
Entry Point and does not match any pattern in Step 4 "Forbidden trigger patterns".Assertion completeness (per test)
Expected Response is asserted.Resource Verification is asserted.Negative Verification is asserted (where the spec lists it).Data References is loaded by the test.Isolation
Infra alignment
testcontainer dependency.testcontainer.infra/ for real rows and container endpoints for testcontainer rows.testcontainer without the ability to trigger that condition from the declared entry point. Any such case should have been surfaced in Step 4.3 and sent to Step 8 (re-freeze).Run all *PostMigrationIT tests. Required: 100% pass, and the run MUST be a real execution that reached the application. For each TC, dependencies must follow the decision table exactly: real rows hit real provisioned resources, testcontainer rows hit instantiated containers/emulators, and mock rows are served by configured test doubles.
Execution is mandatory — compile/unit-test success is not verification.
mvn verify / mvn failsafe:integration-test, Gradle ./gradlew integrationTest, dotnet test against the IT project, pytest tests/integration, go test -tags=integration ./...). Confirm from the runner's output that each *PostMigrationIT method was actually executed (e.g. Failsafe Tests run: N ≥ TC count, not Tests run: 0). A green build that ran 0 IT methods is not a pass.success:
mvn compile / mvn test-compile / type-check only.mvn test, dotnet test without the IT project, pytest without the integration marker) — by convention *IT / integration tests are excluded from this phase.@MockBean present", "assertions look right") without running them.success.mock but which silently falls back to a real network call (because the mock wasn't wired, or because the SDK uses default credentials when no stub is present) is a test bug, not a pass — fix the mock wiring; do not declare success on the strength of an unintended real call.testcontainer but which silently falls back to a real cloud call or a mock is a , not a pass — fix container wiring.Task status outcome (mandatory mapping). Pick exactly one based on the actual runtime result — never on "compile passed" or "unit tests passed". Runtime coverage checks apply to TCs whose decision-table rows are real and/or testcontainer:
| Situation | Status |
|---|---|
Every *PostMigrationIT ran AND 100% pass; real-dep TCs hit real resources, testcontainer-dep TCs hit configured containers/emulators, and mock-dep TCs were served by the configured doubles | success |
| Verification is paused waiting on a hand-off (Infra agent, migration developer for production bug, re-freeze cycle); will resume | pending (with summary of who/what is blocking) |
*PostMigrationIT executed and at least one failed, AND the cause is a production bug or a test bug that cannot be reconciled with the spec, AND no further hand-off is in progress | failed |
| Real-dep TCs could not be started or completed and the blocker cannot be resolved (Infra Expert unavailable/declined, or infra drift cannot be fixed in this run), OR testcontainer-dep TCs could not be started or completed and required container runtime/emulator setup cannot be restored in this run | failed |
Mock-dep TCs were not executed for any reason, OR verification produced no real execution evidence at all (zero *PostMigrationIT methods executed, runner reported Tests run: 0, or only compile/unit phases ran) | failed |
The status success is permitted only when the Runtime Execution Evidence required by Step 9 can be filled in with real numbers for every TC. If you would have to write "integration tests were not executed because..." for any TC in the summary, the status is not success — it is pending (real-dep infra handoff active, or testcontainer setup still unresolved) or failed (handoff exhausted, mock-dep TCs unrun, or no path forward).
This section is the single reference point for failure classification. Steps 5 and 6 route here when a runtime or generation-time failure occurs.
The spec is the source of truth. Before deciding it is a test bug, prove the test contradicts the spec. The default classification of any disagreement between spec and runtime behavior is production bug.
testcontainer dependency (e.g. Docker daemon unavailable, image pull failure, emulator config missing, unsupported testcontainers version) → report as an error, fix in this skill; if unresolved, use ask_user. Do not route these to the Infra Expert.Handover protocol (production bug / infra issue):
Hand over per the teams SOP. The hand-back message must include:
| Classification | Recipient | Message must include |
|---|---|---|
| Production bug | Migration developer | Which TC-* failed, the declared expected behavior from the spec, the observed behavior from the run, and the suspected production cause |
| Infra issue (real dependencies only) | Infra Expert | Which *PostMigrationIT could not run, the exact error or missing prerequisite, and the real resource(s) involved (resource group/account/namespace/server names) |
Prohibited responses (both): do not patch the test to work around the problem — no trigger rewrites, no loosened assertions, no auth-setup changes beyond Step 5. Do not loop indefinitely or flip to success.
Exhausted hand-off: if the recipient is unavailable or does not exist in teams-roles.json, fall back to ask_user. If ask_user is also unavailable or the user declines to act → close the task as failed per the status mapping in Step 6.
Whenever any of the following occurs — the Step 3 audit fails; Step 4 finds an uncovered entry point, an infeasible-as-real failure-injection case, or a planning gap that cannot be expressed against the current spec; Step 6 finds a generated test cannot be reconciled with the spec; or any new fixture / scenario is needed — coordinate a baseline re-freeze: unfreeze the contents of test-cases/ → amend (test-cases.md, testdata/, and/or infra-decision-table.md) → re-run the create-test-baseline freeze gate → re-freeze. There is no side channel for adding fixtures or cases in Phase 3.
Create ${modernization-work-folder}/${taskid}/verification-summary.md summarizing decisions, results, and gaps. This is the only report artifact — do not emit additional report / status markdown files. (The planning table from Step 4 and the *PostMigrationIT source files from Step 5 are separate required outputs and continue to exist.)
The summary MUST include a Runtime Execution Evidence section with:
mvn -pl web,worker verify).*PostMigrationIT methods equals the count of TC-* planned in Step 4.az login principal name, MI client ID, or CI SP) and the target resource identifiers (resource group + account/namespace/server) that were actually contacted. For testcontainer-dep TCs: container image(s), mapped endpoints, and emulator auth strategy used. For mock-dep TCs: the test-double mechanism used (e.g. @MockBean, WireMock stub, in-memory fake) so it is auditable that no accidental real call occurred.If this section cannot be populated with real execution data for every TC (real-dep TCs with real-resource evidence, testcontainer-dep TCs with container runtime evidence, mock-dep TCs with mock-wiring evidence), the task is not eligible to be marked success — go back to Step 6 and resolve the real-dependency Infra issue or the testcontainer setup issue (per Step 7), or fix the missing execution first.
infra/az CLI command that performs a write operation (e.g. az role assignment create, az storage account create, az keyvault set-policy, az group create, az resource update, az ad app create) is forbidden. Read-only az commands (e.g. az account show, az role assignment list, az resource list) are permitted for diagnostic purposes only. If a missing role assignment, resource, or configuration is identified, hand over to the Infra Expert per Step 7 — do not provision or reconfigure Azure resources from within this skill.