From e7853633fab7758ba2949d83ac05a12c603d5d89 Mon Sep 17 00:00:00 2001 From: Samuel Allan Date: Tue, 23 Jan 2024 16:53:31 +1030 Subject: [PATCH] Allow running unit tests on a single charm This allows scoping a tox run of py3* and cover enviroments to a single charm or ops-sunbeam, to facilitate faster testing. Usage examples: ``` tox -e py3 # test all tox -e py3 -- ops-sunbeam # just the ops sunbeam lib tox -e py3 -- barbican-k8s # only the barbican charm tox -e cover tox -e cover -- ops-sunbeam tox -e cover -- barbican-k8s ``` Closes-Bug: #2050840 Change-Id: Ieb3cd5ad85ee7a04a320cc41fbc3ad406e034a57 --- run_tox.sh | 175 ++++++++++++++++++++++++++++++++--------------------- tox.ini | 8 +-- 2 files changed, 109 insertions(+), 74 deletions(-) diff --git a/run_tox.sh b/run_tox.sh index e0d65e37..fac9efa2 100755 --- a/run_tox.sh +++ b/run_tox.sh @@ -4,9 +4,39 @@ set -o xtrace source common.sh +# print checks to test based on the first arg +get_charms_to_test() { + local charm=$1 + if [[ -z "$charm" ]]; then + ls charms + elif [[ "$charm" = "ops-sunbeam" ]]; then + # ops-sunbeam is treated differently, so don't process it here + false + else + local charms=($(ls charms)) + if [[ ! ${charms[@]} =~ $charm ]]; + then + echo "Argument should be one of ${charms[@]}" >&2 + exit 1 + fi + echo "$charm" + fi +} + +should_test_ops_sunbeam() { + # ops-sunbeam should be tested + # if no arguments (test everything) + # or ops-sunbeam is specified. + if [[ -z "$1" || "$1" = "ops-sunbeam" ]]; then + true + else + false + fi +} + if [[ $1 == "fmt" ]]; then - src_path_array=$(ls -d -1 "charms/"**/src) + src_path_array=$(ls -d -1 "charms/"**/src) tst_path_array=$(ls -d -1 "charms/"**/tests) lib_path_array=$(ls -d -1 "charms/"**/lib) @@ -14,99 +44,104 @@ then tst_path="${tst_path_array[*]}" lib_path="${lib_path_array[*]}" - isort ${src_path} ${tst_path} - black --config pyproject.toml ${src_path} ${tst_path} + isort ${src_path} ${tst_path} + black --config pyproject.toml ${src_path} ${tst_path} elif [[ $1 == "pep8" ]]; then - src_path_array=$(ls -d -1 "charms/"**/src) - tst_path_array=$(ls -d -1 "charms/"**/tests) - - src_path="${src_path_array[*]}" - tst_path="${tst_path_array[*]}" + src_path_array=$(ls -d -1 "charms/"**/src) + tst_path_array=$(ls -d -1 "charms/"**/tests) - codespell ${src_path} ${tst_path} + src_path="${src_path_array[*]}" + tst_path="${tst_path_array[*]}" + + codespell ${src_path} ${tst_path} pflake8 --config pyproject.toml ${src_path} ${tst_path} - isort --check-only --diff ${src_path} ${tst_path} - black --config pyproject.toml --check --diff ${src_path} ${tst_path} + isort --check-only --diff ${src_path} ${tst_path} + black --config pyproject.toml --check --diff ${src_path} ${tst_path} elif [[ $1 =~ ^(py3|py310|py311)$ ]]; then - # Run py3 on ops-sunbeam - pushd ops-sunbeam + + # Run py3 on ops-sunbeam + if should_test_ops_sunbeam $2; then + pushd ops-sunbeam stestr run --slowest || exit 1 popd + fi + + # Run py3 on sunbeam charms + for charm in $(get_charms_to_test $2); do + push_common_files $charm || exit 1 + pushd charms/$charm + PYTHONPATH=./src:./lib stestr run --slowest || exit 1 + popd + pop_common_files $charm || exit 1 + done - # Run py3 on all sunbeam charms - charms=($(ls charms)) - for charm in ${charms[@]}; do - push_common_files $charm || exit 1 - pushd charms/$charm - PYTHONPATH=./src:./lib stestr run --slowest || exit 1 - popd - pop_common_files $charm || exit 1 - done elif [[ $1 == "cover" ]]; then coverage erase - # Run coverage on ops-sunbeam - pushd ops-sunbeam - coverage erase + # Run coverage on ops-sunbeam + if should_test_ops_sunbeam $2; then + pushd ops-sunbeam + coverage erase PYTHON="coverage run --parallel-mode --omit .tox/*" stestr run --slowest || exit 1 - coverage combine + coverage combine popd + fi - # Run coverage on all sunbeam charms - charms=($(ls charms)) - for charm in ${charms[@]}; do - push_common_files $charm || exit 1 - pushd charms/$charm - coverage erase - PYTHONPATH=./src:./lib:../../ops-sunbeam PYTHON="coverage run --parallel-mode --omit .tox/*,src/templates/*" stestr run --slowest || exit 1 - coverage combine - popd - done + # Run coverage on sunbeam charms + for charm in $(get_charms_to_test $2); do + push_common_files $charm || exit 1 + pushd charms/$charm + coverage erase + PYTHONPATH=./src:./lib:../../ops-sunbeam PYTHON="coverage run --parallel-mode --omit .tox/*,src/templates/*" stestr run --slowest || exit 1 + coverage combine + popd + done - # Prepare coverage report - coverage combine charms/*/.coverage ops-sunbeam/.coverage - coverage html -d cover - coverage xml -o cover/coverage.xml - coverage report + # Prepare coverage report + coverage combine charms/*/.coverage ops-sunbeam/.coverage + coverage html -d cover + coverage xml -o cover/coverage.xml + coverage report + + # Common files should be deleted after coverage combine + for charm in $(get_charms_to_test $2); do + pop_common_files $charm || exit 1 + done - # Common files should be deleted after coverage combine - for charm in ${charms[@]}; do - pop_common_files $charm || exit 1 - done elif [[ $1 == "build" ]]; then - if [[ $# != 2 ]]; - then - echo "Command format: tox -e build " - exit 1 - fi + if [[ $# != 2 ]]; + then + echo "Command format: tox -e build " + exit 1 + fi - charm=$2 - charms=($(ls charms)) - if [[ ! ${charms[@]} =~ $charm ]]; - then - echo "Argument should be one of ${charms[@]}"; - exit 1 - fi + charm=$2 + charms=($(ls charms)) + if [[ ! ${charms[@]} =~ $charm ]]; + then + echo "Argument should be one of ${charms[@]}"; + exit 1 + fi - push_common_files $charm || exit 1 - pushd charms/$charm || exit 1 - charmcraft -v pack || exit 1 - if [[ -e "${charm}.charm" ]]; - then - echo "Removing bad downloaded charm maybe?" - rm "${charm}.charm" - fi - echo "Renaming charm ${charm}_*.charm to ${charm}.charm" + push_common_files $charm || exit 1 + pushd charms/$charm || exit 1 + charmcraft -v pack || exit 1 + if [[ -e "${charm}.charm" ]]; + then + echo "Removing bad downloaded charm maybe?" + rm "${charm}.charm" + fi + echo "Renaming charm ${charm}_*.charm to ${charm}.charm" - mv ${charm}_*.charm ${charm}.charm + mv ${charm}_*.charm ${charm}.charm - popd || exit 1 - pop_common_files $charm || exit 1 + popd || exit 1 + pop_common_files $charm || exit 1 else - echo "tox argument should be one of pep8, py3, py310, py311, cover"; + echo "tox argument should be one of pep8, py3, py310, py311, cover"; exit 1 fi diff --git a/tox.ini b/tox.ini index bfe7be59..03806c9d 100644 --- a/tox.ini +++ b/tox.ini @@ -49,22 +49,22 @@ commands = deps = -r{toxinidir}/test-requirements.txt commands = - {toxinidir}/run_tox.sh py3 + {toxinidir}/run_tox.sh py3 {posargs} [testenv:py310] deps = {[testenv:py3]deps} commands = - {toxinidir}/run_tox.sh py310 + {toxinidir}/run_tox.sh py310 {posargs} [testenv:py311] deps = {[testenv:py3]deps} commands = - {toxinidir}/run_tox.sh py311 + {toxinidir}/run_tox.sh py311 {posargs} [testenv:cover] deps = {[testenv:py3]deps} commands = - {toxinidir}/run_tox.sh cover + {toxinidir}/run_tox.sh cover {posargs} [testenv:build] basepython = python3