Guide

Testing migration guides and changelog examples

Test both sides of an upgrade against pinned releases, rehearse the transition and assign ownership of gaps.

Published
Updated
November 10, 2026
Reading time
12 min
Facts checked against
Existing DocsAlive documentation and guide coverage (November 7, 2026)
Outlined documentation pages with a lime pulse line running out of the stack
On this pageThe short answerMap the transition before writing testsTest the old behavior in its own environmentTest the replacement against the new releaseRehearse the upgrade as a sequenceMake deprecation guidance precisePin versions and record the environmentInclude changelog examplesSet a release gate with clear ownershipMake reports useful to maintainersHow DocsAlive fitsFAQ

The short answer

Treat a migration guide as a versioned contract between the release a reader has and the release they want to adopt. Test each meaningful “before” example against the old release it describes and each “after” example against the new release or release candidate. Pin the versions, use clean environments, and check the behavior the prose promises. A snippet that compiles against the new version does not by itself establish that the documented upgrade path works.

Include deprecations, configuration changes, installation instructions and code snippets in the changelog. Run the checks before publication as a release gate, and check the public installation path after release. Record what was executed, what was checked without execution and what still needs a person. Give each transition an owner who can coordinate documentation, product and release decisions. The SDK release gate and release checklist provide related workflows.

Map the transition before writing tests

A migration guide usually starts with a working application on an older version and ends with that application using a newer one. Write down the exact starting and target releases, supported runtime and platform assumptions, and the outcome a reader should see. If the guide covers several starting versions, list those paths explicitly. A test from one old version does not prove that all supported starting points work.

Inventory each instruction in the order a reader follows it: install or upgrade a package, adjust imports, change configuration, replace deprecated calls, run a command, and verify the result. Connect the prose to the examples that demonstrate it. Include code blocks in release notes and the changelog, where a short replacement snippet may be copied without the surrounding migration guide.

Documentation element Question to answer Evidence to keep
Version scope Which old and new releases does this path cover? Exact versions and package sources
Before example Did the old API work as shown? Old environment and result
Upgrade instruction Can a reader obtain the intended release? Command, artifact and installed version
After example Does the replacement work on the new release? New environment and assertions
Deprecation note Is the timing and replacement clear? Release-specific behavior and owner
Changelog snippet Does the short example have enough context? Source location and check level

Start with the most important supported transition and the path readers are directed to first. Add alternatives as the documentation promises them. Keep an explicit list of untested language tabs, platforms and starting versions; a page-level pass is not proof of all of them. If a path needs a manual step, name the person responsible and describe the evidence they should retain.

Test the old behavior in its own environment

Create a clean environment for the exact old version. Install it using the source and method appropriate to the guide, then run the “before” example with the prerequisites a reader is told to provide. Check that it actually illustrates the old behavior, including meaningful output or side effects where those are part of the explanation. A before snippet that has never been run may misrepresent the starting point and make the replacement hard to evaluate.

Keep this environment separate from the new-version environment. An old package left on a search path, a cached configuration file, or a local checkout can make the test use a different version from the one in the report. Record the installed version and origin as well as the command that selected it. If the old release is no longer obtainable through the normal public path, document how the test obtained it and whether readers can still follow the published instructions.

An intentionally incomplete before fragment can be checked with a small, visible harness. Record what the harness adds: imports, an application object, a configuration file or sample data may all matter. If the page presents the fragment as independently copyable, supply the missing context in the page instead of letting the test conceal it. A harness pass proves the assembled example, not necessarily the isolated text a reader copied.

The purpose of the old-version check is not to keep obsolete behavior indefinitely. It establishes the starting condition that the guide claims to translate. If an old example fails, determine whether the version scope is wrong, a dependency has moved, or the example was never correct. Record a known limitation and its owner when a supported historical environment cannot be reproduced.

Test the replacement against the new release

Create a second clean environment and install the exact target release or candidate. Run the “after” code using the prerequisites and configuration described on the page. Assert the useful outcome rather than merely checking that the program exits. If a migration changes a return value, error, file or request, check the aspect the prose says has changed. Save the command, package source, runtime and result alongside the documentation revision.

Choose representative inputs that make the difference between the two APIs visible. If both old and new snippets print the same result, assert that result in both environments; the shared outcome can show that the reader's intended task still works. If the new API intentionally changes the result, document the difference and check each expected outcome separately. Do not force equality when the purpose of the migration is a behavior change.

A replacement may need new setup as well as a renamed call. Review imports, constructors, configuration names, permissions, dependency requirements and cleanup instructions. A test that injects a missing setting silently can pass while the upgrade fails for readers. Make the setup visible on the page or clearly link to a prerequisite, and record any fixture supplied only by the test harness.

Test the intended candidate before release, then repeat a small reader path against the published package when available. Those runs answer different questions: the candidate run can inform a release decision, while the published run checks what readers can obtain. Record any special source, local artifact or substitution used in the candidate test. A successful candidate check should not be described as a successful public installation check.

Rehearse the upgrade as a sequence

Independent before and after tests are necessary but do not cover every transition problem. Rehearse the documented sequence from a working old environment: run the old example, perform the documented upgrade, apply the stated changes, and run the new example. Check the result at the boundaries. This can reveal a missing configuration conversion or a step that assumes a fresh installation when the guide promises an in-place upgrade.

Use disposable state. Back up or create a fixture where the guide involves files or data, and verify the fixture before the migration. If the page promises that existing data remains usable, check that property after the transition in an appropriate test environment. If the test replaces a real service with a fixture, state that limitation. Never run a destructive migration against production merely to verify documentation.

Some migrations cannot be fully automated because they require a user decision, a browser, credentials, external services or access to proprietary data. Separate the parts that can be checked from the manual rehearsal. Provide a bounded checklist for the remaining steps, identify the test environment, and capture the outcome without exposing secrets. A skipped step is a coverage gap, not evidence that the full transition works.

Review rollback guidance when it is part of the published promise. Check the documented preconditions and whether a reader can identify a safe point to stop. If reversal is not supported, the page should say so clearly; the test report should not imply that returning to the earlier state was verified. Escalate uncertainty about data or irreversible operations to the appropriate product owner before release.

Make deprecation guidance precise

A deprecation notice needs a target audience and a useful action. Identify the old API or configuration, the version context, the recommended replacement and any behavior that differs. Check that the old example represents the old release and that the replacement works in the version the page names. If both forms are available during a transition, test and label the supported combinations rather than assuming every reader has already upgraded.

A warning can be useful evidence, but its exact wording is not always the reader's contract. Decide whether to check a stable category or property, a specific message, or simply the documented behavior. Avoid a comparison that discards all warnings: it could hide a new problem. Also avoid asserting incidental text unless the guide promises that exact text. Preserve actual output when a check fails so an owner can make the decision.

Check links from deprecation notes to replacement instructions. A correct replacement buried on another page is not enough if the changelog links to the wrong release or the guide omits a prerequisite. Read the rendered notice and follow the path a user would take. If no replacement exists, say what the reader should do and who owns the decision; an automated pass cannot fill that gap in the product guidance.

When an API is removed, verify that the migration guide does not describe the old call as usable on the new target. Conversely, do not run every historical before snippet against the newest release and classify the expected incompatibility as a documentation defect. The version label gives the test its meaning. Maintain a mapping from each block to its target version so automated checks preserve that distinction.

Pin versions and record the environment

For every result, record the documentation revision, old and new package versions, package source, runtime, operating system, dependency choices, setup commands and the test selection. Use exact pins for the baseline transition. This lets another maintainer reproduce a failure and distinguish a product change from a changed dependency or environment. Retain any lockfile or resolution information relevant to that result.

Pinning is one view, not a guarantee for all readers. If the guide promises a supported range, choose representative additional combinations and record which ones ran. A separate scheduled check can exercise current allowed dependencies, while the pinned check remains reproducible. Label those results independently: a moving dependency check answers a different question from a fixed release gate.

Keep old and new credentials, fixtures and test data scoped appropriately. A clean environment should not inherit a developer's private state or depend on a production account. Use authorized disposable resources for state-changing tests, and verify cleanup when the workflow creates remote objects. If external availability prevents a run, report it as a blocked check and preserve the error; it is not automatically either a product defect or a pass.

Version the documentation itself. A migration page for a future release should be clearly associated with that release and not presented as the default path before readers can obtain it. After publication, verify links, version labels and installation instructions on the public page. Archived guides may need their own dependencies and owners even after the main documentation moves on.

Include changelog examples

Changelog snippets are easy to overlook because they are short and often written near release time. Inventory code fences, inline commands and configuration examples in release notes as well as full migration pages. Give each snippet a target version and an intended check: complete executable example, fragment checked with a visible harness, command reviewed manually, or illustrative output. Include the location in the report so a maintainer can find the published text.

A concise changelog example may omit context deliberately. Make the omission clear and link to a complete migration path where readers need setup. If it claims to be a complete replacement, check that it includes the imports and configuration a reader needs. Avoid testing a longer private example while publishing a shorter, broken one; extract or otherwise tie the check to the actual source that produces the page.

Review the release notes and guide together for contradictions. A changelog may say a parameter is optional while the guide supplies it without explanation, or a short example may use an API name from a previous draft. Compare the final candidate behavior and the actual text before publication. Assign the same release owner to resolve discrepancies, even when different people maintain the two documents.

Set a release gate with clear ownership

A release gate is an agreed decision point, not simply a CI job. Name the candidate, the required paths and the people who can decide whether the release proceeds. Run the baseline transition early enough to fix a failure before publishing. Include documentation changes, API changes and dependency changes in the triggers for relevant checks; a migration example can break even when its page was not edited.

Agree in advance how to treat a failure. A replacement example that fails against the target candidate is a direct conflict with the migration promise and needs investigation before release. An unavailable external service may block evidence without proving the example is wrong. An intentionally incomplete fragment may need a clearer label or manual review. Preserve the original error and environment so the owner can distinguish these cases.

When a release proceeds with a known gap, record the affected version path, reader impact, reason, decision maker, owner and follow-up date. Do not bury it in a green aggregate status. Review open exceptions at the next release and remove them only when the missing evidence or fix is available. The GitHub Actions guide covers ways to run focused checks on changes and separate scheduled checks for drift.

After publication, install the public release in another clean environment and follow the public migration instructions. This smoke check cannot block the release that already happened, but it can identify a mismatch in the published package, page or link. Route failures to someone who can coordinate a documentation correction or product response. Retain both the candidate and public results so the timing of the issue is clear.

Make reports useful to maintainers

A report should connect every result to the exact page and example, its target version, the command or manual procedure, and the expected and actual behavior. Distinguish execution, compilation or syntax checks, manual review, skips and unselected variants. Summaries are useful for a release decision, but maintainers need the underlying error and setup to fix a failure.

A documentation owner can coordinate the page, but resolving a migration failure may require the API owner, release engineer and support team. Assign one person to ensure that the question is answered: is the example incorrect, is the product behavior unintended, or is the test environment unavailable? The owner should also confirm that the resulting fix reaches every affected guide and changelog entry.

Review the reader journey after the automated checks pass. Does the guide identify the starting version? Can readers tell which steps apply to their configuration? Is the expected result recognizable, and is a changed behavior explained? Automated checks can show that a selected path behaved as asserted; they cannot determine whether the migration is understandable for every reader or whether an important path was omitted.

How DocsAlive fits

DocsAlive extracts supported fenced examples and runs or checks them in page order, with a fresh container for each page. It selects one variant from each tab group. Python, JavaScript on Node 20, simple TypeScript, shell and curl or HTTP examples have the coverage described in the framework reference. Compiled-language examples are recognized but not executed yet; credential-dependent examples are classified rather than executed with real keys.

Expect version-dependent findings on migration pages. On our results page, one engine flag on a migration page was a “before” snippet that shows the old API on purpose; we reviewed it as a false alarm. A migration still needs an explicit mapping between each before or after block and its intended version. Read report.md and report.json with the findings reference, including skips and unselected variants. A pass can represent execution or a syntax check. Use separate version-specific checks and an upgrade rehearsal where needed; review the prose, installation path and behavior that the automated selection does not cover.

See pricing: the Open source plan is $0/month for public OSI-licensed projects, Team is $299 per month, Growth is $699 per month, and Scale starts at $1,499 per month. Contact us to discuss coverage or request a free health check.

FAQ

Should before code pass on the new version?

Not necessarily. Test it against the old release it is meant to illustrate; test the replacement against the new release. Record the intended version for each block.

Are separate before and after tests enough?

They establish useful endpoints, but can miss a broken upgrade step. Rehearse the documented sequence with disposable state when the guide promises a transition.

Should changelog snippets be tested?

Yes, according to their intent. Check complete examples, use visible harnesses for fragments, and record manual or untested cases with an owner.

What should block a release?

Agree on the policy before the run. Investigate a replacement that fails against the intended candidate, and record the impact, owner and decision for any accepted gap.

Keep reading
Outlined documentation pages with a lime pulse line running out of the stackGuide

Docs Testing: How to Test the Code Samples in Your Docs

Why code examples in documentation break, the ways teams test them (doctest, docs-as-tests, CI runners) and how to run every sample on each release.

Two lenses held over the same documentation page, each bringing a different layer into focusComparison

Vale vs markdownlint: What Each Docs Linter Catches

Vale checks prose style; markdownlint checks Markdown structure. What each catches, sample configs, running both in CI and what neither one tests.

Blueprint of two documentation pages: one with a handwritten test script, one whose code blocks are framed and checkedComparison

Doc Detective vs DocsAlive: Testing the Code in Your Docs

Doc Detective is a free, open-source docs-as-tests framework; DocsAlive is a hosted docs CI for code examples. Features, price, setup and when to use each.

A machine blueprint above a ruled documentation page, with a caliper measuring between themComparison

Promptless Alternative: Promptless vs DocsAlive Compared

Promptless drafts docs updates from what you ship; DocsAlive runs the code examples you've published. Features, pricing, security and when to use each.

A long workbench of outlined testing instruments, each with a small lime light, beside a stack of documentation pagesGuide

Best Free Tools to Test Code Examples in Documentation

Free, open-source tools that run the code examples in your docs: rustdoc, Go examples, doctest, pytest plugins, Sphinx doctest, Doc Detective and byexample.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing SDK Docs Before Every Release: A Release-Gate Guide

Test SDK and client-library docs against the package you ship: build the wheel or npm tarball, install it clean, run every example, and gate the release in CI.

Outlined documentation pages with a lime pulse line running out of the stackGuide

How to Test Quickstarts and Tutorials in Your Docs

Test the onboarding path a new reader follows: run quickstarts in a clean environment, in page order, sort real bugs from credentials and fragments, and wire it into CI.

Outlined documentation pages with a lime pulse line running out of the stackGuide

How to Test CLI Documentation: Commands, Flags and Output

Test the commands a CLI page promises: install in a clean container, run examples in order, compare flags with --help, check exit codes and output, and run it in CI.

Outlined documentation pages with a lime pulse line running out of the stackGuide

How to Test API Reference Docs: Requests, Responses and SDKs

Test API reference pages against the contract they publish: methods, parameters, request and response examples, SDK snippets, status codes and OpenAPI samples.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Docs testing for API-first companies

Keep API quickstarts, SDK snippets and curl examples working across releases.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Docs testing for CLI and developer-tool vendors

Test developer-tool install paths, package managers and command examples across releases.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing README Code Examples: Install, Usage and CI

Keep README install commands and usage examples working with clean environments, output checks and CI.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing Notebooks and Executable Docs: Cells, Kernels and Output

Test notebooks in fresh kernels, check meaningful output and manage dependencies, data and drift in CI.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing Docs in GitHub Actions: Pull Requests and Scheduled Checks

Run documentation example checks in GitHub Actions with practical guidance on schedules, path filters, caching, secrets and reports.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing Code Examples in MkDocs, Docusaurus and Sphinx Sites

Find and test documentation examples in Markdown, MDX and reStructuredText, alongside site builds and link checks.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Python Docs Testing: Doctest, Pytest and Markdown

Test Python documentation with doctest, pytest, Markdown example execution and isolated environments.

Outlined documentation pages with a lime pulse line running out of the stackGuide

JavaScript Docs Testing: Node, TypeScript and Modules

Test Node and TypeScript documentation examples across module formats, package versions and type checks.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing Go documentation examples

Test Go example functions and Markdown snippets against the intended module versions in clean environments.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Sphinx Docs Testing: doctest, code-block and MyST

Test Sphinx documentation examples: what the doctest and linkcheck builders prove, code-block and literalinclude, MyST fences, and what a Markdown scan covers.

Outlined documentation pages with a lime pulse line running out of the stackGuide

ReadMe Docs Testing: CLI, OpenAPI and Code Examples

Test ReadMe documentation examples: docs-as-code and bi-directional sync, what lint and oas:validate prove, Tabs variants and runnable code.

Outlined documentation pages with a lime pulse line running out of the stackGuide

TypeScript Docs Testing: tsc --noEmit and Runtime

Test TypeScript documentation examples: type-check snippets with tsc --noEmit in a consumer project, then run them, and what each check proves.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Docusaurus Docs Testing: Code Blocks, Tabs and MDX

Test Docusaurus documentation examples: builds vs runnable code, code block metadata, Tabs install variants, MDX pages and clean-container runs.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Mintlify Docs Testing: CodeGroup, Tabs and the CLI

Test Mintlify documentation examples: docs.json, MDX pages, CodeGroup and Tabs variants, what mint broken-links and mint validate prove, and clean runs.

Outlined documentation pages with a lime pulse line running out of the stackGuide

MkDocs Docs Testing: Code Examples, Tabs and Snippets

Test MkDocs documentation examples: strict builds, Material tabs, Snippets includes, mkdocstrings pages and clean-container runs.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing Installation Instructions: pip, npm and Containers

Test documented install steps in clean environments: pip and extras, venv, npm install vs npm ci, containers and the first import.

Outlined documentation pages with a lime pulse line running out of the stackGuide

AI SDK Docs Testing: LLM Examples, Keys and Drift

Test AI and LLM SDK documentation examples: requests, responses, streaming, tool calls, credentials, model retirements and CI.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Docs Testing Checklist: Code Examples Before Release

A practical pre-release checklist for testing documentation examples, reviewing gaps and verifying published packages.

Outlined documentation pages with a lime pulse line running out of the stackGuide

The Cost of Broken Code Examples in Documentation

Understand how broken documentation examples create friction in developer adoption and support, and how to reduce it.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing Rust documentation examples

Test Rust rustdoc examples and cargo documentation tests, and keep native Rust checks because compiled Rust fences are recognized but not executed.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing VitePress documentation examples

Test VitePress Markdown examples separately from the site build, including code groups, includes and what a plain Markdown scan covers.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing docs in GitLab CI

Run documentation example checks in GitLab CI jobs, keep site builds separate from execution, and review what a scan covers and skips.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing JSON, TOML and YAML examples in docs

Test JSON, TOML and YAML config examples in documentation: parse, schema and tool checks, honest fence labels, fragments, CI jobs and what a scan covers.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing Java documentation examples

Test Java examples in READMEs, SDK docs and Javadoc: the source launcher, javac, JShell scripts, assertions, @snippet files, CI and what a scan covers.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing PHP documentation examples

Test PHP examples in docs: php -l lint, clean-directory runs, assertions with zend.assertions, Composer scratch projects, PHPUnit, CI and scan coverage.

Outlined documentation pages with a lime pulse line running out of the stackGuide

Testing docs examples that need API keys

Test credential-gated docs examples: honest placeholders, offline stubs and fixtures, live sandbox jobs, CI secrets and fork rules, and how a scan classifies them.

A machine blueprint above a ruled documentation page, with a caliper measuring between themGuide

Documentation Drift: How to Detect It Before Users Do

What documentation drift is, why code examples drift first, and practical ways to detect it: ownership, release checks, link and execution tests.

See which of your code samples still run.

Send us a public repository. Our team runs DocsAlive on its docs and emails you the real report within 2 business days. Free, no signup.