Run tests, then collect result and coverage #24
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Run tests, then collect result and coverage | |
#on: { push: { paths-ignore: [ 'README.md', 'LICENSE', '**/requirements.txt' ] }, workflow_dispatch } | |
on: { workflow_dispatch } | |
# Configuration | |
env: | |
strPlatform: x86 # or x64 | |
strConfiguration: Debug # or Release | |
strNameOccSetupFile: OpenCppCoverageSetup-x86-0.9.9.0.exe | |
strGhTagOccSetupFile: release-0.9.9.0 # from https://github.com/OpenCppCoverage/OpenCppCoverage/tags | |
strNameCppcheckSetupFile: cppcheck-2.11-x64-Setup.msi | |
strGhTagCppcheckSetupFile: 2.11 # from https://github.com/danmar/cppcheck/releases/tag/ | |
strOccExecutable: OpenCppCoverage.exe | |
relHtmlReport: HtmlReportOcc | |
strCoberturaReport: CoberturaReportOcc.xml | |
relGtestOutput: GtestOutput | |
module0: GTest1.exe | |
module1: GTestDefWindowProc.exe | |
module2: GTestEmptyWorkingSet.exe | |
module3: GTestMem.exe | |
jobs: | |
collect-tests-code-coverage: | |
runs-on: windows-latest | |
permissions: | |
actions: read # for "dawidd6/action-download-artifact@v2" | |
contents: read # for "actions/checkout@v3" when GITHUB_TOKEN | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Set values (windows-latest) | |
run: | # build from *.sln, all tests | |
echo "dirTestExecutables=${{github.workspace}}\qa\UnitTest\bin\${{env.strPlatform}}\${{env.strConfiguration}}" >> $env:GITHUB_ENV | |
echo "strCfg=${{env.strPlatform}}-${{env.strConfiguration}}" >> $env:GITHUB_ENV | |
echo "dirSetupOcc=${env:Programfiles}\Occ" >> $env:GITHUB_ENV | |
echo "dirSetupCppcheck=${env:Programfiles}\cppcheck" >> $env:GITHUB_ENV | |
- name: Download artifact | |
uses: dawidd6/action-download-artifact@v2 | |
with: | |
github_token: ${{secrets.GITHUB_TOKEN}} | |
workflow: build-tests-gtest-debug-x86.yml | |
name: artifact-build-tests-gtest-${{env.strCfg}} | |
path: ${{env.dirTestExecutables}} | |
search_artifacts: true | |
- name: Cache tool Occ | |
uses: actions/cache@v3 | |
with: | |
path: ${{env.dirSetupOcc}} | |
key: cache-key-tool-occ-${{env.strNameOccSetupFile}} | |
id: cache-tool-occ | |
- name: Download tool Occ | |
if: steps.cache-tool-occ.outputs.cache-hit != 'true' | |
uses: robinraju/release-downloader@v1.8 | |
with: | |
repository: OpenCppCoverage/OpenCppCoverage | |
fileName: ${{env.strNameOccSetupFile}} | |
tag: ${{env.strGhTagOccSetupFile}} | |
- name: Install tool Occ | |
if: steps.cache-tool-occ.outputs.cache-hit != 'true' | |
run: | | |
$arglist="/VERYSILENT /SUPPRESSMSGBOXES /DIR=""${{env.dirSetupOcc}}"" /LOG=""${{runner.temp}}\${{env.strNameOccSetupFile}}.log""" | |
Start-Process "${{env.strNameOccSetupFile}}" -ArgumentList $arglist -Wait | |
#type "${{runner.temp}}\${{env.strNameOccSetupFile}}.log" | |
- name: Run tool Occ | |
continue-on-error: true | |
run: | # double launching because windows system hooks from AppCompat conflicts with gmock-win32 hooks | |
@( | |
"${{env.module0}}" | |
, "${{env.module1}}" | |
, "${{env.module2}}" | |
, "${{env.module3}}" | |
).ForEach{ Start-Process "${{env.dirTestExecutables}}\$_" -ArgumentList '--gtest_repeat=0' -NoNewWindow; } | |
$common_args='-q --working_dir "src"' | |
$modules="--modules ${{env.dirTestExecutables}}" | |
$sep = ' --excluded_sources '; $excluded_sources = $sep + ( '"{0}"' -f ( @( | |
'src\Main.h' | |
, 'src\Legacy' | |
, 'qa\UnitTest' | |
, 'D:\a\_work' | |
, 'C:\Program Files' | |
) -join '"'+$sep+'"') ); | |
$excluded_line_regex='--excluded_line_regex .*@NOCOVERAGE.*' | |
Function runnerOcc_ ( $arg_program ) { | |
$export_type="--export_type binary:${{runner.temp}}\${arg_program}.cov" | |
$program_to_run="${{env.dirTestExecutables}}\$arg_program --gtest_brief=1 --gtest_output=xml:${{runner.temp}}\${{env.relGtestOutput}}\$arg_program.xml" | |
Start-Process -Wait -NoNewWindow "${{env.dirSetupOcc}}\${{env.strOccExecutable}}" -ArgumentList "$common_args $modules $excluded_sources $excluded_line_regex $export_type -- $program_to_run" | |
} | |
runnerOcc_ ${{env.module0}} | |
runnerOcc_ ${{env.module1}} | |
runnerOcc_ ${{env.module2}} | |
runnerOcc_ ${{env.module3}} | |
# Change html template | |
$ffnOccTemplate="${{env.dirSetupOcc}}\Template\MainTemplate.html" | |
(Get-Content $ffnOccTemplate).replace('{{TITLE}}', 'Merged from all tests') | Set-Content $ffnOccTemplate | |
$export_type="--export_type html:${{runner.temp}}\${{env.relHtmlReport}} --export_type cobertura:${{runner.temp}}\${{env.strCoberturaReport}}" | |
$sep = " --input_coverage ${{runner.temp}}\"; | |
$input_coverage = $sep + ( @( | |
"${{env.module0}}.cov" | |
, "${{env.module1}}.cov" | |
, "${{env.module2}}.cov" | |
, "${{env.module3}}.cov" | |
) -join $sep ); | |
Start-Process -Wait -NoNewWindow "${{env.dirSetupOcc}}\${{env.strOccExecutable}}" -ArgumentList "$input_coverage $export_type" | |
[xml]$oSystem_Xml_XmlDocument = Get-Content ${{runner.temp}}\${{env.strCoberturaReport}}; | |
$oSystem_Xml_XmlElement = $oSystem_Xml_XmlDocument.GetElementsByTagName( 'coverage' ).Item( 0 ); | |
$uLinesCovered = $oSystem_Xml_XmlElement.GetAttribute( 'lines-covered' ); | |
$uLinesValid = $oSystem_Xml_XmlElement.GetAttribute( 'lines-valid' ); | |
$dCoveredPercent = ( 100 * ( $uLinesCovered / $uLinesValid ) ); | |
$strCoveredPercent = [math]::Round( $dCoveredPercent, 2 ); | |
echo "strCoverageValue=$strCoveredPercent" >> $env:GITHUB_ENV | |
- name: Generate *.svg file for badge TestsCoverage if success | |
if: ${{ success( ) }} | |
uses: emibcn/badge-action@v2.0.2 | |
with: | |
label: Tests coverage | |
status: ${{env.strCoverageValue}}% | |
color: ${{ false | |
|| env.strCoverageValue > 90 && 'green' | |
|| env.strCoverageValue > 80 && 'yellow,green' | |
|| env.strCoverageValue > 70 && 'yellow' | |
|| env.strCoverageValue > 60 && 'orange,yellow' | |
|| env.strCoverageValue > 50 && 'orange' | |
|| env.strCoverageValue > 40 && 'red,orange' | |
|| env.strCoverageValue > 30 && 'red,red,orange' | |
|| env.strCoverageValue > 20 && 'red,red,red,orange' | |
|| 'red' }} | |
path: TestsCoverage-Occ-${{runner.os}}-${{env.strCfg}}.svg | |
# env-s not pass between steps when failure | |
- name: Generate *.svg file for badge TestsCoverage if failure | |
if: ${{ failure( ) }} | |
uses: emibcn/badge-action@v2.0.2 | |
with: | |
label: Tests coverage | |
status: failing | |
color: red | |
path: TestsCoverage-Occ-${{runner.os}}-${{env.strCfg}}.svg | |
- name: Put *.svg file to Gists for badge TestsCoverage | |
if: ${{ success( ) || failure( ) }} # yes, not 'always( )' because 'cancelled( )' | |
uses: exuanbo/actions-deploy-gist@v1 | |
with: | |
token: ${{ secrets.ACCESS_TO_GIST }} | |
gist_id: 2af621bdd237231125e907ea81b1f8a8 | |
file_path: TestsCoverage-Occ-${{runner.os}}-${{env.strCfg}}.svg | |
- uses: actions/setup-python@v4 | |
with: | |
python-version: 3.10 # need for metrixpp/metrix++ because "python ValueError: invalid mode: 'rU'" | |
cache: pip | |
- name: Install xml merger | |
run: pip install junitparser | |
- name: Merge xml reports | |
run: junitparser merge --suite-name AllTests --glob "${{runner.temp}}\${{env.relGtestOutput}}\*.xml" "${{env.strCfg}}.xml" | |
- name: Install gtest xml to html converter | |
run: git clone https://github.com/Alex0vSky/gtest_report | |
- name: Convert xml to html | |
working-directory: ./gtest_report # directory html_resources must be in current dir | |
run: | | |
py scripts\genHtmlReportFromGtest.py "out\GoogleTestCombinedOutput.html" "..\${{env.strCfg}}.xml" | |
mv -v "out" ${{runner.temp}}\GoogleTestCombinedOutput | |
[xml]$oSystem_Xml_XmlDocument = Get-Content ..\${{env.strCfg}}.xml | |
$oSystem_Xml_XmlElement = $oSystem_Xml_XmlDocument.GetElementsByTagName( 'testsuites' ).Item( 0 ); | |
$uTests = $oSystem_Xml_XmlElement.GetAttribute( 'tests' ); | |
echo "uTests=$uTests" >> $env:GITHUB_ENV | |
- name: Generate *.svg file for badge GoogleTest | |
uses: emibcn/badge-action@v2.0.2 | |
with: | |
label: GoogleTest | |
status: ${{env.uTests}} testsuites | |
path: GoogleTest-testsuites-${{runner.os}}-${{env.strCfg}}.svg | |
- name: Put *.svg file to Gists for badge GoogleTest | |
uses: exuanbo/actions-deploy-gist@v1 | |
with: | |
token: ${{ secrets.ACCESS_TO_GIST }} | |
gist_id: 2af621bdd237231125e907ea81b1f8a8 | |
file_path: GoogleTest-testsuites-${{runner.os}}-${{env.strCfg}}.svg | |
- name: Install metrics code | |
run: pip install metrixpp | |
- name: Run metrics code | |
run: | | |
$strVersionMetrixpp=( pip show metrixpp |findstr Version ) -replace 'Version: ','' | |
"Version: $strVersionMetrixpp" > ${{runner.temp}}\metrixpp.txt | |
metrix++ collect --log-level=ERROR --std.code.lines.code --std.code.lines.comments --std.code.complexity.cyclomatic --db-file=${{runner.temp}}\metrixpp.db -- ${{github.workspace}}\src | |
metrix++ view --log-level=ERROR --db-file=${{runner.temp}}\metrixpp.db -- ${{github.workspace}}\src >> ${{runner.temp}}\metrixpp.txt | |
metrix++ view --log-level=ERROR --format=xml --db-file=${{runner.temp}}\metrixpp.db -- ${{github.workspace}}\src > ${{runner.temp}}\metrixpp.xml | |
[xml]$oSystem_Xml_XmlDocument = Get-Content ${{runner.temp}}\metrixpp.xml | |
$uLocTotalCode = $oSystem_Xml_XmlDocument.GetElementsByTagName( 'std.code.lines' ).GetElementsByTagName( 'code' ).GetAttribute( 'total' ); | |
$uLocTotalComments = $oSystem_Xml_XmlDocument.GetElementsByTagName( 'std.code.lines' ).GetElementsByTagName( 'comments' ).GetAttribute( 'total' ); | |
$child = $oSystem_Xml_XmlDocument.CreateElement( 'Version' ) | |
$child.InnerText = $strVersionMetrixpp; | |
$oSystem_Xml_XmlDocument.DocumentElement.AppendChild( $child ); | |
$oSystem_Xml_XmlDocument.Save( "${{runner.temp}}\metrixpp.xml" ) | |
$uLocTotalCode = [math]::Round( $uLocTotalCode, 0 ); | |
$uLocTotalComments = [math]::Round( $uLocTotalComments, 0 ); | |
echo "metrixpp_uLocTotalCode=$uLocTotalCode" >> $env:GITHUB_ENV | |
echo "metrixpp_uLocTotalComments=$uLocTotalComments" >> $env:GITHUB_ENV | |
- name: Generate *.svg file for badge LinesOfСode | |
uses: emibcn/badge-action@v2.0.2 | |
with: | |
label: LinesOfСode | |
status: ${{env.metrixpp_uLocTotalCode}} | |
color: a9a9a9 # darkgrey=a9a9a9, lightgrey=d3d3d3 | |
path: Metrixpp-LinesOfСode.svg | |
- name: Put *.svg file to Gists for badge LinesOfСode | |
uses: exuanbo/actions-deploy-gist@v1 | |
with: | |
token: ${{ secrets.ACCESS_TO_GIST }} | |
gist_id: 2af621bdd237231125e907ea81b1f8a8 | |
file_path: Metrixpp-LinesOfСode.svg | |
- name: Generate *.svg file for badge Comments | |
uses: emibcn/badge-action@v2.0.2 | |
with: | |
label: Comments | |
status: ${{env.metrixpp_uLocTotalComments}} | |
color: a9a9a9 # darkgrey=a9a9a9, lightgrey=d3d3d3 | |
path: Metrixpp-Comments.svg | |
- name: Put *.svg file to Gists for badge Comments | |
uses: exuanbo/actions-deploy-gist@v1 | |
with: | |
token: ${{ secrets.ACCESS_TO_GIST }} | |
gist_id: 2af621bdd237231125e907ea81b1f8a8 | |
file_path: Metrixpp-Comments.svg | |
- name: Install GoogleStyle cpplint | |
run: pip install cpplint | |
- name: Run GoogleStyle cpplint | |
id: RunToolGoogleStyleCpplint | |
continue-on-error: true # when cpplint return error | |
run: | | |
$strVersionCpplint=(pip show cpplint |findstr Version) -replace 'Version: ','' | |
$arrFilter = @( | |
'whitespace/tab', | |
'whitespace/end_of_line', | |
'whitespace/parens', | |
'readability/namespace', | |
'whitespace/comments' | |
); | |
$filter = '-' + ( $arrFilter -join ',-' ); | |
$linelength=120 | |
$cpplint_args="--linelength=$linelength --filter=$filter --exclude=src\MsvcGenerated\* --exclude=src\Legacy\* --recursive --output=junit src"; | |
Start-Process -Wait -NoNewWindow cpplint -ArgumentList $cpplint_args -RedirectStandardError ${{runner.temp}}\cpplint.xml | |
[xml]$oSystem_Xml_XmlDocument = Get-Content ${{runner.temp}}\cpplint.xml | |
$cpplint_failures = $oSystem_Xml_XmlDocument.GetElementsByTagName( 'testsuite' ).GetAttribute( 'failures' ); | |
$child = $oSystem_Xml_XmlDocument.CreateElement( 'Arguments' ) | |
$child.InnerText = $cpplint_args; | |
$oSystem_Xml_XmlDocument.DocumentElement.AppendChild( $child ); | |
$child = $oSystem_Xml_XmlDocument.CreateElement( 'Version' ) | |
$child.InnerText = $strVersionCpplint; | |
$oSystem_Xml_XmlDocument.DocumentElement.AppendChild( $child ); | |
$oSystem_Xml_XmlDocument.Save( "${{runner.temp}}\cpplint.xml" ) | |
echo "cpplint_failures=$cpplint_failures" >> $env:GITHUB_ENV | |
echo "cpplint_arrFilter_Count=$($arrFilter.Count)" >> $env:GITHUB_ENV | |
echo "cpplint_linelength=$linelength" >> $env:GITHUB_ENV | |
- name: Generate *.svg file for badge GoogleStyle cpplint if success | |
if: steps.RunToolGoogleStyleCpplint.outcome == 'success' && env.cpplint_failures == '0' | |
uses: emibcn/badge-action@v2.0.2 | |
with: | |
label: cpplint | |
status: ${{env.cpplint_arrFilter_Count}} filters, linelength=${{env.cpplint_linelength}} | |
path: GoogleStyle_cpplint.svg | |
- name: Generate *.svg file for badge GoogleStyle cpplint if failure | |
if: env.cpplint_failures > 0 || env.cpplint_failures == '' | |
uses: emibcn/badge-action@v2.0.2 | |
with: | |
label: cpplint | |
status: failing | |
color: red | |
path: GoogleStyle_cpplint.svg | |
- name: Put *.svg file to Gists for badge GoogleStyle cpplint | |
uses: exuanbo/actions-deploy-gist@v1 | |
with: | |
token: ${{ secrets.ACCESS_TO_GIST }} | |
gist_id: 2af621bdd237231125e907ea81b1f8a8 | |
file_path: GoogleStyle_cpplint.svg | |
- name: Cache tool cppcheck | |
uses: actions/cache@v3 | |
with: | |
path: ${{env.dirSetupCppcheck}} | |
key: cache-key-tool-cppcheck-${{env.strNameCppcheckSetupFile}} | |
id: cache-tool-cppcheck | |
- name: Download tool cppcheck | |
if: steps.cache-tool-cppcheck.outputs.cache-hit != 'true' | |
uses: robinraju/release-downloader@v1.8 | |
with: | |
repository: danmar/cppcheck | |
fileName: ${{env.strNameCppcheckSetupFile}} | |
tag: ${{env.strGhTagCppcheckSetupFile}} | |
- name: Install tool cppcheck | |
if: steps.cache-tool-cppcheck.outputs.cache-hit != 'true' | |
run: | | |
$arglist = "/i ""${{github.workspace}}\${{env.strNameCppcheckSetupFile}}"" INSTALLDIR=""${{env.dirSetupCppcheck}}"" TARGETDIR=""${{env.dirSetupCppcheck}}"" ALLUSERS=2 MSIINSTALLPERUSER=1 /quiet /norestart /log ""${{runner.temp}}\${{env.strNameCppcheckSetupFile}}.log"" " | |
$uWait_seconds = 60; | |
$ps = new-object System.Diagnostics.Process; $ps.StartInfo.UseShellExecute = $false; $ps.StartInfo.WorkingDirectory = Get-Location; | |
$ps.StartInfo.Filename = "msiexec" | |
$ps.StartInfo.Arguments = $arglist | |
$uWait_milliseconds = $uWait_seconds *1000; | |
$ps.start( ); $ps.WaitForExit( $uWait_milliseconds ); | |
type "${{runner.temp}}\${{env.strNameCppcheckSetupFile}}.log" | |
- name: Run tool cppcheck | |
id: RunToolCppcheck | |
continue-on-error: true | |
run: | | |
$common = ' --std=c++14 --platform=win32A --library=microsoft_sal --library=windows --enable=all -q --xml '; | |
$include = ''; | |
$include += ' -I "resource"' | |
$include += ' -I "src"' | |
$include += ' -I "ThirdParty\SynCOMAPIv1_0\Include"' | |
$defines = '' | |
$defines += ' -DDECLSPEC_IMPORT=__declspec(import)' | |
$defines += ' -D_X86_=1' | |
$defines += ' -D_M_HYBRID_X86_ARM64=1' | |
$suppress = ' --suppress=missingIncludeSystem --suppress=missingInclude:*\SynCtrl.h --suppress=preprocessorErrorDirective:*\SynCtrl.h' | |
$cppcheck_exe = "${{env.dirSetupCppcheck}}\cppcheck.exe" | |
$cppcheck_args = $common + $include + $defines + $suppress + ' ' + 'src'; | |
Start-Process -Wait -NoNewWindow $cppcheck_exe -ArgumentList $cppcheck_args -RedirectStandardError ${{runner.temp}}\cppcheck.xml | |
[xml]$oSystem_Xml_XmlDocument = Get-Content ${{runner.temp}}\cppcheck.xml | |
$uCountError = $oSystem_Xml_XmlDocument.GetElementsByTagName( 'results' ).GetElementsByTagName( 'errors' ).GetElementsByTagName( 'error' ).Count; | |
[xml]$oSystem_Xml_XmlDocument = Get-Content ${{runner.temp}}\cppcheck.xml | |
$child = $oSystem_Xml_XmlDocument.CreateElement( 'Arguments' ) | |
$child.InnerText = $cppcheck_args; | |
$oSystem_Xml_XmlDocument.DocumentElement.AppendChild( $child ); | |
$oSystem_Xml_XmlDocument.Save( "${{runner.temp}}\cppcheck.xml" ) | |
echo "cppcheck_uCountError=$uCountError" >> $env:GITHUB_ENV | |
- name: Generate *.svg file for badge cppcheck if success | |
if: steps.RunToolCppcheck.outcome == 'success' && env.cppcheck_uCountError == '0' | |
uses: emibcn/badge-action@v2.0.2 | |
with: | |
label: cppcheck | |
status: enable=all | |
color: green | |
path: StaticAnalysis_cppcheck.svg | |
- name: Generate *.svg file for badge cppcheck if failure | |
if: env.cppcheck_uCountError > 0 || env.cppcheck_uCountError == '' | |
uses: emibcn/badge-action@v2.0.2 | |
with: | |
label: cppcheck | |
status: ${{env.cppcheck_uCountError}} errors | |
color: red | |
path: StaticAnalysis_cppcheck.svg | |
- name: Put *.svg file to Gists for badge cppcheck | |
uses: exuanbo/actions-deploy-gist@v1 | |
with: | |
token: ${{ secrets.ACCESS_TO_GIST }} | |
gist_id: 2af621bdd237231125e907ea81b1f8a8 | |
file_path: StaticAnalysis_cppcheck.svg | |
- uses: actions/upload-artifact@v3 | |
with: | |
name: artifact-coverage-tests-OpenCppCoverage-${{env.strCfg}} | |
path: | | |
${{ runner.temp }}\${{ env.relHtmlReport }} | |
${{ runner.temp }}\GoogleTestCombinedOutput | |
${{ runner.temp }}\metrixpp.txt | |
${{ runner.temp }}\cpplint.xml | |
${{ runner.temp }}\cppcheck.xml | |
${{ runner.temp }}\${{ env.strCoberturaReport }} |