Implemented 'unittest_report_xml_directory' and 'unittest_report_xml_filename'.

This commit is contained in:
Patrick Lehmann
2024-12-18 22:22:54 +01:00
parent 70134b31c3
commit 12991ee38a
5 changed files with 81 additions and 94 deletions

View File

@@ -135,11 +135,14 @@ jobs:
UnitTesting: UnitTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@dev uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@dev
needs: needs:
- ConfigParams
- UnitTestingParams - UnitTestingParams
with: with:
jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }} jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }}
requirements: "-r tests/unit/requirements.txt" requirements: "-r tests/unit/requirements.txt"
# pacboy: "msys/git python-lxml:p" # pacboy: "msys/git python-lxml:p"
unittest_report_xml_directory: ${{ needs.ConfigParams.outputs.unittest_report_xml_directory }}
unittest_report_xml_filename: ${{ needs.ConfigParams.outputs.unittest_report_xml_filename }}
unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }} unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }} coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}

View File

@@ -59,18 +59,33 @@ on:
mypy_prepare_command: mypy_prepare_command:
description: "" description: ""
value: ${{ jobs.Extract.outputs.mypy_prepare_command }} value: ${{ jobs.Extract.outputs.mypy_prepare_command }}
unittest_report_xml_directory:
description: ""
value: ${{ jobs.Extract.outputs.unittest_report_xml_directory }}
unittest_report_xml_filename:
description: ""
value: ${{ jobs.Extract.outputs.unittest_report_xml_filename }}
unittest_report_xml:
description: ""
value: ${{ jobs.Extract.outputs.unittest_report_xml }}
coverage_report_html_directory: coverage_report_html_directory:
description: "" description: ""
value: ${{ jobs.Extract.outputs.coverage_report_html_directory }} value: ${{ jobs.Extract.outputs.coverage_report_html_directory }}
coverage_report_xml_directory: coverage_report_xml_directory:
description: "" description: ""
value: ${{ jobs.Extract.outputs.coverage_report_xml_directory }} value: ${{ jobs.Extract.outputs.coverage_report_xml_directory }}
coverage_report_xml_filename:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_xml_filename }}
coverage_report_xml: coverage_report_xml:
description: "" description: ""
value: ${{ jobs.Extract.outputs.coverage_report_xml }} value: ${{ jobs.Extract.outputs.coverage_report_xml }}
coverage_report_json_directory: coverage_report_json_directory:
description: "" description: ""
value: ${{ jobs.Extract.outputs.coverage_report_json_directory }} value: ${{ jobs.Extract.outputs.coverage_report_json_directory }}
coverage_report_json_filename:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_json_filename }}
coverage_report_json: coverage_report_json:
description: "" description: ""
value: ${{ jobs.Extract.outputs.coverage_report_json }} value: ${{ jobs.Extract.outputs.coverage_report_json }}
@@ -83,10 +98,15 @@ jobs:
package_fullname: ${{ steps.getPackageName.outputs.package_fullname }} package_fullname: ${{ steps.getPackageName.outputs.package_fullname }}
package_directory: ${{ steps.getPackageName.outputs.package_directory }} package_directory: ${{ steps.getPackageName.outputs.package_directory }}
mypy_prepare_command: ${{ steps.getPackageName.outputs.mypy_prepare_command }} mypy_prepare_command: ${{ steps.getPackageName.outputs.mypy_prepare_command }}
unittest_report_xml_directory: ${{ steps.getVariables.outputs.unittest_report_xml_directory }}
unittest_report_xml_filename: ${{ steps.getVariables.outputs.unittest_report_xml_filename }}
unittest_report_xml: ${{ steps.getVariables.outputs.unittest_report_xml }}
coverage_report_html_directory: ${{ steps.getVariables.outputs.coverage_report_html_directory }} coverage_report_html_directory: ${{ steps.getVariables.outputs.coverage_report_html_directory }}
coverage_report_xml_directory: ${{ steps.getVariables.outputs.coverage_report_xml_directory }} coverage_report_xml_directory: ${{ steps.getVariables.outputs.coverage_report_xml_directory }}
coverage_report_xml_filename: ${{ steps.getVariables.outputs.coverage_report_xml_filename }}
coverage_report_xml: ${{ steps.getVariables.outputs.coverage_report_xml }} coverage_report_xml: ${{ steps.getVariables.outputs.coverage_report_xml }}
coverage_report_json_directory: ${{ steps.getVariables.outputs.coverage_report_json_directory }} coverage_report_json_directory: ${{ steps.getVariables.outputs.coverage_report_json_directory }}
coverage_report_json_filename: ${{ steps.getVariables.outputs.coverage_report_json_filename }}
coverage_report_json: ${{ steps.getVariables.outputs.coverage_report_json }} coverage_report_json: ${{ steps.getVariables.outputs.coverage_report_json }}
steps: steps:
@@ -144,9 +164,10 @@ jobs:
from tomli import load as tomli_load from tomli import load as tomli_load
htmlDirectory = Path("htmlcov") coverageHTMLDirectory = Path("htmlcov")
xmlFile = Path("./coverage.xml") unittestXMLFile = Path("./unittest.xml")
jsonFile = Path("./coverage.json") coverageXMLFile = Path("./coverage.xml")
coverageJSONFile = Path("./coverage.json")
coverageRC = "${{ inputs.coverage_config }}".strip() coverageRC = "${{ inputs.coverage_config }}".strip()
# Read output paths from 'pyproject.toml' file # Read output paths from 'pyproject.toml' file
@@ -156,9 +177,10 @@ jobs:
with pyProjectFile.open("rb") as file: with pyProjectFile.open("rb") as file:
pyProjectSettings = tomli_load(file) pyProjectSettings = tomli_load(file)
htmlDirectory = Path(pyProjectSettings["tool"]["coverage"]["html"]["directory"]) unittestXMLFile = Path(pyProjectSettings["tool"]["pytest"]["xml_path"])
xmlFile = Path(pyProjectSettings["tool"]["coverage"]["xml"]["output"]) coverageHTMLDirectory = Path(pyProjectSettings["tool"]["coverage"]["html"]["directory"])
jsonFile = Path(pyProjectSettings["tool"]["coverage"]["json"]["output"]) coverageXMLFile = Path(pyProjectSettings["tool"]["coverage"]["xml"]["output"])
coverageJSONFile= Path(pyProjectSettings["tool"]["coverage"]["json"]["output"])
else: else:
print(f"File '{pyProjectFile}' not found.") print(f"File '{pyProjectFile}' not found.")
print(f"::error title=FileNotFoundError::File '{pyProjectFile}' not found.") print(f"::error title=FileNotFoundError::File '{pyProjectFile}' not found.")
@@ -171,9 +193,9 @@ jobs:
with coverageRCFile.open("rb") as file: with coverageRCFile.open("rb") as file:
coverageRCSettings = tomli_load(file) coverageRCSettings = tomli_load(file)
htmlDirectory = Path(coverageRCSettings["html"]["directory"]) coverageHTMLDirectory = Path(coverageRCSettings["html"]["directory"])
xmlFile = Path(coverageRCSettings["xml"]["output"]) coverageXMLFile = Path(coverageRCSettings["xml"]["output"])
jsonFile = Path(coverageRCSettings["json"]["output"]) coverageJSONFile = Path(coverageRCSettings["json"]["output"])
else: else:
print(f"File '{coverageRCFile}' not found.") print(f"File '{coverageRCFile}' not found.")
print(f"::error title=FileNotFoundError::File '{coverageRCFile}' not found.") print(f"::error title=FileNotFoundError::File '{coverageRCFile}' not found.")
@@ -184,11 +206,16 @@ jobs:
print(f"GITHUB_OUTPUT: {github_output}") print(f"GITHUB_OUTPUT: {github_output}")
with github_output.open("a+", encoding="utf-8") as f: with github_output.open("a+", encoding="utf-8") as f:
f.write(dedent(f"""\ f.write(dedent(f"""\
coverage_report_html_directory={htmlDirectory.as_posix()} coverage_report_html_directory={coverageHTMLDirectory.as_posix()}
coverage_report_xml_directory={xmlFile.parent.as_posix()} unittest_report_xml_directory={unittestXMLFile.parent.as_posix()}
coverage_report_xml={xmlFile.as_posix()} unittest_report_xml_filename={unittestXMLFile.name}
coverage_report_json_directory={jsonFile.parent.as_posix()} unittest_report_xml={unittestXMLFile.as_posix()}
coverage_report_json={jsonFile.as_posix()} coverage_report_xml_directory={coverageXMLFile.parent.as_posix()}
coverage_report_xml_filename={coverageXMLFile.name}
coverage_report_xml={coverageXMLFile.as_posix()}
coverage_report_json_directory={coverageJSONFile.parent.as_posix()}
coverage_report_json_filename={coverageJSONFile.name}
coverage_report_json={coverageJSONFile.as_posix()}
""")) """))
print(f"DEBUG:\n html={htmlDirectory}\n xml={xmlFile}\n json={jsonFile}") print(f"DEBUG:\n unittest xml={unittestXMLFile}\n coverage html={coverageHTMLDirectory}\n coverage xml={coverageXMLFile}\n coverage json={coverageJSONFile}")

View File

@@ -94,6 +94,16 @@ on:
required: false required: false
default: 'unit' default: 'unit'
type: string type: string
unittest_report_xml_directory:
description: 'Path where to save the unittest summary report XML.'
required: false
default: 'report/unit'
type: string
unittest_report_xml_filename:
description: 'Filename of the unittest summary report XML.'
required: false
default: 'TestReportSummary.xml'
type: string
coverage_config: coverage_config:
description: 'Path to the .coveragerc file. Use pyproject.toml by default.' description: 'Path to the .coveragerc file. Use pyproject.toml by default.'
required: false required: false
@@ -323,69 +333,6 @@ jobs:
if: matrix.system == 'msys2' && matrix.runtime == 'UCRT64' && inputs.ucrt64_before_script != '' if: matrix.system == 'msys2' && matrix.runtime == 'UCRT64' && inputs.ucrt64_before_script != ''
run: ${{ inputs.ucrt64_before_script }} run: ${{ inputs.ucrt64_before_script }}
# Read pyproject.toml
- name: 🔁 Extract configurations from pyproject.toml
id: getVariables
shell: python
run: |
from os import getenv
from pathlib import Path
from sys import version
from textwrap import dedent
print(f"Python: {version}")
from tomli import load as tomli_load
htmlDirectory = Path("htmlcov")
xmlFile = Path("./coverage.xml")
jsonFile = Path("./coverage.json")
coverageRC = "${{ inputs.coverage_config }}".strip()
# Read output paths from 'pyproject.toml' file
if coverageRC == "pyproject.toml":
pyProjectFile = Path("pyproject.toml")
if pyProjectFile.exists():
with pyProjectFile.open("rb") as file:
pyProjectSettings = tomli_load(file)
htmlDirectory = Path(pyProjectSettings["tool"]["coverage"]["html"]["directory"])
xmlFile = Path(pyProjectSettings["tool"]["coverage"]["xml"]["output"])
jsonFile = Path(pyProjectSettings["tool"]["coverage"]["json"]["output"])
else:
print(f"File '{pyProjectFile}' not found.")
print(f"::error title=FileNotFoundError::File '{pyProjectFile}' not found.")
exit(1)
# Read output paths from '.coveragerc' file
elif len(coverageRC) > 0:
coverageRCFile = Path(coverageRC)
if coverageRCFile.exists():
with coverageRCFile.open("rb") as file:
coverageRCSettings = tomli_load(file)
htmlDirectory = Path(coverageRCSettings["html"]["directory"])
xmlFile = Path(coverageRCSettings["xml"]["output"])
jsonFile = Path(coverageRCSettings["json"]["output"])
else:
print(f"File '{coverageRCFile}' not found.")
print(f"::error title=FileNotFoundError::File '{coverageRCFile}' not found.")
exit(1)
# Write jobs to special file
github_output = Path(getenv("GITHUB_OUTPUT"))
print(f"GITHUB_OUTPUT: {github_output}")
with github_output.open("a+", encoding="utf-8") as f:
f.write(dedent(f"""\
unittest_report_html_directory={htmlDirectory}
coverage_report_html_directory={htmlDirectory.as_posix()}
coverage_report_xml={xmlFile}
coverage_report_json={jsonFile}
"""))
print(f"DEBUG:\n html={htmlDirectory}\n xml={xmlFile}\n json={jsonFile}")
# Run pytests # Run pytests
- name: ✅ Run unit tests (Ubuntu/macOS) - name: ✅ Run unit tests (Ubuntu/macOS)
@@ -395,7 +342,7 @@ jobs:
export PYTHONPATH=$(pwd) export PYTHONPATH=$(pwd)
cd "${{ inputs.root_directory || '.' }}" cd "${{ inputs.root_directory || '.' }}"
[ -n '${{ inputs.unittest_xml_artifact }}' ] && PYTEST_ARGS='--junitxml=report/unit/TestReportSummary.xml' || unset PYTEST_ARGS [ -n '${{ inputs.unittest_xml_artifact }}' ] && PYTEST_ARGS='--junitxml=${{ inputs.unittest_report_xml_directory }}/${{ inputs.unittest_report_xml_filename }}' || unset PYTEST_ARGS
if [ -n '${{ inputs.coverage_config }}' ]; then if [ -n '${{ inputs.coverage_config }}' ]; then
printf "%s\n" "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}" printf "%s\n" "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}"
coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }} coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}
@@ -411,7 +358,7 @@ jobs:
$env:PYTHONPATH = (Get-Location).ToString() $env:PYTHONPATH = (Get-Location).ToString()
cd "${{ inputs.root_directory || '.' }}" cd "${{ inputs.root_directory || '.' }}"
$PYTEST_ARGS = if ("${{ inputs.unittest_xml_artifact }}") { "--junitxml=report/unit/TestReportSummary.xml" } else { "" } $PYTEST_ARGS = if ("${{ inputs.unittest_xml_artifact }}") { "--junitxml=${{ inputs.unittest_report_xml_directory }}/${{ inputs.unittest_report_xml_filename }}" } else { "" }
if ("${{ inputs.coverage_config }}") { if ("${{ inputs.coverage_config }}") {
Write-Host "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}" Write-Host "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}"
coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }} coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}
@@ -439,14 +386,14 @@ jobs:
# Upload artifacts # Upload artifacts
- name: 📤 Upload 'TestReportSummary.xml' artifact - name: 📤 Upload '${{ inputs.unittest_report_xml_filename }}' artifact
if: inputs.unittest_xml_artifact != '' if: inputs.unittest_xml_artifact != ''
continue-on-error: true continue-on-error: true
uses: pyTooling/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ inputs.unittest_xml_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }} name: ${{ inputs.unittest_xml_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
working-directory: report/unit working-directory: ${{ inputs.unittest_report_xml_directory }}
path: TestReportSummary.xml path: ${{ inputs.unittest_report_xml_filename }}
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1

View File

@@ -27,9 +27,12 @@ jobs:
UnitTesting: UnitTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@dev uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@dev
needs: needs:
- ConfigParams
- UnitTestingParams - UnitTestingParams
with: with:
jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }} jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }}
unittest_report_xml_directory: ${{ needs.ConfigParams.outputs.unittest_report_xml_directory }}
unittest_report_xml_filename: ${{ needs.ConfigParams.outputs.unittest_report_xml_filename }}
unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }} unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
unittest_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }} unittest_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }}
# coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }} # coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}
@@ -40,11 +43,14 @@ jobs:
PlatformTesting: PlatformTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@dev uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@dev
needs: needs:
- ConfigParams
- PlatformTestingParams - PlatformTestingParams
with: with:
jobs: ${{ needs.PlatformTestingParams.outputs.python_jobs }} jobs: ${{ needs.PlatformTestingParams.outputs.python_jobs }}
# tests_directory: "" # tests_directory: ""
unittest_directory: platform unittest_directory: platform
unittest_report_xml_directory: ${{ needs.ConfigParams.outputs.unittest_report_xml_directory }}
unittest_report_xml_filename: ${{ needs.ConfigParams.outputs.unittest_report_xml_filename }}
unittest_xml_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_xml }} unittest_xml_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_xml }}
unittest_html_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_html }} unittest_html_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_html }}
coverage_sqlite_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_sqlite }} coverage_sqlite_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_sqlite }}

View File

@@ -20,6 +20,9 @@ show_error_codes = true
namespace_packages = true namespace_packages = true
html_report = "report/typing" html_report = "report/typing"
[tool.pytest]
junit_xml = "report/unit/TestReportSummary.xml"
[tool.pytest.ini_options] [tool.pytest.ini_options]
addopts = "--tb=native" addopts = "--tb=native"
# Don't set 'python_classes = *' otherwise, pytest doesn't search for classes # Don't set 'python_classes = *' otherwise, pytest doesn't search for classes
@@ -30,6 +33,7 @@ filterwarnings = [
"error::DeprecationWarning", "error::DeprecationWarning",
"error::PendingDeprecationWarning" "error::PendingDeprecationWarning"
] ]
junit_logging = "all"
[tool.interrogate] [tool.interrogate]
color = true color = true