October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk8 min

Why Green Local Tests Can Hide a Broken Project Graph

A green local test run shows that the tests you invoked passed in your environment. It does not prove the full dependency graph is complete or that CI resolves the same way. Here is how to tell the difference and find the gap.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A green local test run is evidence about one thing: the tests and build context that actually executed passed on your machine. It does not show that the repository’s full project or dependency graph is complete, that every module and configuration was resolved, or that your continuous integration (CI) system resolves dependencies the same way. When tests pass locally but a dependency relationship is missing or inconsistent elsewhere, the two checks have usually covered different ground.

This article explains the difference between running tests and validating the project graph, lists the places where static dependency information and the real build can disagree, and gives a diagnostic sequence you can apply to a specific repository.

As an Amazon Associate I earn from qualifying purchases.

What “project graph” means here

The term is used loosely. In this article, a project graph is the set of build and dependency relationships a build tool resolves: which projects depend on which, which components and variants are selected, and which direct and transitive dependencies end up on each classpath or in each package. It is not the same as an architecture diagram or a module-dependency diagram drawn for documentation, although those can be used to validate the same code.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Build tools build this graph from configuration files and dependency declarations. Gradle, for example, describes a resolved graph as relationships among components and variants, including direct and transitive dependencies, and its dependencies task can display part of that graph. The authoritative description is in the Gradle User Manual’s Graph Resolution page, which reports version 9.8.0 at the time of writing.

Test execution and graph validation answer different questions

A test run answers: did this selected code, under this selected task, behave as the tests expect? A graph validation answers: are the relationships the build will use complete, resolvable and consistent with the rules the repository has set? A test can exercise a module that never touches a broken dependency, and a graph check can flag a problem in a module no test imports.

Check What it establishes What it does not establish
Local test run (one project or one test target) The selected tests passed in your local environment with the tool versions and variables you have. That other projects, configurations or the whole solution were built or tested, or that CI resolves the same versions.
Full build task on the whole solution, with the configuration CI uses Everything included in that task compiled and resolved under that configuration. That static manifests or submitted graphs show every relationship, or that build-time-only dependencies match what production resolves.
Static dependency graph (manifests and lockfiles) The dependencies that supported manifests and lockfiles declare, including direct and transitive ones. Dependencies that only appear at build time, values set by environment variables, or files that were never declared.
Build-resolved graph (generated during the actual build) The dependencies the build tool resolved in that build environment. Anything outside the scope of that build, such as a project or configuration the job did not run.
Architecture or layer validation Whether code respects the dependency rules written in the validation diagram, within the analysed scope. Whether every file was analysed; live validation may cover only edited files unless full solution analysis is enabled.

The practical consequence is that “the tests passed” is a statement about a subset. Before reading a green result as a clean graph, state which command, which target and which configuration produced it.

Why the graph you see can differ from the real build

Static dependency detection reads what a repository exposes in its manifests and lockfiles. The build, however, resolves what those files, the environment and the build scripts produce together. Several gaps follow from that difference.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Variables that only the build environment can resolve

GitHub’s documentation for the dependency graph notes that some values in manifests may depend on the build environment. A version written as a placeholder or a property is not always resolvable from the file alone. If your local shell exports a property that CI does not set, the local resolution can succeed while CI resolves a different version or fails. The GitHub Docs troubleshooting page for the dependency graph describes these environment-dependent cases and the processing limits that apply to them.

Dependencies copied or generated into the repository

Loose dependency files copied into a repository are not automatically included in the graph. A vendored JAR, a hand-copied library or a generated artefact can be on your classpath without appearing in any manifest the graph reads. A local test that imports the vendored code will pass; a graph-based check will not see the relationship at all unless it is declared or submitted.

Build-time dependencies that need separate submission

Some dependencies exist only during the build, such as code generators, plugins or tooling resolved by the build script. GitHub documents that build-time dependencies may need to be submitted through an API or through an automatic workflow. If nobody submits them, the static graph is incomplete by design, even when the build itself is correct. Gradle’s dependency-submission action documentation describes one route for sending build-resolved data.

Processing limits and analysis scope

Graph generators apply limits. GitHub documents limits on manifest size and on the number of manifests processed. Microsoft’s layer-diagram validation can analyse only edited files in live validation unless full solution analysis is enabled. A report that looks complete may therefore omit files or relationships for reasons unrelated to your code. Read the stated scope before treating the report as an inventory.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Generated graph data is only as complete as its job

GitLab warns that a dependency graph generated from SBOM data may not reflect dependencies resolved in the actual build environment. Its guidance is to generate graph data inside a controlled build job where that is possible, so the data reflects the same resolution the build uses. The GitLab Docs page on dependency scanning by using SBOM sets out that caveat.

None of these mechanisms proves that a specific local/CI mismatch has one of these causes. They are the documented ways a local test can pass while a graph-based check, or a different CI resolution, finds a missing or inconsistent relationship.

Lockfiles improve repeatability but do not prove coverage

Lockfiles record exact resolved versions, and GitHub’s explanation of how the dependency graph recognises dependencies makes the practical point: lockfiles keep contributor versions consistent, which makes it easier to test and debug. That benefit is real. If two developers see different versions of a transitive dependency, a lockfile narrows the gap.

A lockfile, however, records the dependencies that were resolved when it was written. It does not show whether every project in the repository was built against it, whether a configuration was excluded from the run, or whether a dependency was added after the lockfile was last updated. NuGet illustrates the split: the generated obj/project.assets.json file manages the overall dependency graph used by a project, according to Microsoft Learn’s description of NuGet. That file describes one project’s resolved graph; it is not a claim about the whole solution.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Treat a lockfile as evidence about the versions that were pinned, not as proof that the full graph was exercised.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Why CI can disagree with your machine

When local tests pass and CI fails, the difference is usually in one of four places: the scope of the command, the tool and runtime versions, the environment variables, or the task selection. The graph adds a fifth: where dependency data comes from. The comparison below is the basis for the diagnostic sequence that follows.

Dimension Local run CI run What to compare
Scope One module or the whole solution, depending on the command you typed Often the full pipeline, sometimes a matrix of projects Exact task and target names, and whether a filter excludes projects
Source of graph data Usually the build tool’s own resolution May add a static manifest graph or a submitted snapshot Whether CI submits build-resolved data or relies on static files
Reproducibility Versions may come from a local cache or an unpinned range Versions may come from a clean resolution Lockfile presence, cache state and dynamic version ranges
Validation stage Local command only Build step, plus any architecture or graph validation step Which checks run in CI but not locally
Documented limits Your tool’s configured analysis scope Platform limits on manifest size and count, and analysis scope set in the pipeline The stated limits on each side

A diagnostic sequence for a missing or inconsistent dependency

Work through these steps in order. Each one narrows the cause before you change code.

  1. Name the command that passed. Record the exact invocation, such as ./gradlew :app:test or dotnet test against a named project. Note whether it ran one test project, one configuration, or the whole solution.
  2. Run the intended full build. Execute the full build and any integration or architecture-validation tasks that CI requires, including those with separate validation stages. A green result only counts for the tasks that ran.
  3. Inspect the resolved graph. For Gradle, run ./gradlew :app:dependencies --configuration runtimeClasspath for each project and configuration in question, replacing the names with yours. Check the output for the dependency that is missing or at an unexpected version. Other build tools have equivalent commands.
  4. Compare declared dependencies with the real resolution. Set the lockfile, the manifest and the resolved graph side by side. Look for property placeholders, dependencies copied into the repository, and build-script dependencies that never appear in a manifest.
  5. Check environment variables and the build context. Compare the variables set locally with those set in CI. A property defined only on your machine is a common source of divergence.
  6. Make graph generation run in the build. Where possible, generate graph data from the same build job that compiles the code. GitHub’s dependency submission REST API accepts build-resolved dependency snapshots, and GitLab recommends generating graph data within a controlled build job when appropriate.
  7. Check validation scope and processing limits. Confirm whether the validation analysed the files you changed or the whole solution, and whether the graph report hit a size or count limit. A report that omits a file is not evidence that the file has no problem.
  8. Reproduce the CI environment before changing code. Match tool versions, runtime versions, configuration files and environment variables, and rerun the same task selection. Only after the environments match should you change the dependency or the code.

Choosing a stronger check

If the local test is the only check you run, add one of these before trusting a green result for dependency changes:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • A full build of the solution or the project set that CI builds, using the same task names.
  • A build-resolved dependency snapshot submitted from the build job, rather than a static manifest alone.
  • An architecture or layer validation run with full solution analysis enabled, if your team uses dependency diagrams.
  • A lockfile check in CI, so that version changes appear as explicit diffs.

Each check covers a different part of the graph. Use them together and state, in the pull request or the build summary, which scope each one covered.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.