Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Host Based Unit Test updates #837

Merged
merged 4 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def do_post_build(self, thebuilder):
""").strip())
return 0

error_messages = [] # MU_CHANGE- Check for invalid tests
for test in testList:
# Configure output name if test uses cmocka.
shell_env.set_shell_var(
Expand All @@ -120,7 +121,20 @@ def do_post_build(self, thebuilder):
for xml_result_file in xml_results_list:
root = xml.etree.ElementTree.parse(
xml_result_file).getroot()
# MU_CHANGE [BEGIN] - Check for invalid tests
if len(root) == 0:
error_messages.append(f'{os.path.basename(test)} did not generate a test suite(s).')
Javagedes marked this conversation as resolved.
Show resolved Hide resolved
error_messages.append(' Review source code to ensure Test suites are created and tests '
' are registered!')
failure_count += 1
for suite in root:
if len(suite) == 0:
error_messages.append(f'TestSuite [{suite.attrib["name"]}] for test {test} did not '
'contain a test case(s).')
error_messages.append(' Review source code to ensure test cases are registered to '
'the suite!')
failure_count += 1
# MU_CHANGE [END] - Check for invalid tests
for case in suite:
for result in case:
if result.tag == 'failure':
Expand All @@ -130,7 +144,7 @@ def do_post_build(self, thebuilder):
" %s - %s" % (case.attrib['name'], result.text))
failure_count += 1

if thebuilder.env.GetValue("CODE_COVERAGE") != "FALSE":
if thebuilder.env.GetValue("CODE_COVERAGE", "FALSE") == "TRUE": # MU_CHANGE
if thebuilder.env.GetValue("TOOL_CHAIN_TAG") == "GCC5":
ret = self.gen_code_coverage_gcc(thebuilder)
if ret != 0:
Expand All @@ -151,6 +165,10 @@ def do_post_build(self, thebuilder):
return -1
# MU_CHANGE end - reformat coverage data

# MU_CHANGE [BEGIN] - Check for invalid tests
for error in error_messages:
logging.error(error)
# MU_CHANGE [END] - Check for invalid tests
return failure_count

def gen_code_coverage_gcc(self, thebuilder):
Expand Down
25 changes: 22 additions & 3 deletions UnitTestFrameworkPkg/ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -1491,17 +1491,36 @@ GTEST_OUTPUT=xml:<absolute or relative path to output file>

This mode is used by the test running plugin to aggregate the results for CI test status reporting in the web view.

### XML Reporting Test Consolidation

There exists multiple tools for consolidating and generating consolidated test results from the
test xml files that are generated. The arguably most convenient tool available is the
`xunit-viewer` node package, installed via `npm install -g xunit-viewer`. This tool can
consolidate all generated xml reports and create an html or cli summary of test results.

The following command will generate a consolidated report at `<report_name>.html` and
also print summary overview of the test results to the command line:

`xunit-viewer --results Build --output <report_name>.html --console`

### Code Coverage

Code coverage can be enabled for Host based Unit Tests with `CODE_COVERAGE=TRUE`, which generates a cobertura report
per package tested, and combined cobertura report for all packages tested. The per-package cobertura report will be
present at `Build/<Pkg>/HostTest/<Target_Toolchain>/<Pkg>_coverage.xml`. The overall cobertura report will be present
at `Build/coverage.xml`

Code coverage generation has two config knobs:
Code coverage generation has three config knobs. Each can be turned on/off by setting it to TRUE
or FALSE e.g. `CC_REORGANIZE=TRUE`:

1. `CC_REORGANIZE`: Controls if code coverage results are re-formatted into a "by-inf" folder
structure rather than the default "by-test" folder structure. Default: `TRUE`
1. `CC_FULL`: Generates zero'd out coverage data for untested source files in the package.
Default: `FALSE`
1. `CC_FLATTEN`: Groups all source files together, rather than by INF. Default: `FALSE`

1. `CC_FULL`: If set to `TRUE`, will generate zero'd out coverage data for untested source files in the package.
2. `CC_FLATTEN`: If Set to `TRUE`, will group all source files together, rather than by INF.
** NOTE: `CC_FULL` and `CC_FLATTEN` values only matter if `CC_REORGANIZE=TRUE`, as they only
effect how the coverage report is reorganized.

**TIP: `CC_FLATTEN=TRUE/FALSE` will produce different coverage percentage results as `TRUE` de-duplicates source files
that are consumed by multiple INFs.
Expand Down
3 changes: 2 additions & 1 deletion UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@
"cobertura", # tool for code coverage
"pycobertura", # tool for code coverage
"loongarch",
"loongson"
"loongson",
"xunit",
],
"IgnoreStandardPaths": [], # Standard Plugin defined paths that should be ignore
"AdditionalIncludePaths": [] # Additional paths to spell check (wildcards supported)
Expand Down
Loading