pytestCheckHook: support inclusion and exclusion of path globs, test items, keywords, and markers (#386513)
This commit is contained in:
@@ -170,6 +170,14 @@ in
|
||||
"test_print"
|
||||
] ++ previousPythonAttrs.disabledTests or [ ];
|
||||
});
|
||||
disabledTests-expression = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
__structuredAttrs = true;
|
||||
pname = "test-pytestCheckHook-disabledTests-expression-${previousPythonAttrs.pname}";
|
||||
disabledTests = [
|
||||
"TestBasic and test_print"
|
||||
"test_str"
|
||||
] ++ previousPythonAttrs.disabledTests or [ ];
|
||||
});
|
||||
disabledTestPaths = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-disabledTestPaths-${previousPythonAttrs.pname}";
|
||||
disabledTestPaths = [
|
||||
@@ -184,6 +192,12 @@ in
|
||||
] ++ previousPythonAttrs.disabledTestPaths or [ ];
|
||||
})
|
||||
);
|
||||
disabledTestPaths-item = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-disabledTestPaths-item-${previousPythonAttrs.pname}";
|
||||
disabledTestPaths = [
|
||||
"tests/test_basic.py::TestBasic"
|
||||
] ++ previousPythonAttrs.disabledTestPaths or [ ];
|
||||
});
|
||||
disabledTestPaths-glob = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-disabledTestPaths-glob-${previousPythonAttrs.pname}";
|
||||
disabledTestPaths = [
|
||||
@@ -198,6 +212,78 @@ in
|
||||
] ++ previousPythonAttrs.disabledTestPaths or [ ];
|
||||
})
|
||||
);
|
||||
enabledTests = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-enabledTests-${previousPythonAttrs.pname}";
|
||||
enabledTests = [
|
||||
"TestBasic"
|
||||
] ++ previousPythonAttrs.disabledTests or [ ];
|
||||
});
|
||||
enabledTests-expression = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
__structuredAttrs = true;
|
||||
pname = "test-pytestCheckHook-enabledTests-expression-${previousPythonAttrs.pname}";
|
||||
enabledTests = [
|
||||
"TestBasic and test_print"
|
||||
"test_str"
|
||||
] ++ previousPythonAttrs.disabledTests or [ ];
|
||||
});
|
||||
enabledTests-disabledTests = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-enabledTests-disabledTests-${previousPythonAttrs.pname}";
|
||||
enabledTests = [
|
||||
"TestBasic"
|
||||
] ++ previousPythonAttrs.disabledTests or [ ];
|
||||
disabledTests = [
|
||||
"test_print"
|
||||
] ++ previousPythonAttrs.disabledTests or [ ];
|
||||
});
|
||||
enabledTestPaths = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-enabledTestPaths-${previousPythonAttrs.pname}";
|
||||
enabledTestPaths = [
|
||||
"tests/test_basic.py"
|
||||
] ++ previousPythonAttrs.enabledTestPaths or [ ];
|
||||
});
|
||||
enabledTestPaths-nonexistent = testers.testBuildFailure (
|
||||
objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-enabledTestPaths-nonexistent-${previousPythonAttrs.pname}";
|
||||
enabledTestPaths = [
|
||||
"tests/test_foo.py"
|
||||
] ++ previousPythonAttrs.enabledTestPaths or [ ];
|
||||
})
|
||||
);
|
||||
enabledTestPaths-dir = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-enabledTestPaths-dir-${previousPythonAttrs.pname}";
|
||||
enabledTestPaths = [
|
||||
"tests"
|
||||
] ++ previousPythonAttrs.enabledTestPaths or [ ];
|
||||
});
|
||||
enabledTestPaths-dir-disabledTestPaths = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-enabledTestPaths-dir-disabledTestPaths-${previousPythonAttrs.pname}";
|
||||
enabledTestPaths = [
|
||||
"tests"
|
||||
] ++ previousPythonAttrs.enabledTestPaths or [ ];
|
||||
disabledTestPaths = [
|
||||
"tests/test_basic.py"
|
||||
] ++ previousPythonAttrs.disabledTestPaths or [ ];
|
||||
});
|
||||
enabledTestPaths-glob = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-enabledTestPaths-glob-${previousPythonAttrs.pname}";
|
||||
enabledTestPaths = [
|
||||
"tests/test_obj*.py"
|
||||
] ++ previousPythonAttrs.enabledTestPaths or [ ];
|
||||
});
|
||||
enabledTestPaths-glob-nonexistent = testers.testBuildFailure (
|
||||
objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-enabledTestPaths-glob-nonexistent-${previousPythonAttrs.pname}";
|
||||
enabledTestPaths = [
|
||||
"tests/test_foo*.py"
|
||||
] ++ previousPythonAttrs.enabledTestPaths or [ ];
|
||||
})
|
||||
);
|
||||
enabledTestPaths-item = objprint.overridePythonAttrs (previousPythonAttrs: {
|
||||
pname = "test-pytestCheckHook-enabledTestPaths-item-${previousPythonAttrs.pname}";
|
||||
enabledTestPaths = [
|
||||
"tests/test_basic.py::TestBasic"
|
||||
] ++ previousPythonAttrs.enabledTestPaths or [ ];
|
||||
});
|
||||
};
|
||||
};
|
||||
} ./pytest-check-hook.sh
|
||||
|
||||
@@ -3,22 +3,64 @@
|
||||
|
||||
echo "Sourcing pytest-check-hook"
|
||||
|
||||
function _pytestIncludeExcludeExpr() {
|
||||
local includeListName="$1"
|
||||
local -n includeListRef="$includeListName"
|
||||
local excludeListName="$2"
|
||||
local -n excludeListRef="$excludeListName"
|
||||
local includeString excludeString
|
||||
if [[ -n "${includeListRef[*]-}" ]]; then
|
||||
# ((element1) or (element2))
|
||||
includeString="(($(concatStringsSep ") or (" "$includeListName")))"
|
||||
fi
|
||||
if [[ -n "${excludeListRef[*]-}" ]]; then
|
||||
# and not (element1) and not (element2)
|
||||
excludeString="${includeString:+ and }not ($(concatStringsSep ") and not (" "$excludeListName"))"
|
||||
fi
|
||||
echo "$includeString$excludeString"
|
||||
}
|
||||
|
||||
function pytestCheckPhase() {
|
||||
echo "Executing pytestCheckPhase"
|
||||
runHook preCheck
|
||||
|
||||
# Compose arguments
|
||||
local -a flagsArray=(-m pytest)
|
||||
if [ -n "${disabledTests[*]-}" ]; then
|
||||
disabledTestsString="not $(concatStringsSep " and not " disabledTests)"
|
||||
flagsArray+=(-k "$disabledTestsString")
|
||||
fi
|
||||
|
||||
local -a _pathsArray=()
|
||||
local -a _pathsArray
|
||||
local path
|
||||
|
||||
_pathsArray=()
|
||||
concatTo _pathsArray enabledTestPaths
|
||||
for path in "${_pathsArray[@]}"; do
|
||||
if [[ "$path" =~ "::" ]]; then
|
||||
flagsArray+=("$path")
|
||||
else
|
||||
# The `|| kill "$$"` trick propagates the errors from the process substitutiton subshell,
|
||||
# which is suggested by a StackOverflow answer: https://unix.stackexchange.com/a/217643
|
||||
readarray -t -O"${#flagsArray[@]}" flagsArray < <(@pythonCheckInterpreter@ - "$path" <<EOF || kill "$$")
|
||||
import glob
|
||||
import sys
|
||||
path_glob=sys.argv[1]
|
||||
if not len(path_glob):
|
||||
sys.exit('Got an empty enabled tests path glob. Aborting')
|
||||
path_expanded = glob.glob(path_glob)
|
||||
if not len(path_expanded):
|
||||
sys.exit('Enabled tests path glob "{}" does not match any paths. Aborting'.format(path_glob))
|
||||
for path in path_expanded:
|
||||
print(path)
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
|
||||
_pathsArray=()
|
||||
concatTo _pathsArray disabledTestPaths
|
||||
for path in "${_pathsArray[@]}"; do
|
||||
# Check if every path glob matches at least one path
|
||||
@pythonCheckInterpreter@ - "$path" <<EOF
|
||||
if [[ "$path" =~ "::" ]]; then
|
||||
flagsArray+=("--deselect=$path")
|
||||
else
|
||||
# Check if every path glob matches at least one path
|
||||
@pythonCheckInterpreter@ - "$path" <<EOF
|
||||
import glob
|
||||
import sys
|
||||
path_glob=sys.argv[1]
|
||||
@@ -27,9 +69,18 @@ if not len(path_glob):
|
||||
if next(glob.iglob(path_glob), None) is None:
|
||||
sys.exit('Disabled tests path glob "{}" does not match any paths. Aborting'.format(path_glob))
|
||||
EOF
|
||||
flagsArray+=("--ignore-glob=$path")
|
||||
flagsArray+=("--ignore-glob=$path")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -n "${enabledTests[*]-}" ]] || [[ -n "${disabledTests[*]-}" ]]; then
|
||||
flagsArray+=(-k "$(_pytestIncludeExcludeExpr enabledTests disabledTests)")
|
||||
fi
|
||||
|
||||
if [[ -n "${enabledTestMarks[*]-}" ]] || [[ -n "${disabledTestMarks[*]-}" ]]; then
|
||||
flagsArray+=(-m "$(_pytestIncludeExcludeExpr enabledTestMarks disabledTestMarks)")
|
||||
fi
|
||||
|
||||
# Compatibility layer to the obsolete pytestFlagsArray
|
||||
eval "flagsArray+=(${pytestFlagsArray[*]-})"
|
||||
|
||||
|
||||
@@ -106,8 +106,12 @@ let
|
||||
"doInstallCheck"
|
||||
"pyproject"
|
||||
"format"
|
||||
"disabledTestMarks"
|
||||
"disabledTestPaths"
|
||||
"disabledTests"
|
||||
"enabledTestMarks"
|
||||
"enabledTestPaths"
|
||||
"enabledTests"
|
||||
"pytestFlags"
|
||||
"pytestFlagsArray"
|
||||
"unittestFlags"
|
||||
@@ -439,6 +443,7 @@ let
|
||||
}
|
||||
// optionalAttrs (attrs.doCheck or true) (
|
||||
getOptionalAttrs [
|
||||
"disabledTestMarks"
|
||||
"disabledTestPaths"
|
||||
"disabledTests"
|
||||
"pytestFlags"
|
||||
@@ -446,6 +451,21 @@ let
|
||||
"unittestFlags"
|
||||
"unittestFlagsArray"
|
||||
] attrs
|
||||
//
|
||||
lib.mapAttrs
|
||||
(
|
||||
name: value:
|
||||
lib.throwIf (
|
||||
attrs.${name} == [ ]
|
||||
) "${lib.getName finalAttrs}: ${name} must be unspecified, null or a non-empty list." attrs.${name}
|
||||
)
|
||||
(
|
||||
getOptionalAttrs [
|
||||
"enabledTestMarks"
|
||||
"enabledTestPaths"
|
||||
"enabledTests"
|
||||
] attrs
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user