<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-family:arial,sans-serif"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Nov 15, 2023 at 8:11 AM Juraj Linkeš <juraj.linkes@pantheon.tech> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Format according to the Google format and PEP257, with slight<br>
deviations.<br>
<br>
Signed-off-by: Juraj Linkeš <juraj.linkes@pantheon.tech><br>
---<br>
dts/framework/dts.py | 128 ++++++++++++++++++++++++++++++++++++-------<br>
dts/main.py | 8 ++-<br>
2 files changed, 112 insertions(+), 24 deletions(-)<br>
<br>
diff --git a/dts/framework/dts.py b/dts/framework/dts.py<br>
index 4c7fb0c40a..331fed7dc4 100644<br>
--- a/dts/framework/dts.py<br>
+++ b/dts/framework/dts.py<br>
@@ -3,6 +3,33 @@<br>
# Copyright(c) 2022-2023 PANTHEON.tech s.r.o.<br>
# Copyright(c) 2022-2023 University of New Hampshire<br>
<br>
+r"""Test suite runner module.<br>
+<br>
+A DTS run is split into stages:<br>
+<br>
+ #. Execution stage,<br>
+ #. Build target stage,<br>
+ #. Test suite stage,<br>
+ #. Test case stage.<br>
+<br>
+The module is responsible for running tests on testbeds defined in the test run configuration.<br>
+Each setup or teardown of each stage is recorded in a :class:`~framework.test_result.DTSResult` or<br>
+one of its subclasses. The test case results are also recorded.<br>
+<br>
+If an error occurs, the current stage is aborted, the error is recorded and the run continues in<br>
+the next iteration of the same stage. The return code is the highest `severity` of all<br>
+:class:`~.framework.exception.DTSError`\s.<br>
+<br>
+Example:<br>
+ An error occurs in a build target setup. The current build target is aborted and the run<br>
+ continues with the next build target. If the errored build target was the last one in the given<br>
+ execution, the next execution begins.<br>
+<br>
+Attributes:<br>
+ dts_logger: The logger instance used in this module.<br>
+ result: The top level result used in the module.<br>
+"""<br>
+<br>
import sys<br>
<br>
from .config import (<br>
@@ -23,9 +50,38 @@<br>
<br>
<br>
def run_all() -> None:<br>
- """<br>
- The main process of DTS. Runs all build targets in all executions from the main<br>
- config file.<br>
+ """Run all build targets in all executions from the test run configuration.<br>
+<br>
+ Before running test suites, executions and build targets are first set up.<br>
+ The executions and build targets defined in the test run configuration are iterated over.<br>
+ The executions define which tests to run and where to run them and build targets define<br>
+ the DPDK build setup.<br>
+<br>
+ The tests suites are set up for each execution/build target tuple and each scheduled<br>
+ test case within the test suite is set up, executed and torn down. After all test cases<br>
+ have been executed, the test suite is torn down and the next build target will be tested.<br>
+<br>
+ All the nested steps look like this:<br>
+<br>
+ #. Execution setup<br>
+<br>
+ #. Build target setup<br>
+<br>
+ #. Test suite setup<br>
+<br>
+ #. Test case setup<br>
+ #. Test case logic<br>
+ #. Test case teardown<br>
+<br>
+ #. Test suite teardown<br>
+<br>
+ #. Build target teardown<br>
+<br>
+ #. Execution teardown<br>
+<br>
+ The test cases are filtered according to the specification in the test run configuration and<br>
+ the :option:`--test-cases` command line argument or<br>
+ the :envvar:`DTS_TESTCASES` environment variable.<br>
"""<br>
global dts_logger<br>
global result<br>
@@ -87,6 +143,8 @@ def run_all() -> None:<br>
<br>
<br>
def _check_dts_python_version() -> None:<br>
+ """Check the required Python version - v3.10."""<br>
+<br>
def RED(text: str) -> str:<br>
return f"\u001B[31;1m{str(text)}\u001B[0m"<br>
<br>
@@ -111,9 +169,16 @@ def _run_execution(<br>
execution: ExecutionConfiguration,<br>
result: DTSResult,<br>
) -> None:<br>
- """<br>
- Run the given execution. This involves running the execution setup as well as<br>
- running all build targets in the given execution.<br>
+ """Run the given execution.<br>
+<br>
+ This involves running the execution setup as well as running all build targets<br>
+ in the given execution. After that, execution teardown is run.<br>
+<br>
+ Args:<br>
+ sut_node: The execution's SUT node.<br>
+ tg_node: The execution's TG node.<br>
+ execution: An execution's test run configuration.<br>
+ result: The top level result object.<br>
"""<br>
<a href="http://dts_logger.info" rel="noreferrer" target="_blank">dts_logger.info</a>(<br>
f"Running execution with SUT '{<a href="http://execution.system_under_test_node.name" rel="noreferrer" target="_blank">execution.system_under_test_node.name</a>}'."<br>
@@ -150,8 +215,18 @@ def _run_build_target(<br>
execution: ExecutionConfiguration,<br>
execution_result: ExecutionResult,<br>
) -> None:<br>
- """<br>
- Run the given build target.<br>
+ """Run the given build target.<br>
+<br>
+ This involves running the build target setup as well as running all test suites<br>
+ in the given execution the build target is defined in.<br>
+ After that, build target teardown is run.<br>
+<br>
+ Args:<br>
+ sut_node: The execution's SUT node.<br>
+ tg_node: The execution's TG node.<br>
+ build_target: A build target's test run configuration.<br>
+ execution: The build target's execution's test run configuration.<br>
+ execution_result: The execution level result object associated with the execution.<br>
"""<br>
<a href="http://dts_logger.info" rel="noreferrer" target="_blank">dts_logger.info</a>(f"Running build target '{<a href="http://build_target.name" rel="noreferrer" target="_blank">build_target.name</a>}'.")<br>
build_target_result = execution_result.add_build_target(build_target)<br>
@@ -183,10 +258,17 @@ def _run_all_suites(<br>
execution: ExecutionConfiguration,<br>
build_target_result: BuildTargetResult,<br>
) -> None:<br>
- """<br>
- Use the given build_target to run execution's test suites<br>
- with possibly only a subset of test cases.<br>
- If no subset is specified, run all test cases.<br>
+ """Run the execution's (possibly a subset) test suites using the current build_target.<br>
+<br>
+ The function assumes the build target we're testing has already been built on the SUT node.<br>
+ The current build target thus corresponds to the current DPDK build present on the SUT node.<br>
+<br>
+ Args:<br>
+ sut_node: The execution's SUT node.<br>
+ tg_node: The execution's TG node.<br>
+ execution: The execution's test run configuration associated with the current build target.<br>
+ build_target_result: The build target level result object associated<br>
+ with the current build target.<br>
"""<br></blockquote><div><br></div><div><div style="font-family:arial,sans-serif" class="gmail_default">Is it worth mentioning in this method or the _run_build_target method that when a blocking suite fails that no more suites will be run on that build target?<br></div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
end_build_target = False<br>
if not execution.skip_smoke_tests:<br>
@@ -215,16 +297,22 @@ def _run_single_suite(<br>
build_target_result: BuildTargetResult,<br>
test_suite_config: TestSuiteConfig,<br>
) -> None:<br>
- """Runs a single test suite.<br>
+ """Run all test suite in a single test suite module.<br>
+<br>
+ The function assumes the build target we're testing has already been built on the SUT node.<br>
+ The current build target thus corresponds to the current DPDK build present on the SUT node.<br>
<br>
Args:<br>
- sut_node: Node to run tests on.<br>
- execution: Execution the test case belongs to.<br>
- build_target_result: Build target configuration test case is run on<br>
- test_suite_config: Test suite configuration<br>
+ sut_node: The execution's SUT node.<br>
+ tg_node: The execution's TG node.<br>
+ execution: The execution's test run configuration associated with the current build target.<br>
+ build_target_result: The build target level result object associated<br>
+ with the current build target.<br>
+ test_suite_config: Test suite test run configuration specifying the test suite module<br>
+ and possibly a subset of test cases of test suites in that module.<br>
<br>
Raises:<br>
- BlockingTestSuiteError: If a test suite that was marked as blocking fails.<br>
+ BlockingTestSuiteError: If a blocking test suite fails.<br>
"""<br>
try:<br>
full_suite_path = f"tests.TestSuite_{test_suite_config.test_suite}"<br>
@@ -248,9 +336,7 @@ def _run_single_suite(<br>
<br>
<br>
def _exit_dts() -> None:<br>
- """<br>
- Process all errors and exit with the proper exit code.<br>
- """<br>
+ """Process all errors and exit with the proper exit code."""<br>
result.process()<br>
<br>
if dts_logger:<br>
diff --git a/dts/main.py b/dts/main.py<br>
index 5d4714b0c3..f703615d11 100755<br>
--- a/dts/main.py<br>
+++ b/dts/main.py<br>
@@ -4,9 +4,7 @@<br>
# Copyright(c) 2022 PANTHEON.tech s.r.o.<br>
# Copyright(c) 2022 University of New Hampshire<br>
<br>
-"""<br>
-A test framework for testing DPDK.<br>
-"""<br>
+"""The DTS executable."""<br>
<br>
import logging<br>
<br>
@@ -17,6 +15,10 @@ def main() -> None:<br>
"""Set DTS settings, then run DTS.<br>
<br>
The DTS settings are taken from the command line arguments and the environment variables.<br>
+ The settings object is stored in the module-level variable settings.SETTINGS which the entire<br>
+ framework uses. After importing the module (or the variable), any changes to the variable are<br>
+ not going to be reflected without a re-import. This means that the SETTINGS variable must<br>
+ be modified before the settings module is imported anywhere else in the framework.<br>
"""<br>
settings.SETTINGS = settings.get_settings()<br>
from framework import dts<br>
-- <br>
2.34.1<br>
<br>
</blockquote></div></div>