Requirements Coverage Report by Release

Overview

When you view the list of requirements in Spira, you can see the overall test coverage for each requirement as a special Test Coverage column next to the requirement name:

However this is the overall test coverage for the requirement, across all releases it has been tested in.

Suppose you want the test coverage for just a specific release and/or sprint? How would you get that?

At a summary level, you can use the Requirements Regression Coverage home page widget:

However, to get the full list of requirements that makes up this data, you would need to use a custom report instead.

Requirements Test Coverage By Release Report

This section assumes you know how to create a new custom report in Spira, as described in this guide. Create a new Custom Report and choose the option to add a new Custom Section:

In the custom section, choose a name such as "Requirements Test Coverage by Release" and then enter the following ESQL query:

select RQ.REQUIREMENT_ID, RQ.NAME as REQUIREMENT_NAME, RTC.TEST_CASE_ID, TCR.EXECUTION_STATUS_ID, TCR.EXECUTION_STATUS_NAME
from
  SpiraTestEntities.R_Requirements as RQ left join
  SpiraTestEntities.R_RequirementTestCases as RQT on RQ.REQUIREMENT_ID = RQT.REQUIREMENT_ID join
  SpiraTestEntities.R_ReleaseTestCases as RTC on RQT.TEST_CASE_ID = RTC.TEST_CASE_ID left join
    (select TR1.TEST_CASE_ID, TR1.EXECUTION_STATUS_ID, TR1.EXECUTION_STATUS_NAME
    from SpiraTestEntities.R_TestRuns as TR1 join
      (select TR.TEST_CASE_ID, max(TR.END_DATE) as EXECUTION_DATE
      from SpiraTestEntities.R_TestRuns as TR where TR.RELEASE_ID in {${ReleaseAndChildIds}} and TR.PROJECT_ID = ${ProjectId} and TR.END_DATE is not null
      group by TR.TEST_CASE_ID) as TR2 on TR1.TEST_CASE_ID = TR2.TEST_CASE_ID and TR1.END_DATE = TR2.EXECUTION_DATE
    where TR1.RELEASE_ID in {${ReleaseAndChildIds}} and TR1.PROJECT_ID = ${ProjectId}) as TCR on RTC.TEST_CASE_ID = TCR.TEST_CASE_ID
where
  RTC.PROJECT_ID = ${ProjectId} and
  RTC.RELEASE_ID in {${ReleaseAndChildIds}}
group by RQ.REQUIREMENT_ID, RQ.NAME, RTC.TEST_CASE_ID, TCR.EXECUTION_STATUS_ID, TCR.EXECUTION_STATUS_NAME
order by RQ.NAME, RQ.REQUIREMENT_ID, TCR.EXECUTION_STATUS_ID

For the XSLT template, instead of using the option to auto-generate, use this template instead:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:key name="groups" match="/RESULTS/ROW" use="REQUIREMENT_ID" />
  <xsl:template match="/RESULTS">
    <table class="DataGrid">
		<tr>
			<th>Req ID</th>
			<th>Requirement Name</th>
			<th>Test Case Coverage</th>
			<th>Graph</th>
		</tr>
		<xsl:apply-templates select="ROW[generate-id() = generate-id(key('groups', REQUIREMENT_ID)[1])]"/>
	</table>
  </xsl:template>
  <xsl:template match="ROW">
        <tr>
			<td>RQ:<xsl:value-of select="REQUIREMENT_ID"/></td>
			<td><xsl:value-of select="REQUIREMENT_NAME"/></td>
			<td>
				<xsl:for-each select="key('groups', REQUIREMENT_ID)">
					TC:<xsl:value-of select="TEST_CASE_ID"/> = 
					<xsl:choose>
						<xsl:when test="EXECUTION_STATUS_NAME != ''">
							<xsl:value-of select="EXECUTION_STATUS_NAME " />
						</xsl:when>
						<xsl:otherwise>
							<xsl:text>Not Run</xsl:text>
						</xsl:otherwise>
					</xsl:choose>, 
				</xsl:for-each>
			</td>
			<td>
				<div style="display:inline-block; white-space: nowrap">
					<xsl:for-each select="key('groups', REQUIREMENT_ID)">
						<xsl:choose>
							<xsl:when test="EXECUTION_STATUS_NAME = 'Passed'">
								<div style="display:inline-block; background-color:lime; height: 20px; width: 20px"></div>
							</xsl:when>
							<xsl:when test="EXECUTION_STATUS_NAME = 'Failed'">
								<div style="display:inline-block; background-color:red; height: 20px; width: 20px"></div>
							</xsl:when>
							<xsl:when test="EXECUTION_STATUS_NAME = 'Blocked'">
								<div style="display:inline-block; background-color:yellow; height: 20px; width: 20px"></div>
							</xsl:when>
							<xsl:when test="EXECUTION_STATUS_NAME = 'Caution'">
								<div style="display:inline-block; background-color:orange; height: 20px; width: 20px"></div>
							</xsl:when>
							<xsl:otherwise>
								<div style="display:inline-block; background-color:silver; height: 20px; width: 20px"></div>
							</xsl:otherwise>
						</xsl:choose>				
					</xsl:for-each>
				</div>
			</td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

When you run the new custom report, you will see a table like the following:

You can run this custom report for any release in the product.

*Note that this report template will only look good in HTML format because of the inline graph. If you want to display in PDF or MS-Word, use this simplified template instead:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:key name="groups" match="/RESULTS/ROW" use="REQUIREMENT_ID" />
  <xsl:template match="/RESULTS">
    <table class="DataGrid">
		<tr>
			<th>Req ID</th>
			<th>Requirement Name</th>
			<th>Test Case Coverage</th>
		</tr>
		<xsl:apply-templates select="ROW[generate-id() = generate-id(key('groups', REQUIREMENT_ID)[1])]"/>
	</table>
  </xsl:template>
  <xsl:template match="ROW">
        <tr>
			<td>RQ:<xsl:value-of select="REQUIREMENT_ID"/></td>
			<td><xsl:value-of select="REQUIREMENT_NAME"/></td>
			<td>
				<xsl:for-each select="key('groups', REQUIREMENT_ID)">
					TC:<xsl:value-of select="TEST_CASE_ID"/> = 
					<xsl:choose>
						<xsl:when test="EXECUTION_STATUS_NAME != ''">
							<xsl:value-of select="EXECUTION_STATUS_NAME " />
						</xsl:when>
						<xsl:otherwise>
							<xsl:text>Not Run</xsl:text>
						</xsl:otherwise>
					</xsl:choose>, 
				</xsl:for-each>
			</td>
        </tr>
    </xsl:template>
</xsl:stylesheet>