Classes
Class Structure
Here’s the overview of the essential classes used in the tmt project. It should help you to get quickly started and better understand the relation between the individual classes.
Basic
The Common
class is the parent of most of the available
classes, it provides common methods for logging, running commands
and workdir handling. The _CommonBase
class is an actual root
of the class tree, makes sure the inheritance works correctly.
The Core
class together with its child classes Test
,
Plan
and Story
cover the Metadata Specification:
_CommonBase
└── Common
├── Core
│ ├── Plan
│ ├── Story
│ └── Test
├── Clean
├── Guest
├── Phase
├── Run
├── Status
├── Step
└── Tree
Phases
Actions performed during a normal step and plugins for individual step:
Phase
├── Action
│ ├── Login
│ └── Reboot
└── BasePlugin
├── GuestlessPlugin
│ ├── DiscoverPlugin
│ │ ├── DiscoverFmf
│ │ └── DiscoverShell
│ ├── ProvisionPlugin
│ │ ├── ProvisionArtemis
│ │ ├── ProvisionConnect
│ │ ├── ProvisionLocal
│ │ ├── ProvisionPodman
│ │ └── ProvisionTestcloud
│ └── ReportPlugin
│ ├── ReportDisplay
│ ├── ReportHtml
│ ├── ReportJUnit
│ ├── ReportPolarion
│ └── ReportReportPortal
└── Plugin
├── ExecutePlugin
│ └── ExecuteInternal
│ └── ExecuteUpgrade
├── FinishPlugin
│ ├── FinishAnsible
│ └── FinishShell
└── PreparePlugin
├── PrepareAnsible
│ └── FinishAnsible
├── PrepareInstall
└── PrepareShell
Steps
A brief overview of all test steps:
Step
├── Discover
├── Provision
├── Prepare
├── Execute
├── Finish
└── Report
Containers used for storing configuration data for individual step plugins:
DataContainer
└── SpecBasedContainer, SerializableContainer
├── FmfId
│ └── DependencyFmfId
├── Link
├── Links
└── StepData
├── DiscoverStepData
│ ├── DiscoverFmfStepData
│ └── DiscoverShellData
├── ExecuteStepData
│ ├── ExecuteInternalData
│ └── ExecuteUpgradeData
├── FinishStepData
│ └── FinishShellData
├── PrepareStepData
│ ├── PrepareAnsibleData
│ ├── PrepareInstallData
│ └── PrepareShellData
├── ProvisionStepData
│ ├── ProvisionArtemisData
│ ├── ProvisionConnectData
│ ├── ProvisionLocalData
│ ├── ProvisionPodmanData
│ └── ProvisionTestcloudData
└── ReportStepData
├── ReportHtmlData
├── ReportJUnitData
├── ReportPolarionData
└── ReportReportPortalData
Guests
Guests provisioned for test execution:
Guest
├── GuestContainer
├── GuestLocal
└── GuestSsh
├── GuestArtemis
└── GuestTestcloud
Data related to provisioned guests:
GuestData
├── GuestSshData
│ ├── ArtemisGuestData
│ ├── ConnectGuestData
│ └── TestcloudGuestData
└── PodmanGuestData
Attributes
Hierarchy
Object hierarchy is following: Run
-> Plans
-> Steps
-> Plugins
, where the Run
is on the top of this hierarchy.
The objects have the parent
attribute, that is pointing to
the parent in which the current instance is contained.
Nodes, Trees
The node
attribute of Test
, Plan
and Story
instances references the original leaf node of the fmf metadata
tree from which the respective test, plan or story have been
created.
In a similar way, the tree
property of the Tree
instance
points to the original fmf.Tree
from which it was initialized.
Keys, Fields, Options
Configuration options appear throughout the code in several forms, here’s a summary of the differences and naming:
- key
a config input coming from the
fmf
files, consistently using dashes, example:some-thing
- field
defined by the
tmt.utils.field()
helper, is a python attribute, using underscores, example:some_thing
- option
coming from the command line, defined using the
tmt.options.option()
helper, includes the--
prefix, example:--some-thing
Class Conversions
Various internal objects and classes often need to be converted from their Python nature to data that can be saved, loaded or exported in different form. To facilitate these conversions, three families of helper methods are provided, each with its own set of use cases.
to_spec
/to_minimal_spec
/from_spec
This family of methods works with tmt specification, i.e. raw
user-provided data coming from fmf files describing plans, tests,
stories, or from command-line options. from_spec()
shall be
called to spawn objects representing the user input, while
to_spec()
should produce output one could find in fmf files.
The default implementation comes from tmt.utils.SpecBasedContainer
class, all classes based on user input data should include this
class among their bases.
to_minimal_spec
performs the identical operation as to_spec
,
but its result should not include keys that are optional and not set,
while to_spec
should always include all keys, even when set to
default values or not set at all.
# Create an fmf id object from raw data
fmf_id = tmt.base.FmfId.from_spec({'url': ..., 'ref': ...})
to_serialized
/from_serialized
/unserialize
This family of methods is aiming at runtime objects that may be saved into and loaded from tmt working files, i.e. files tmt uses to store a state in its workdir, like step.yaml or guests.yaml.
Third member of this family, unserialize
, is similar to
from_serialized
- both create an object from its serialized form,
only unserialize
is capable of detecting the class to instantiate
while for using from_serialized
, one must already know which
class to work with. unserialize
then uses from_serialized
under the hood to do the heavy lifting when correct class is
identified.
The default implementation comes from tmt.utils.SerializableContainer
class, all classes that are being saved and loaded during tmt run
should include this class among their bases.
See https://en.wikipedia.org/wiki/Serialization for more details on the concept of serialization.
# tmt.steps.discover.shell.DiscoverShellData wishes to unserialize its
# `tests` a list of `TestDescription` objects rather than a list of
# dictionaries (the default implementation).
@classmethod
def from_serialized(cls, serialized: Dict[str, Any]) -> 'DiscoverShellData':
obj = super().from_serialized(serialized)
obj.tests = [TestDescription.from_serialized(
serialized_test) for serialized_test in serialized['tests']]
return obj
# A step saving its state...
content: Dict[str, Any] = {
'status': self.status(),
'data': [datum.to_serialized() for datum in self.data]
}
self.write('step.yaml', tmt.utils.dict_to_yaml(content))
# ... and loading it back.
# Note the use of unserialize(): step data may have been serialized from
# various different classes (derived from tmt.steps.provision.Guest),
# and unserialize() will detect the correct class.
raw_step_data: Dict[Any, Any] = tmt.utils.yaml_to_dict(self.read('step.yaml'))
self.data = [
StepData.unserialize(raw_datum) for raw_datum in raw_step_data['data']
]
to_dict
/to_minimal_dict
Very special helper methods: its use cases are not related to any
input or output data, and most of the time, when in need of
iterating over object’s keys and/or values, one can use keys()
,
values()
or items()
methods. They are used as sources of data
for serialization and validation, but they usually have no use outside
of default implementations.
Warning
If you think of using to_dict()
, please, think again and be sure
you know what are you doing. Despite its output being sometimes
perfectly compatible with output of to_serialized()
or to_spec()
,
it is not generaly true, and using it instead of proper methods may lead
to unexpected exceptions.
The same applies to to_minimal_dict()
.
# tmt.base.FmfId's specification is basically just a mapping,
# therefore `to_dict()` is good enough to produce a specification.
def to_spec(self) -> Dict[str, Any]:
return self.to_dict()
Commands vs. shell scripts
tmt internals makes distinction between a command and a shell script. This is
important to enforce proper handling of shell scripts specified by users -
prepare
and finish
scripts, test commands, etc.
There are two basic types for describing commands:
tmt.utils.Command
- a list of “command elements” representing an executable followed by its arguments. Common throughout tmt’s code, never used withshell=True
. This is the only form accepted bytmt.utils.Common.run()
method.tmt.utils.ShellScript
- a free-form string containing a shell script, from a single built-in command to multiline complex scripts. Traditionally, this kind of “commands” is accompanied byshell=True
, tmt code convertsShellScript
values intoCommand
elements, e.g. with the help of theShellScript.to_element()
method.
Following rules apply:
tmt code shall stick to
Command
andShellScript
types when passing commands between functions and classes. There should be no need for custom types likeList[str]
orstr
, the preferred types are equipped with necessary conversion helpers.in most cases, tmt is given scripts by users, not executable commands with options. Plugin writers should avoid using bare
str
orCommand
types when annotating this kind of input. For example:class FooStepData(tmt.steps.StepData): # `--script ...` option dictates step data to have a field of correct type script: List[tmt.utils.ShellScript] ... def go(self): ... # When calling `get()`, hint type linters with the right type scripts: List[tmt.utils.ShellScript] = self.get('script')
shell=True
should not be needed, useShellScript.to_shell_command()
instead.
Both ShellScript
and Command
support addition, therefore it’s possible
to build up commands and scripts from smaller building blocks:
>>> command = Command('ls')
>>> command += Command('-al')
>>> command += ['/']
>>> str(command)
'ls -al /'
>>> script = ShellScript('ls -al')
>>> script += ShellScript('ls -al $HOME')
>>> str(script)
'ls -al; ls -al $HOME'
There are several functions available to help with conversion between command and shell script format:
Command.to_element
Convert a command - or possibly just command options - to a command element. Useful when you got a list of command options that another command is expecting as its options:
>>> ssh_command = Command('ssh', '-o', 'ForwardX11=yes', '-o', 'IdentitiesOnly=yes')
>>> command = Command('rsync', '-e', ssh_command.to_element())
>>> str(command)
"rsync -e 'ssh -o ForwardX11=yes -o IdentitiesOnly=yes'"
Command.to_script
Convert a command to a shell script:
>>> command1 = Command('ls', '-al', '/')
>>> command2 = Command('bash', '-c', command1.to_script().to_element())
>>> str(command2)
"bash -c 'ls -al /'"
Script.to_element
Convert a shell script to a command element:
>>> command = Command('bash', '-c', ShellScript('ls -al /').to_element())
>>> str(command)
"bash -c 'ls -al /'"
Script.from_scripts
Convert a list of shell scripts into a single script. Useful when building a script from multiple steps:
>>> scripts: List[ShellScript] = [
... ShellScript('cd $HOME'),
... ShellScript('ls -al')
... ]
>>>
>>> if True:
... scripts.append(ShellScript('rm -f bar'))
...
>>> script = ShellScript.from_scripts(scripts)
>>> str(script)
'cd $HOME; ls -al; rm -f bar'
Script.to_shell_command
Convert a shell script into a shell-driven command. This is what shell=True
would do, but it makes it explicit and involves correct type conversion:
>>> script = ShellScript("""
... cd $HOME
... ls -al
... """)
>>> command = script.to_shell_command()
>>> str(command)
"/bin/bash -c '\ncd $HOME\nls -al\n'"
Essential Classes
Test Management Tool
- class tmt.Clean(*, parent: Common | None = None, name: str | None = None, workdir: Literal[True] | Path | None = None, cli_invocation: tmt.cli.CliInvocation | None = None, logger: Logger)
A class for cleaning up workdirs, guests or images
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- guests() bool
Clean guests of runs
- images() bool
Clean images of provision plugins
- runs() bool
Clean workdirs of runs
- class tmt.Guest(*, data: GuestData, name: str | None = None, parent: Common | None = None, logger: Logger)
Guest provisioned for test execution
A base class for guest-like classes. Provides some of the basic methods and functionality, but note some of the methods are left intentionally empty. These do not have valid implementation on this level, and it’s up to Guest subclasses to provide one working in their respective infrastructure.
The following keys are expected in the ‘data’ container:
role ....... guest role in the multihost scenario guest ...... name, hostname or ip address
These are by default imported into instance attributes.
- ansible(playbook: Path, extra_args: str | None = None, friendly_command: str | None = None, log: LoggingFunction | None = None, silent: bool = False) None
Run an Ansible playbook on the guest.
A wrapper for
_run_ansible()
which is reponsible for running the playbook while this method makes sure our logging is consistent.- Parameters:
playbook – path to the playbook to run.
extra_args – aditional arguments to be passed to
ansible-playbook
via--extra-args
.friendly_command – if set, it would be logged instead of the command itself, to improve visibility of the command in logging output.
log – a logging function to use for logging of command output. By default,
logger.debug
is used.silent – if set, logging of steps taken by this function would be reduced.
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- details() None
Show guest details such as distro and kernel
- execute(command: ShellScript, cwd: Path | None = None, env: Dict[str, str] | None = None, friendly_command: str | None = None, test_session: bool = False, silent: bool = False, log: LoggingFunction | None = None, interactive: bool = False, **kwargs: Any) CommandOutput
- execute(command: Command, cwd: Path | None = None, env: Dict[str, str] | None = None, friendly_command: str | None = None, test_session: bool = False, silent: bool = False, log: LoggingFunction | None = None, interactive: bool = False, **kwargs: Any) CommandOutput
Execute a command on the guest.
- Parameters:
command – either a command or a shell script to execute.
cwd – if set, execute command in this directory on the guest.
env – if set, set these environment variables before running the command.
friendly_command – nice, human-friendly representation of the command.
- property facts: GuestFacts
- guest: str | None
- hardware: Hardware | None
- property is_ready: bool
Detect guest is ready or not
- load(data: GuestData) None
Load guest data into object attributes for easy access
Called during guest object initialization. Takes care of storing all supported keys (see class attribute _keys for the list) from provided data to the guest object attributes. Child classes can extend it to make additional guest attributes easily available.
Data dictionary can contain guest information from both command line options / L2 metadata / user configuration and wake up data stored by the save() method below.
- localhost = False
- multihost_name
Return guest’s multihost name, i.e. name and its role
- classmethod options(how: str | None = None) List[Callable[[Any], Any]]
Prepare command line options related to guests
- pull(source: Path | None = None, destination: Path | None = None, options: List[str] | None = None, extend_options: List[str] | None = None) None
Pull files from the guest
- push(source: Path | None = None, destination: Path | None = None, options: List[str] | None = None, superuser: bool = False) None
Push files to the guest
- reboot(hard: bool = False, command: Command | ShellScript | None = None, timeout: int | None = None) bool
Reboot the guest, return True if successful
Parameter ‘hard’ set to True means that guest should be rebooted by way which is not clean in sense that data can be lost. When set to False reboot should be done gracefully.
Use the ‘command’ parameter to specify a custom reboot command instead of the default ‘reboot’.
Parameter ‘timeout’ can be used to specify time (in seconds) to wait for the guest to come back up after rebooting.
- reconnect(timeout: int | None = None, tick: float = 5, tick_increase: float = 1.0) bool
Ensure the connection to the guest is working
The default timeout is 5 minutes. Custom number of seconds can be provided in the timeout parameter. This may be useful when long operations (such as system upgrade) are performed.
- remove() None
Remove the guest
Completely remove all guest instance data so that it does not consume any disk resources.
- classmethod requires() List[DependencySimple | DependencyFmfId | DependencyFile]
All requirements of the guest implementation
- role: str | None
- save() GuestData
Save guest data for future wake up
Export all essential guest data into a dictionary which will be stored in the guests.yaml file for possible future wake up of the guest. Everything needed to attach to a running instance should be added into the data dictionary by child classes.
- start() None
Start the guest
Get a new guest instance running. This should include preparing any configuration necessary to get it started. Called after load() is completed so all guest data should be available.
- stop() None
Stop the guest
Shut down a running guest instance so that it does not consume any memory or cpu resources. If needed, perform any actions necessary to store the instance status to disk.
- wake() None
Wake up the guest
Perform any actions necessary after step wake up to be able to attach to a running guest instance and execute commands. Called after load() is completed so all guest data should be prepared.
- class tmt.GuestSsh(*, data: GuestData, name: str | None = None, parent: Common | None = None, logger: Logger)
Guest provisioned for test execution, capable of accepting SSH connections
The following keys are expected in the ‘data’ dictionary:
role ....... guest role in the multihost scenario (inherited) guest ...... hostname or ip address (inherited) port ....... port to connect to user ....... user name to log in key ........ path to the private key (str or list) password ... password
These are by default imported into instance attributes.
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- execute(command: Command | ShellScript, cwd: Path | None = None, env: Dict[str, str] | None = None, friendly_command: str | None = None, test_session: bool = False, silent: bool = False, log: LoggingFunction | None = None, interactive: bool = False, **kwargs: Any) CommandOutput
Execute a command on the guest.
- Parameters:
command – either a command or a shell script to execute.
cwd – execute command in this directory on the guest.
env – if set, set these environment variables before running the command.
friendly_command – nice, human-friendly representation of the command.
- property is_ready: bool
Detect guest is ready or not
- key: List[Path]
- password: str | None
- port: int | None
- pull(source: Path | None = None, destination: Path | None = None, options: List[str] | None = None, extend_options: List[str] | None = None) None
Pull files from the guest
By default the whole plan workdir is synced from the same location on the guest. Use the ‘source’ and ‘destination’ to sync custom location, the ‘options’ parameter to modify default options
DEFAULT_RSYNC_PULL_OPTIONS
and ‘extend_options’ to extend them (e.g. by exclude).
- push(source: Path | None = None, destination: Path | None = None, options: List[str] | None = None, superuser: bool = False) None
Push files to the guest
By default the whole plan workdir is synced to the same location on the guest. Use the ‘source’ and ‘destination’ to sync custom location and the ‘options’ parametr to modify default options which are ‘-Rrz –links –safe-links –delete’.
Set ‘superuser’ if rsync command has to run as root or passwordless sudo on the Guest (e.g. pushing to r/o destination)
- reboot(hard: bool = False, command: Command | ShellScript | None = None, timeout: int | None = None, tick: float = 30.0, tick_increase: float = 1.0) bool
Reboot the guest, return True if reconnect was successful
Parameter ‘hard’ set to True means that guest should be rebooted by way which is not clean in sense that data can be lost. When set to False reboot should be done gracefully.
Use the ‘command’ parameter to specify a custom reboot command instead of the default ‘reboot’.
- remove() None
Remove the guest
Completely remove all guest instance data so that it does not consume any disk resources.
- ssh_option: List[str]
- stop() None
Stop the guest
Shut down a running guest instance so that it does not consume any memory or cpu resources. If needed, perform any actions necessary to store the instance status to disk.
- user: str | None
- class tmt.Logger(actual_logger: Logger, base_shift: int = 0, labels: List[str] | None = None, labels_padding: int = 0, verbosity_level: int = 0, debug_level: int = 0, quiet: bool = False, topics: Set[Topic] | None = None)
A logging entry point, representing a certain level of verbosity and handlers.
Provides actual logging methods plus methods for managing verbosity levels and handlers.
- add_console_handler(apply_colors: bool = False) None
Attach console handler to this logger
- add_logfile_handler(filepath: tmt.utils.Path) None
Attach a log file handler to this logger
- apply_verbosity_options(cli_invocation: tmt.cli.CliInvocation | None = None, **kwargs: Any) Logger
Update logger’s settings to match given CLI options.
Use this method to update logger’s settings after
Logger.descend()
call, to reflect options given to a tmt subcommand.
- clone() Logger
Create a copy of this logger instance.
All its settings are propagated to new instance. Settings are not shared, and may be freely modified after cloning without affecting the other logger.
- classmethod create(actual_logger: Logger | None = None, **verbosity_options: Any) Logger
Create a (root) tmt logger.
This method has a very limited set of use cases:
CLI bootstrapping right after tmt started.
Unit tests of code that requires logger as one of its inputs.
3rd party apps treating tmt as a library, i.e. when they wish tmt to use their logger instead of tmt’s default one.
- Parameters:
actual_logger – a
logging.Logger
instance to wrap. If not set, a default logger namedtmt
is created.
- debug(key: str, value: str | int | bool | float | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None, color: str | None = None, shift: int = 0, level: int = 1, topic: Topic | None = None) None
- descend(logger_name: str | None = None, extra_shift: int = 1) Logger
Create a copy of this logger instance, but with a new raw logger.
New
logging.Logger
instance is created from our raw logger, forming a parent/child relationship betwen them, and it’s then wrapped withLogger
instance. Settings of this logger are copied to new one, with the exception ofbase_shift
which is increased by one, effectively indenting all messages passing through new logger.- Parameters:
logger_name – optional name for the underlying
logging.Logger
instance. Useful for debugging. If not set, a generic one is created.extra_shift – by how many extra levels should messages be indented by new logger.
- fail(message: str, shift: int = 0) None
- classmethod get_bootstrap_logger() Logger
Create a logger designed for tmt startup time.
Warning
This logger has a very limited use case span, i.e. before tmt can digest its command-line options and create a proper logger. This happens inside
tmt.cli.main()
function, but there are some actions taken by tmt code before this function is called by Click, actions that need to emit logging messages. Using it anywhere outside of this brief time in tmt’s runtime should be ruled out.
- info(key: str, value: str | int | bool | float | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None, color: str | None = None, shift: int = 0) None
- property labels_span: int
Length of rendered labels
- print(key: str, value: str | int | bool | float | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None, color: str | None = None, shift: int = 0) None
- verbose(key: str, value: str | int | bool | float | tmt.utils.Path | tmt.utils.Command | tmt.utils.ShellScript | None = None, color: str | None = None, shift: int = 0, level: int = 1, topic: Topic | None = None) None
- warn(message: str, shift: int = 0) None
- class tmt.Plan(*, node: Tree, tree: Tree | None = None, run: Run | None = None, skip_validation: bool = False, raise_on_validation_error: bool = False, logger: Logger, **kwargs: Any)
Plan object (L2 Metadata)
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- context: FmfContext
- static create(*, name: str, template: str, path: Path, force: bool = False, dry: bool | None = None, logger: Logger) None
Create a new plan
- static edit_template(raw_content: str) str
Edit the default template with custom values
- property environment: Dict[str, str]
Return combined environment from plan data and command line
- gate: List[str]
- go() None
Execute the plan
- property is_remote_plan_reference: bool
Check whether the plan is a remote plan reference
- lint_discover_unknown_method() Generator[Tuple[LinterOutcome, str], None, None]
P004: discover step methods must be known
- lint_execute_not_defined() Generator[Tuple[LinterOutcome, str], None, None]
P002: execute step must be defined with “how”
- lint_execute_unknown_method() Generator[Tuple[LinterOutcome, str], None, None]
P003: execute step methods must be known
- lint_fmf_remote_ids_valid() Generator[Tuple[LinterOutcome, str], None, None]
P005: remote fmf ids must be valid
- lint_phases_have_guests() Generator[Tuple[LinterOutcome, str], None, None]
P007: step phases require existing guests and roles
- lint_unique_names() Generator[Tuple[LinterOutcome, str], None, None]
P006: phases must have unique names
- lint_unknown_keys() Generator[Tuple[LinterOutcome, str], None, None]
P001: all keys are known
- prune() None
Remove all uninteresting files from the plan workdir
- show() None
Show plan details
- step_names(enabled_only: bool = True, skip: List[str] | None = None) Generator[str, None, None]
Iterate over step names.
- Parameters:
enabled_only – if set, only enabled steps would be listed.
skip – if step name is in this list, it would be skipped.
- Yields:
step names.
- steps(enabled_only: bool = True, skip: List[str] | None = None) Generator[Step, None, None]
Iterate over steps.
- Parameters:
enabled_only – if set, only enabled steps would be listed.
skip – if step name is in this list, it would be skipped.
- Yields:
instance of
tmt.step.Step
, representing each step.
- class tmt.Result(name: str, result: ~tmt.result.ResultOutcome = ResultOutcome.PASS, note: str | None = None, log: ~typing.List[~tmt.utils.Path] = <factory>, starttime: str | None = None, endtime: str | None = None, duration: str | None = None, serialnumber: int = 0, fmf_id: ~tmt.base.FmfId | None = None, ids: ~typing.Dict[str, str | None] = <factory>, guest: ~tmt.result.ResultGuestData = <factory>, check: ~typing.List[~tmt.result.CheckResult] = <factory>, data_path: ~tmt.utils.Path | None = None)
Describes what tmt knows about a single test result
- check: List[CheckResult]
- data_path: Path | None = None
- static failures(log: str | None, msg_type: str = 'FAIL') str
Filter stdout and get only messages with certain type
- fmf_id: FmfId | None = None
- classmethod from_test(*, test: Test, result: ResultOutcome, note: str | None = None, ids: Dict[str, str | None] | None = None, log: List[Path] | None = None, guest: Guest | None = None) Result
Create a result from a test instance.
A simple helper for extracting interesting data from a given test. While it’s perfectly possible to go directly through
Result(...)
, when holding atmt.base.Test
instance, this method would initialize theResult
instance with the following:test name
test identifier (
id
key) andextra-*
IDs
Result would be interpreted according to test’s
result
key (see https://tmt.readthedocs.io/en/stable/spec/tests.html#result).
- guest: ResultGuestData
- ids: Dict[str, str | None]
- interpret_result(interpret: ResultInterpret) Result
Interpret result according to a given interpretation instruction.
Inspect and possibly modify
result
andnote
attributes, following theinterpret
value.- Parameters:
interpret – how to interpret current result.
- Returns:
Result
instance containing the updated result.
- serialnumber: int = 0
- show(display_guest: bool = True) str
Return a nicely colored result with test name (and note)
- class tmt.Run(*, id_: Path | None = None, tree: Tree | None = None, cli_invocation: tmt.cli.CliInvocation | None = None, logger: Logger)
Test run, a container of plans
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- property environment: Dict[str, str]
Return environment combined from wake up and command line
- finish() None
Check overall results, return appropriate exit code
- follow() None
Periodically check for new lines in the log.
- go() None
Go and do test steps for selected plans
- load() None
Load list of selected plans and enabled steps
- load_from_workdir() None
Load the run from its workdir, do not require the root in run.yaml to exist. Doest not load the fmf tree.
Use only when the data in workdir is sufficient (e.g. tmt clean and status only require the steps to be loaded and their status).
- save() None
Save list of selected plans and enabled steps
- class tmt.Status(*, parent: CommonDerivedType | None = None, name: str | None = None, workdir: Literal[True] | Path | None = None, relative_indent: int = 1, cli_invocation: tmt.cli.CliInvocation | None = None, logger: Logger, **kwargs: Any)
Status of tmt work directories.
- FIRST_COL_LEN = 11
- LONGEST_STEP = 'provision'
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- static colorize_column(content: str) str
Add color to a status column
- classmethod pad_with_spaces(string: str) str
Append spaces to string to properly align the first column
- plan_matches_filters(plan: Plan) bool
Check if the given plan matches filters from the command line
- print_header() None
Print the header of the status table based on verbosity
- show() None
Display the current status
- class tmt.Story(*, node: Tree, tree: Tree | None = None, skip_validation: bool = False, raise_on_validation_error: bool = False, logger: Logger, **kwargs: Any)
User story object
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- coverage(code: bool, test: bool, docs: bool) Tuple[bool, bool, bool]
Show story coverage
- static create(*, name: str, template: str, path: Path, force: bool = False, dry: bool | None = None, logger: Logger) None
Create a new story
- property documented: List[Link]
Return links to relevant documentation
- example: List[str]
- classmethod from_tree(tree: Tree) List[Story]
Gather list of instances of this class in a given tree.
Helpful when looking for objects of a class derived from
Core
in a given tree, encapsulating the mapping between core classes and tree search methods.- Parameters:
tree – tree to search for objects.
- property implemented: List[Link]
Return links to relevant source code
- lint_story() Generator[Tuple[LinterOutcome, str], None, None]
S002: story key must be defined
- lint_unknown_keys() Generator[Tuple[LinterOutcome, str], None, None]
S001: all keys are known
- priority: StoryPriority | None = None
- show() None
Show story details
- property status: List[str]
Aggregate story status from implemented-, verified- and documented-by links
- story: str | None = None
- title: str | None = None
- property verified: List[Link]
Return links to relevant test coverage
- class tmt.Test(*, node: Tree, tree: Tree | None = None, skip_validation: bool = False, raise_on_validation_error: bool = False, logger: Logger, **kwargs: Any)
Test object (L1 Metadata)
- check: List[Check]
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- component: List[str]
- contact: List[str]
- static create(*, name: str, template: str, path: Path, force: bool = False, dry: bool | None = None, logger: Logger) None
Create a new test
- data_path: Path | None = None
- duration: str = '5m'
- endtime: str | None = None
- environment: Dict[str, str]
- framework: str = 'shell'
- classmethod from_dict(*, mapping: Dict[str, Any], name: str, skip_validation: bool = False, raise_on_validation_error: bool = False, logger: Logger, **kwargs: Any) Test
Initialize test data from a dictionary.
Useful when data describing a test are stored in a mapping instead of an fmf node.
- lint_absolute_path() Generator[Tuple[LinterOutcome, str], None, None]
T003: test directory path must be absolute
- lint_defined_test() Generator[Tuple[LinterOutcome, str], None, None]
T002: test script must be defined
- lint_legacy_coverage_key() Generator[Tuple[LinterOutcome, str], None, None]
T006: coverage has been obsoleted by link
- lint_legacy_relevancy_rules() Generator[Tuple[LinterOutcome, str], None, None]
T005: relevancy has been obsoleted by adjust
- lint_manual_test_path_exists() Generator[Tuple[LinterOutcome, str], None, None]
T007: manual test path is not an actual path
- lint_manual_valid_markdown() Generator[Tuple[LinterOutcome, str], None, None]
T008: manual test should be valid markdown
- lint_path_exists() Generator[Tuple[LinterOutcome, str], None, None]
T004: test directory path must exist
- lint_require_type_field() Generator[Tuple[LinterOutcome, str], None, None]
T009: require fields should have type field
- lint_unknown_keys() Generator[Tuple[LinterOutcome, str], None, None]
T001: all keys are known
- manual: bool = False
- property manual_test_path: Path
- path: Path | None = None
- real_duration: str | None = None
- recommend: List[DependencySimple | DependencyFmfId | DependencyFile]
- require: List[DependencySimple | DependencyFmfId | DependencyFile]
- result: str = 'respect'
- returncode: int | None = None
- serialnumber: int = 0
- show() None
Show test details
- starttime: str | None = None
- test: ShellScript | None = None
- property test_framework: Type[TestFramework]
- where: List[str]
- class tmt.Tree(*, path: Path | None = None, tree: Tree | None = None, fmf_context: FmfContext | None = None, logger: Logger)
Test Metadata Tree
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- classmethod grow(*, path: Path | None = None, tree: Tree | None = None, fmf_context: FmfContext | None = None, logger: Logger | None = None) Tree
Initialize tmt tree from directory path or given fmf tree.
This method serves as an entry point for interactive use of tmt-as-a-library, providing sane defaults.
Warning
This method has a very limited use case, i.e. to help bootstrapping interactive tmt sessions. Using it anywhere outside of this scope should be ruled out.
- static init(*, path: Path, template: str, force: bool, logger: Logger) None
Initialize a new tmt tree, optionally with a template
- plans(logger: Logger | None = None, keys: List[str] | None = None, names: List[str] | None = None, filters: List[str] | None = None, conditions: List[str] | None = None, run: Run | None = None, links: List[LinkNeedle] | None = None, excludes: List[str] | None = None) List[Plan]
Search available plans
- property root: Path | None
Metadata root
- sanitize_cli_names(names: List[str]) List[str]
Sanitize CLI names in case name includes control character
- stories(logger: Logger | None = None, keys: List[str] | None = None, names: List[str] | None = None, filters: List[str] | None = None, conditions: List[str] | None = None, whole: bool = False, links: List[LinkNeedle] | None = None, excludes: List[str] | None = None) List[Story]
Search available stories
- tests(logger: Logger | None = None, keys: List[str] | None = None, names: List[str] | None = None, filters: List[str] | None = None, conditions: List[str] | None = None, unique: bool = True, links: List[LinkNeedle] | None = None, excludes: List[str] | None = None) List[Test]
Search available tests
- property tree: Tree
Initialize tree only when accessed