codecraftai-testplus 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccai/testplus/__init__.py +57 -0
- ccai/testplus/cli/__init__.py +13 -0
- ccai/testplus/cli/cmdtree/__init__.py +13 -0
- ccai/testplus/cli/cmdtree/testing/__init__.py +33 -0
- ccai/testplus/cli/cmdtree/testing/constants.py +62 -0
- ccai/testplus/cli/cmdtree/testing/jobs.py +195 -0
- ccai/testplus/cli/cmdtree/testing/query.py +165 -0
- ccai/testplus/cli/cmdtree/testing/run.py +371 -0
- ccai/testplus/cli/testplus_command.py +79 -0
- ccai/testplus/distributedtestjob.py +90 -0
- ccai/testplus/distributedtestsequencer.py +111 -0
- ccai/testplus/entrypoints.py +140 -0
- ccai/testplus/initialize.py +103 -0
- ccai/testplus/py.typed +0 -0
- ccai/testplus/testplusdefaulttypefactory.py +47 -0
- codecraftai_testplus-1.2.0.dist-info/METADATA +100 -0
- codecraftai_testplus-1.2.0.dist-info/RECORD +20 -0
- codecraftai_testplus-1.2.0.dist-info/WHEEL +4 -0
- codecraftai_testplus-1.2.0.dist-info/entry_points.txt +3 -0
- codecraftai_testplus-1.2.0.dist-info/licenses/LICENSE.md +204 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: testplus
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: Top level package for the TestPlus framework which exposes
|
|
5
|
+
commonly used APIs and decorators from the underlying
|
|
6
|
+
``ccai.testbase`` package.
|
|
7
|
+
|
|
8
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__author__ = "Myron Walker"
|
|
12
|
+
__copyright__ = "Copyright 2025, Code Craft AI LLC"
|
|
13
|
+
__credits__ = []
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
from ccai.xmodules.xlogging.enhancedloggers import (
|
|
17
|
+
EnhancedLogger,
|
|
18
|
+
getEnhancedLogger
|
|
19
|
+
)
|
|
20
|
+
logger: EnhancedLogger = getEnhancedLogger()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
from ccai.testbase.declaration import registrations as register
|
|
24
|
+
from ccai.testbase.declaration import originations as originate
|
|
25
|
+
from ccai.testbase.declaration import attachments as attach
|
|
26
|
+
|
|
27
|
+
from ccai.testbase.verification import (
|
|
28
|
+
assert_dict_response_has_keys,
|
|
29
|
+
assert_dict_response_has_paths,
|
|
30
|
+
assert_equal,
|
|
31
|
+
assert_expression,
|
|
32
|
+
assert_greater,
|
|
33
|
+
assert_lessthan,
|
|
34
|
+
assert_list_length,
|
|
35
|
+
assert_list_length_greater,
|
|
36
|
+
assert_not_equal,
|
|
37
|
+
assert_type
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
from ccai.testbase.markers import (
|
|
41
|
+
mark_categories,
|
|
42
|
+
mark_keywords,
|
|
43
|
+
mark_priority,
|
|
44
|
+
mark_descendent_categories,
|
|
45
|
+
mark_descendent_keywords,
|
|
46
|
+
mark_descendent_priority
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
from ccai.testbase.results.model.taskingresult import (
|
|
50
|
+
verify_tasking_results
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
from ccai.testbase.constraints import (
|
|
54
|
+
Constraints,
|
|
55
|
+
ConstraintsCatalog,
|
|
56
|
+
FeatureConstraints
|
|
57
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: cli
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: Package containing the command line interface implementation for
|
|
5
|
+
the ``testplus`` command.
|
|
6
|
+
|
|
7
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__author__ = "Myron Walker"
|
|
11
|
+
__copyright__ = "Copyright 2025, Code Craft AI LLC"
|
|
12
|
+
__credits__ = []
|
|
13
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: cmdtree
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: Package defining the command tree structure for the ``testplus``
|
|
5
|
+
CLI.
|
|
6
|
+
|
|
7
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__author__ = "Myron Walker"
|
|
11
|
+
__copyright__ = "Copyright 2025, Code Craft AI LLC"
|
|
12
|
+
__credits__ = []
|
|
13
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: testing
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: CLI group providing commands for interacting with tests and test
|
|
5
|
+
results.
|
|
6
|
+
|
|
7
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__author__ = "Myron Walker"
|
|
11
|
+
__copyright__ = "Copyright 2025, Code Craft AI LLC"
|
|
12
|
+
__credits__ = []
|
|
13
|
+
__version__ = "1.0.0"
|
|
14
|
+
|
|
15
|
+
import click
|
|
16
|
+
|
|
17
|
+
from ccai.testplus.cli.cmdtree.testing.jobs import group_testplus_testing_jobs
|
|
18
|
+
from ccai.testplus.cli.cmdtree.testing.query import command_testplus_testing_query
|
|
19
|
+
from ccai.testplus.cli.cmdtree.testing.run import command_testplus_testing_run
|
|
20
|
+
|
|
21
|
+
@click.group("testing", help="Contains command for working with tests and test results.")
|
|
22
|
+
def group_testplus_testing():
|
|
23
|
+
"""
|
|
24
|
+
Root command group for TestPlus testing related operations.
|
|
25
|
+
|
|
26
|
+
:returns: ``None``
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
group_testplus_testing.add_command(group_testplus_testing_jobs)
|
|
32
|
+
group_testplus_testing.add_command(command_testplus_testing_query)
|
|
33
|
+
group_testplus_testing.add_command(command_testplus_testing_run)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: constants
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: Constants used by the TestPlus testing command tree.
|
|
5
|
+
|
|
6
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__author__ = "Myron Walker"
|
|
10
|
+
__copyright__ = "Copyright 2025, Code Craft AI LLC"
|
|
11
|
+
__credits__ = []
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
from ccai.configuration.normalize import SEPARATOR
|
|
15
|
+
|
|
16
|
+
CONFIGURATION_CHOICES = [
|
|
17
|
+
"all",
|
|
18
|
+
"credentials",
|
|
19
|
+
"landscape",
|
|
20
|
+
"topology",
|
|
21
|
+
"runtime"
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
HELP_ROOT = "The root directory to use when scanning for tests."
|
|
25
|
+
HELP_INCLUDES = "Add a test inclusion expression."
|
|
26
|
+
HELP_EXCLUDES = "Add a test exclusion expression."
|
|
27
|
+
HELP_OUTPUT = "The output directory where results and artifacts are collected."
|
|
28
|
+
HELP_START = r"A time stamp to associate with the start of the run. Example: 2020-10-17T15:30:11.989120 Bash: date +%Y-%m-%dT%H:%M:%S.%N"
|
|
29
|
+
HELP_BRANCH = "The name of the branch to associate with the test run results."
|
|
30
|
+
HELP_BUILD = "The name of the build to associate with the test run results."
|
|
31
|
+
HELP_FLAVOR = "The name of the flavor to associate with the test run results."
|
|
32
|
+
HELP_JOB_ID = "A unique identifier for the job with respect to the job runner."
|
|
33
|
+
HELP_JOB_INITIATOR = "The name of the initiator of the job."
|
|
34
|
+
HELP_JOB_LABEL = "The label associated with the job."
|
|
35
|
+
HELP_JOB_NAME = "The name of the job."
|
|
36
|
+
HELP_JOB_OWNER = "The ownerid and possibly appended ';(display name)' of the test run result owner."
|
|
37
|
+
HELP_DEFAULT_CONFIGS = "Indicates that one or more default configurations should be used."
|
|
38
|
+
HELP_CONFIG_NAME = "A configuration common base name to use for both the 'landscape' and 'topology' configurations."
|
|
39
|
+
HELP_CREDENTIAL = "The full path or URI of the credentials file to use for the testrun."
|
|
40
|
+
HELP_CREDENTIAL_NAMES = "The base name of the credential files to search for in the credential path."
|
|
41
|
+
HELP_CREDENTIAL_SOURCES = f"A '{SEPARATOR}' seperated list of source uris to search for credential documents."
|
|
42
|
+
HELP_LANDSCAPE = "The full path of the landscape file to use for the testrun."
|
|
43
|
+
HELP_LANDSCAPE_NAMES = "The base name of the landscape files to search for in the landscape path."
|
|
44
|
+
HELP_LANDSCAPE_SOURCES = f"A '{SEPARATOR}' seperated list of source uris to search for landscape documents."
|
|
45
|
+
HELP_RUNTIME = "The full path of the runtime file to use for the testrun."
|
|
46
|
+
HELP_RUNTIME_NAMES = "The base name of the runtime files to search for in the runtime path."
|
|
47
|
+
HELP_RUNTIME_SOURCES = f"A '{SEPARATOR}' seperated list of source uris to search for runtime documents."
|
|
48
|
+
HELP_TOPOLOGY = "The full path of the topology file to use for the testrun."
|
|
49
|
+
HELP_TOPOLOGY_NAMES = "The base name of the topology files to search for in the topology path."
|
|
50
|
+
HELP_TOPOLOGY_SOURCES = f"A '{SEPARATOR}' seperated list of source uris to search for topology documents."
|
|
51
|
+
HELP_RUNID = "A uuid to use for the run id for the testrun."
|
|
52
|
+
HELP_CONSOLE_LOG_LEVEL = "The logging level for console output."
|
|
53
|
+
HELP_FILE_LOG_LEVEL = "The logging level for logfile output."
|
|
54
|
+
HELP_DEBUG = "Output debug information to the console."
|
|
55
|
+
HELP_DEBUGGER = "Debugger to active during the test run."
|
|
56
|
+
HELP_BREAKPOINT = "The breakpoint to activate for the test run."
|
|
57
|
+
HELP_TIMETRAVEL = "Enables tracing for Time-Travel-Debugging."
|
|
58
|
+
HELP_TIMEPORTAL = "The name of a time portal to open for Time-Travel-Debugging."
|
|
59
|
+
HELP_PRERUN_DIAGNOSTIC = "Flag indicating that a pre run diagnostic should be performed."
|
|
60
|
+
HELP_POSTRUN_DIAGNOSTIC = "Flag indicating that a post run diagnostic should be performed."
|
|
61
|
+
HELP_INCLUDE_MARKER_EXP = "Allows the specification of a marker expression that if matched will include a test."
|
|
62
|
+
HELP_EXCLUDE_MARKER_EXP = "Allows the specification of a marker expression that if matched will exclude a test."
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: jobs
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: CLI commands for listing, showing and running TestPlus jobs.
|
|
5
|
+
|
|
6
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__author__ = "Myron Walker"
|
|
10
|
+
__copyright__ = "Copyright 2025, Code Craft AI LLC"
|
|
11
|
+
__credits__ = []
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
|
|
16
|
+
import click
|
|
17
|
+
|
|
18
|
+
from ccai.xmodules.xlogging.levels import LOG_LEVEL_NAMES
|
|
19
|
+
from ccai.xmodules.xlogging.enhancedloggers import getEnhancedLogger
|
|
20
|
+
|
|
21
|
+
@click.group("jobs", help="Contains commands for working with test jobs.")
|
|
22
|
+
def group_testplus_testing_jobs():
|
|
23
|
+
"""
|
|
24
|
+
CLI command group for interacting with TestPlus jobs.
|
|
25
|
+
|
|
26
|
+
:returns: ``None``
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
HELP_ROOT = "The root directory to use when scanning for tests."
|
|
32
|
+
HELP_JOB = "The identifier of the job to run."
|
|
33
|
+
HELP_FILTER = "Add a job filter expression."
|
|
34
|
+
HELP_OUTPUT = "The output directory where results and artifacts are collected."
|
|
35
|
+
HELP_START = r"A time stamp to associate with the start of the run. Example: 2020-10-17T15:30:11.989120 Bash: date +%Y-%m-%dT%H:%M:%S.%N"
|
|
36
|
+
HELP_BRANCH = "The name of the branch to associate with the test run results."
|
|
37
|
+
HELP_BUILD = "The name of the build to associate with the test run results."
|
|
38
|
+
HELP_FLAVOR = "The name of the flavor to associate with the test run results."
|
|
39
|
+
HELP_CONSOLE_LOG_LEVEL = "The logging level for console output."
|
|
40
|
+
HELP_FILE_LOG_LEVEL = "The logging level for logfile output."
|
|
41
|
+
HELP_DEBUG = "Output debug information to the console."
|
|
42
|
+
|
|
43
|
+
@click.command("list")
|
|
44
|
+
@click.option("--root", default=".", type=str, help=HELP_ROOT)
|
|
45
|
+
@click.option("--filter", "-f", required=False, help=HELP_FILTER)
|
|
46
|
+
@click.option("--debug", default=False, type=bool, help=HELP_DEBUG)
|
|
47
|
+
def command_testing_jobs_list(root, filter, debug):
|
|
48
|
+
"""
|
|
49
|
+
Lists available TestPlus jobs.
|
|
50
|
+
|
|
51
|
+
:param root: Root directory used when scanning for jobs.
|
|
52
|
+
:param filter: Optional job filter expression.
|
|
53
|
+
:param debug: Whether to emit debug output.
|
|
54
|
+
|
|
55
|
+
:returns: ``None``
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
click.echo("The 'jobs list' command is not yet implemented.", err=True)
|
|
59
|
+
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
@click.command("show")
|
|
63
|
+
@click.option("--root", default=".", type=str, help=HELP_ROOT)
|
|
64
|
+
@click.option("--job", "-j", required=True, help=HELP_JOB)
|
|
65
|
+
@click.option("--debug", default=False, type=bool, help=HELP_DEBUG)
|
|
66
|
+
def command_testplus_testing_jobs_show(root, job, debug):
|
|
67
|
+
"""
|
|
68
|
+
Displays information about a specific TestPlus job.
|
|
69
|
+
|
|
70
|
+
:param root: Root directory used when scanning for jobs.
|
|
71
|
+
:param job: The identifier of the job to show.
|
|
72
|
+
:param debug: Whether to emit debug output.
|
|
73
|
+
|
|
74
|
+
:returns: ``None``
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
click.echo("The 'jobs show' command is not yet implemented.", err=True)
|
|
78
|
+
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
@click.command("run")
|
|
82
|
+
@click.option("--root", default=".", type=str, help=HELP_ROOT)
|
|
83
|
+
@click.option("--job", "-j", required=True, help=HELP_JOB)
|
|
84
|
+
@click.option("--output", "-o", required=False, help=HELP_OUTPUT)
|
|
85
|
+
@click.option("--start", default=None, required=False, help=HELP_START)
|
|
86
|
+
@click.option("--branch", default=None, required=False, help=HELP_BRANCH)
|
|
87
|
+
@click.option("--build", default=None, required=False, help=HELP_BUILD)
|
|
88
|
+
@click.option("--flavor", default=None, required=False, help=HELP_FLAVOR)
|
|
89
|
+
@click.option("--console-level", default=None, required=False, type=click.Choice(LOG_LEVEL_NAMES, case_sensitive=False), help=HELP_CONSOLE_LOG_LEVEL)
|
|
90
|
+
@click.option("--logfile-level", default=None, required=False, type=click.Choice(LOG_LEVEL_NAMES, case_sensitive=False), help=HELP_FILE_LOG_LEVEL)
|
|
91
|
+
def command_testplus_testing_jobs_run(root, job, output, start, branch, build, flavor, console_level, logfile_level):
|
|
92
|
+
"""
|
|
93
|
+
Executes a specified TestPlus job.
|
|
94
|
+
|
|
95
|
+
:param root: Root directory used when scanning for tests.
|
|
96
|
+
:param job: Fully qualified job identifier.
|
|
97
|
+
:param output: Directory for test results.
|
|
98
|
+
|
|
99
|
+
:returns: ``None``
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
# pylint: disable=unused-import,import-outside-toplevel
|
|
103
|
+
|
|
104
|
+
# We do the imports of the automation framework code inside the action functions because
|
|
105
|
+
# we don't want to startup loggin and the processing of inputs and environment variables
|
|
106
|
+
# until we have entered an action method. Thats way we know how to setup the environment.
|
|
107
|
+
|
|
108
|
+
# IMPORTANT: We need to load the context first because it will trigger the loading
|
|
109
|
+
# of the default user configuration
|
|
110
|
+
|
|
111
|
+
from ccai.xmodules.ximport import import_by_name
|
|
112
|
+
from ccai.xmodules.xpython import prepend_python_path
|
|
113
|
+
|
|
114
|
+
# STEP 1 - Initialize the Runtime (Performed by the root command)
|
|
115
|
+
|
|
116
|
+
# STEP 2 - Resolve the configuration variables (Performed by the root command)
|
|
117
|
+
|
|
118
|
+
# STEP 3 - Apply any 'Configuration' related option overrides
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# STEP 4 - Resolve the Configuration Maps
|
|
123
|
+
#from ccai.configuration.configurationmaps import resolve_configuration_maps
|
|
124
|
+
#resolve_configuration_maps(use_credentials=use_credentials, use_landscape=use_landscape,
|
|
125
|
+
# use_runtime=use_runtime, use_topology=use_topology)
|
|
126
|
+
|
|
127
|
+
# STEP 5 - The application of the remaining options must happen after we have resolved configuration
|
|
128
|
+
# maps because some of those settings will get overridden by the options. So the runtime
|
|
129
|
+
# needs to be loaded and set first before we apply runtime options
|
|
130
|
+
|
|
131
|
+
# STEP 6 - Initialize the Results Output
|
|
132
|
+
|
|
133
|
+
# STEP 7 - Create and kick off the job
|
|
134
|
+
from ccai.thisapp.activation import activate_profile_job, JobType
|
|
135
|
+
activate_profile_job(JobType.TestRun)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
test_root = os.path.abspath(os.path.expandvars(os.path.expanduser(root)))
|
|
139
|
+
if not os.path.isdir(test_root):
|
|
140
|
+
errmsg = "The specified root folder does not exist. root=%s" % root
|
|
141
|
+
if test_root != root:
|
|
142
|
+
errmsg += " expanded=%s" % test_root
|
|
143
|
+
raise click.BadParameter(errmsg, param_hint="--root")
|
|
144
|
+
|
|
145
|
+
# Make sure we extend PATH to include the test root
|
|
146
|
+
prepend_python_path(test_root)
|
|
147
|
+
|
|
148
|
+
# Activation of the runtime happens when we initialize test results
|
|
149
|
+
from ccai.testplus.initialize import initialize_testplus_results
|
|
150
|
+
initialize_testplus_results()
|
|
151
|
+
|
|
152
|
+
logger = getEnhancedLogger()
|
|
153
|
+
|
|
154
|
+
tpmod = sys.modules["ccai.testplus"]
|
|
155
|
+
tpmod.logger = logger
|
|
156
|
+
|
|
157
|
+
from ccai.thisapp.wellknown import ConfiguredSuperFactorySingleton
|
|
158
|
+
from ccai.testbase.factoryprotocols import TestBaseFactoryProtocol
|
|
159
|
+
|
|
160
|
+
# At this point in the code, we either lookup an existing test job or we create a test job
|
|
161
|
+
# from the includes, excludes or test_module
|
|
162
|
+
sfactory = ConfiguredSuperFactorySingleton()
|
|
163
|
+
TestJobType = sfactory.get_override_types_by_order(TestBaseFactoryProtocol.get_testbase_default_job_type)
|
|
164
|
+
|
|
165
|
+
if job is not None:
|
|
166
|
+
job_parts = job.split("@")
|
|
167
|
+
if len(job_parts) != 2:
|
|
168
|
+
errmsg = "A --job parameter must be of the form 'package.module@JobClass'"
|
|
169
|
+
raise click.UsageError(errmsg)
|
|
170
|
+
|
|
171
|
+
job_package, job_class = job_parts
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
job_mod = import_by_name(job_package)
|
|
175
|
+
except ImportError as imperr:
|
|
176
|
+
errmsg = "Failure while importing job package %r" % job_package
|
|
177
|
+
raise click.BadParameter(errmsg, param_hint="--job") from imperr
|
|
178
|
+
|
|
179
|
+
if not hasattr(job_mod, job_class):
|
|
180
|
+
errmsg = "The job package %r does not have a job type %r." % (job_package, job_class)
|
|
181
|
+
raise click.BadParameter(errmsg, param_hint="--job")
|
|
182
|
+
|
|
183
|
+
TestJobType = getattr(job_mod, job_class)
|
|
184
|
+
|
|
185
|
+
result_code = 0
|
|
186
|
+
with TestJobType(logger, test_root) as tjob:
|
|
187
|
+
result_code = tjob.execute()
|
|
188
|
+
|
|
189
|
+
sys.exit(result_code)
|
|
190
|
+
|
|
191
|
+
return
|
|
192
|
+
|
|
193
|
+
group_testplus_testing_jobs.add_command(command_testing_jobs_list)
|
|
194
|
+
group_testplus_testing_jobs.add_command(command_testplus_testing_jobs_show)
|
|
195
|
+
group_testplus_testing_jobs.add_command(command_testplus_testing_jobs_run)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: query
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: CLI command used to query tests available in a TestPlus
|
|
5
|
+
environment.
|
|
6
|
+
|
|
7
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__author__ = "Myron Walker"
|
|
11
|
+
__copyright__ = "Copyright 2025, Code Craft AI LLC"
|
|
12
|
+
__credits__ = []
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
from typing import List
|
|
16
|
+
|
|
17
|
+
from ccai.xmodules.xlogging.enhancedloggers import getEnhancedLogger
|
|
18
|
+
import os
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
import click
|
|
22
|
+
|
|
23
|
+
from ccai.testplus.cli.cmdtree.testing.constants import (
|
|
24
|
+
HELP_ROOT,
|
|
25
|
+
HELP_EXCLUDES,
|
|
26
|
+
HELP_INCLUDES,
|
|
27
|
+
HELP_EXCLUDE_MARKER_EXP,
|
|
28
|
+
HELP_INCLUDE_MARKER_EXP
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
@click.command("query", help="Command used to query information about tests.")
|
|
32
|
+
@click.option("--root", default=None, type=str, help=HELP_ROOT)
|
|
33
|
+
@click.option("--excludes", "-x", multiple=True, help=HELP_EXCLUDES)
|
|
34
|
+
@click.option("--includes", "-i", multiple=True, help=HELP_INCLUDES)
|
|
35
|
+
@click.option("--include-marker-exp", required=False, multiple=True, help=HELP_INCLUDE_MARKER_EXP)
|
|
36
|
+
@click.option("--exclude-marker-exp", required=False, multiple=True, help=HELP_EXCLUDE_MARKER_EXP)
|
|
37
|
+
def command_testplus_testing_query(root, includes, excludes,
|
|
38
|
+
include_marker_exp, exclude_marker_exp):
|
|
39
|
+
"""
|
|
40
|
+
Queries tests available within a TestPlus environment.
|
|
41
|
+
|
|
42
|
+
:param root: Root directory used when scanning for tests.
|
|
43
|
+
:param includes: Inclusion expressions for tests.
|
|
44
|
+
:param excludes: Exclusion expressions for tests.
|
|
45
|
+
|
|
46
|
+
:returns: ``None``
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# pylint: disable=unused-import,import-outside-toplevel
|
|
50
|
+
|
|
51
|
+
# We do the imports of the automation framework code inside the action functions because
|
|
52
|
+
# we don't want to startup loggin and the processing of inputs and environment variables
|
|
53
|
+
# until we have entered an action method. Thats way we know how to setup the environment.
|
|
54
|
+
|
|
55
|
+
# IMPORTANT: We need to load the context first because it will trigger the loading
|
|
56
|
+
# of the default user configuration
|
|
57
|
+
|
|
58
|
+
from ccai.thisapp.contextpaths import ContextPaths
|
|
59
|
+
from ccai.thisapp.wellknown import ThisApplicationSingleton
|
|
60
|
+
|
|
61
|
+
from ccai.xmodules.xpython import prepend_python_path
|
|
62
|
+
|
|
63
|
+
from ccai.thisapp.runtimevariables import RuntimeVariables
|
|
64
|
+
|
|
65
|
+
# STEP 2 - Resolve the configuration variables (performed by the root command)
|
|
66
|
+
|
|
67
|
+
# STEP 3 - Apply the configuration related options
|
|
68
|
+
|
|
69
|
+
# Instantiate the application singleton so the application context and the default user
|
|
70
|
+
# configuration are loaded before the configuration maps are resolved.
|
|
71
|
+
ThisApplicationSingleton()
|
|
72
|
+
|
|
73
|
+
# STEP 4 - Resolve the Configuration Maps
|
|
74
|
+
from ccai.configuration.configurationmaps import resolve_configuration_maps
|
|
75
|
+
resolve_configuration_maps(use_credentials=False, use_landscape=False,
|
|
76
|
+
use_runtime=False, use_topology=False)
|
|
77
|
+
|
|
78
|
+
# STEP 5 - Apply any Option Overrides
|
|
79
|
+
|
|
80
|
+
from ccai.runtime.optionoverrides import AM_RUNTIME_OPTION_OVERRIDES
|
|
81
|
+
|
|
82
|
+
from ccai.testbase.markers import MetaFilter, parse_marker_expression
|
|
83
|
+
|
|
84
|
+
# Setup the Test Root
|
|
85
|
+
if root is None:
|
|
86
|
+
if RuntimeVariables.AM_TESTROOT is not None:
|
|
87
|
+
root = RuntimeVariables.AM_TESTROOT
|
|
88
|
+
else:
|
|
89
|
+
root = "."
|
|
90
|
+
|
|
91
|
+
test_root = os.path.abspath(os.path.expandvars(os.path.expanduser(root)))
|
|
92
|
+
if not os.path.isdir(test_root):
|
|
93
|
+
errmsg = "The specified root folder does not exist. root=%s" % root
|
|
94
|
+
if test_root != root:
|
|
95
|
+
errmsg += " expanded=%s" % test_root
|
|
96
|
+
raise click.BadParameter(errmsg)
|
|
97
|
+
|
|
98
|
+
AM_RUNTIME_OPTION_OVERRIDES.override_testroot(root)
|
|
99
|
+
|
|
100
|
+
# Make sure we extend PATH to include the test roots parent folder so imports will
|
|
101
|
+
# work properly.
|
|
102
|
+
test_root_parent = os.path.dirname(test_root)
|
|
103
|
+
prepend_python_path(test_root_parent)
|
|
104
|
+
|
|
105
|
+
metafilters: List[MetaFilter] = []
|
|
106
|
+
for imexp in include_marker_exp:
|
|
107
|
+
imexp = imexp.strip("\"")
|
|
108
|
+
imexp = imexp.strip("'")
|
|
109
|
+
mfilter = parse_marker_expression("+" + imexp)
|
|
110
|
+
metafilters.append(mfilter)
|
|
111
|
+
|
|
112
|
+
for exmexp in exclude_marker_exp:
|
|
113
|
+
exmexp = exmexp.strip("\"")
|
|
114
|
+
exmexp = exmexp.strip("'")
|
|
115
|
+
mfilter = parse_marker_expression("-" + exmexp)
|
|
116
|
+
metafilters.append(mfilter)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# STEP 6 - Initialize the Results Output
|
|
120
|
+
|
|
121
|
+
# Initialize testplus results and logging
|
|
122
|
+
from ccai.testplus.initialize import initialize_testplus_results
|
|
123
|
+
|
|
124
|
+
initialize_testplus_results()
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# STEP 7 - Kick off the query
|
|
128
|
+
|
|
129
|
+
logger = getEnhancedLogger()
|
|
130
|
+
|
|
131
|
+
from ccai.thisapp.wellknown import ConfiguredSuperFactorySingleton
|
|
132
|
+
from ccai.testbase.factoryprotocols import TestBaseFactoryProtocol
|
|
133
|
+
|
|
134
|
+
sfactory = ConfiguredSuperFactorySingleton()
|
|
135
|
+
TestJobType = sfactory.get_override_types_by_order(TestBaseFactoryProtocol.get_testbase_default_job_type)
|
|
136
|
+
|
|
137
|
+
# At this point in the code, we either lookup an existing test job or we create a test job
|
|
138
|
+
# from the includes, excludes or test_module
|
|
139
|
+
with TestJobType(logger, test_root, includes=includes, excludes=excludes, metafilters=metafilters) as tjob:
|
|
140
|
+
query_results = tjob.query()
|
|
141
|
+
|
|
142
|
+
test_names = [tn for tn in query_results.keys()]
|
|
143
|
+
test_names.sort()
|
|
144
|
+
print()
|
|
145
|
+
print("Tests:")
|
|
146
|
+
for tname in test_names:
|
|
147
|
+
tref = query_results[tname]
|
|
148
|
+
print(" " + tname)
|
|
149
|
+
|
|
150
|
+
param_names = [pn for pn in tref.subscriptions.keys()]
|
|
151
|
+
param_names.sort()
|
|
152
|
+
for pname in param_names:
|
|
153
|
+
pinfo = tref.subscriptions[pname]
|
|
154
|
+
print (" {}: {}".format(pname, pinfo.describe_source()))
|
|
155
|
+
|
|
156
|
+
print()
|
|
157
|
+
|
|
158
|
+
if len(tjob.import_errors) > 0:
|
|
159
|
+
print("IMPORT ERRORS:", file=sys.stderr)
|
|
160
|
+
for ifilename in tjob.import_errors:
|
|
161
|
+
imperr_msg = ifilename
|
|
162
|
+
print(" " + imperr_msg, file=sys.stderr)
|
|
163
|
+
print("", file=sys.stderr)
|
|
164
|
+
|
|
165
|
+
return
|