Defect tracking shows zero requirements coverage despite full traceability links

We’re facing a critical issue with our requirements coverage reporting. Defects logged against test cases are showing zero requirements coverage in Analytics views, even though the traceability links are fully established:


Defect DEF-5678 → Tested By → Test Case TC-901
Test Case TC-901 → Tests → Requirement REQ-204

When we query the Analytics service for defect coverage metrics, the API returns:

{
  "DefectId": "DEF-5678",
  "RequirementsCoverage": 0,
  "LinkedRequirements": []
}

This is blocking our release gates which require 100% requirements coverage for all open defects. The traceability matrix view shows the correct relationships when queried manually, but the Analytics refresh doesn’t seem to pick up the transitive links through test cases. We’re running Azure DevOps Server 2025 with daily analytics refresh scheduled. Has anyone encountered this discrepancy between work item links and analytics reporting?

I’ve implemented a comprehensive solution that addresses all four aspects of your coverage problem:

Defect Coverage Calculation: Built a custom Azure Function that runs on a schedule and calculates transitive requirements coverage for all defects. The function uses batch REST API calls to fetch defect links, traverse to test cases, then extract requirements:

var testCases = await GetLinkedWorkItems(defectId, "Tested By");
var requirements = new List<int>();
foreach(var tc in testCases) {
  requirements.AddRange(await GetLinkedWorkItems(tc.Id, "Tests"));
}

Results are written to a custom integer field Custom.RequirementsCovered on each defect work item.

Analytics Refresh Integration: Configured the Analytics service to include the custom coverage field in its schema. This required modifying the Analytics view definition to explicitly include Custom.RequirementsCovered as a dimension. After the function updates defect work items, the next Analytics refresh (we run hourly) picks up the coverage values automatically.

Traceability Matrix Accuracy: Implemented a validation layer that compares the calculated coverage against manual traceability matrix queries. Any discrepancies trigger alerts to the QA team. This caught several cases where test cases had orphaned requirement links due to requirement deletion or renaming.

Release Gates Configuration: Modified release pipeline gates to query Analytics for Custom.RequirementsCovered > 0 instead of trying to traverse relationships at gate evaluation time. The gate now completes in under 3 seconds versus 45+ seconds with the old WIQL approach.

Key implementation details:

  • Azure Function runs every 2 hours (configurable)
  • Processes 200-300 defects per execution in under 90 seconds
  • Uses Azure DevOps PAT with work item read/write permissions
  • Handles edge cases: deleted requirements, circular links, cross-project references
  • Maintains audit log of coverage calculations for compliance

The solution has been running in production for 6 months across 15 teams. Release gate failures due to coverage issues dropped from 40% to under 2%. The custom field approach also enables better Power BI reporting since coverage is now a simple numeric dimension.

Critical configuration: Ensure your custom field is indexed in Analytics by setting IsIndexed=true in the process template. Without indexing, queries against large defect datasets will timeout.

The traceability matrix discrepancy you’re seeing is likely due to how different Azure DevOps components handle relationship queries. The work item tracking system supports deep relationship traversal, but Analytics uses a pre-computed dimensional model that only indexes direct links. This is documented behavior, though not widely known. Your release gate dependency on Analytics coverage is the root issue-Analytics wasn’t designed for transitive relationship validation.

For release gates specifically, we bypass the Analytics service entirely and use WIQL queries with custom logic. The gate runs a query that fetches all defects in the release, retrieves their test case links via REST API, then queries requirements from those test cases. It’s more computationally expensive but gives accurate real-time coverage data. The gate script caches results for 1 hour to avoid performance issues during frequent deployments.

Check your Analytics refresh schedule and scope configuration. If the refresh is set to incremental mode, relationship changes might not propagate correctly. Try forcing a full refresh of the analytics database. Also verify that your Analytics views include the correct work item types and relationship types in the filter criteria. Sometimes the view definition excludes certain link types which causes coverage calculations to fail.

We solved this by implementing a nightly ETL job that materializes the transitive links. The job queries all defects, walks their test case relationships, extracts linked requirements, then writes those as custom fields on the defect work items. This makes the coverage data directly queryable by Analytics without complex joins. The custom field approach works well for release gate validation since gates can evaluate simple field values rather than relationship queries.

The Analytics service in Azure DevOps has a known limitation with transitive relationship queries. It doesn’t automatically traverse multi-hop links like Defect→TestCase→Requirement. The analytics data model flattens direct relationships only, which explains why your coverage calculation returns zero. You’ll need to either create explicit defect-to-requirement links or build custom analytics queries that manually join the relationship tables.