This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 310eaf9a1f Optimize parallel test execution for unit tests (#30705)
310eaf9a1f is described below

commit 310eaf9a1fddab63494124baf52c6afc64b4a832
Author: Jarek Potiuk <[email protected]>
AuthorDate: Wed Apr 19 02:54:30 2023 +0200

    Optimize parallel test execution for unit tests (#30705)
    
    We are runnig the tests in parallel test types in order to speed
    up their execution. Howver some test types and subsets of tests
    are taking far longer to execute than other test types.
    
    The longest tests to run are Providers and WWW tests, and the
    longest tests from Providers are by far Amazon tests, then
    Google. "All Other" Provider tests take about the same time
    as Amazon tests - also after splitting the provider tests,
    Core tests take the longest time.
    
    When we are running tests in parallel on multiple CPUs, often
    the longest running tests remain runing on their own while the
    other CPUS are not busy. We could run separate tests type
    per provider, but overhead of starting the database and collecting
    and initializing tests for them is too big for it to achieve
    speedups - especially for Public runners, having 80 separate
    databases with 80 subsequent container runs is slower than
    running all Provider tests together.
    
    However we can split the Provider tests into smaller number of
    chunks and prioritize running the long chunks first. This
    should improve the effect of parellelisation and improve utilization of
    our multi-CPU machines.
    
    This PR aims to do that:
    
    * Split Provider tests (if amazon or google are part of the
      provider tests) into amazon, google, all-other chunks
    
    * Move sorting of the test types to selective_check, to sort the
      test types according to expected longest running time (the longest
      tests to run are added first)
    
    This should improve the CPU utilization of our multi-CPU runners
    and make the tests involving complete Provider set (or even sets
    containing amazon, google and few other providers)
    execute quite a few minutes faster on average.
    
    We could also get rid of some sequential processing for the Public PRs
    because each test type we will run will be less demanding overall. We
    used to get a lot of 137 exit codes (memory errors) but with splitting
    out Providers, the risk of exhausting resources be two test types
    running in paralel are low.
---
 BREEZE.rst                                         |   9 ++
 Dockerfile.ci                                      |  13 +++
 TESTING.rst                                        |   8 +-
 .../airflow_breeze/commands/testing_commands.py    |  59 +-----------
 .../commands/testing_commands_config.py            |   1 -
 .../src/airflow_breeze/params/shell_params.py      |  11 ++-
 dev/breeze/src/airflow_breeze/utils/run_tests.py   |   6 ++
 .../src/airflow_breeze/utils/selective_checks.py   |  50 +++++++++-
 dev/breeze/tests/test_selective_checks.py          | 101 +++++++++++++--------
 images/breeze/output-commands-hash.txt             |   4 +-
 images/breeze/output_testing_tests.svg             |  76 ++++++++--------
 scripts/docker/entrypoint_ci.sh                    |  13 +++
 12 files changed, 213 insertions(+), 138 deletions(-)

diff --git a/BREEZE.rst b/BREEZE.rst
index dc39062d89..647f672451 100644
--- a/BREEZE.rst
+++ b/BREEZE.rst
@@ -788,6 +788,15 @@ For example this will only run provider tests for airbyte 
and http providers:
 
    breeze testing tests --test-type "Providers[airbyte,http]"
 
+You can also exclude tests for some providers from being run when whole 
"Providers" test type is run.
+
+For example this will run tests for all providers except amazon and google 
provider tests:
+
+.. code-block:: bash
+
+   breeze testing tests --test-type "Providers[-amazon,google]"
+
+
 You can also run parallel tests with ``--run-in-parallel`` flag - by default 
it will run all tests types
 in parallel, but you can specify the test type that you want to run with space 
separated list of test
 types passed to ``--parallel-test-types`` flag.
diff --git a/Dockerfile.ci b/Dockerfile.ci
index c3613ccc26..b86a12dfa7 100644
--- a/Dockerfile.ci
+++ b/Dockerfile.ci
@@ -1049,6 +1049,19 @@ else
             ${TEST_TYPE} == "Postgres" || ${TEST_TYPE} == "MySQL" || \
             ${TEST_TYPE} == "Long" ]]; then
         SELECTED_TESTS=("${ALL_TESTS[@]}")
+    elif [[ ${TEST_TYPE} =~ Providers\[\-(.*)\] ]]; then
+        # When providers start with `-` it means that we should run all 
provider tests except those
+        SELECTED_TESTS=("${PROVIDERS_TESTS[@]}")
+        for provider in ${BASH_REMATCH[1]//,/ }
+        do
+            providers_dir="tests/providers/${provider//./\/}"
+            if [[ -d ${providers_dir} ]]; then
+                echo "${COLOR_BLUE}Ignoring ${providers_dir} as it has been 
deselected.${COLOR_RESET}"
+                
EXTRA_PYTEST_ARGS+=("--ignore=tests/providers/${provider//./\/}")
+            else
+                echo "${COLOR_YELLOW}Skipping ${providers_dir} as the 
directory does not exist.${COLOR_RESET}"
+            fi
+        done
     elif [[ ${TEST_TYPE} =~ Providers\[(.*)\] ]]; then
         SELECTED_TESTS=()
         for provider in ${BASH_REMATCH[1]//,/ }
diff --git a/TESTING.rst b/TESTING.rst
index a89b2d287c..e137d1486c 100644
--- a/TESTING.rst
+++ b/TESTING.rst
@@ -297,12 +297,18 @@ In case of Providers tests, you can run tests for all 
providers
 
     breeze testing tests --test-type Providers
 
-You can also limit the set of providers you would like to run tests of
+You can limit the set of providers you would like to run tests of
 
 .. code-block:: bash
 
     breeze testing tests --test-type "Providers[airbyte,http]"
 
+You can also run all providers but exclude the providers you would like to skip
+
+.. code-block:: bash
+
+    breeze testing tests --test-type "Providers[-amazon,google]"
+
 
 Running full Airflow unit test suite in parallel
 ------------------------------------------------
diff --git a/dev/breeze/src/airflow_breeze/commands/testing_commands.py 
b/dev/breeze/src/airflow_breeze/commands/testing_commands.py
index 752764bd9b..1e569460df 100644
--- a/dev/breeze/src/airflow_breeze/commands/testing_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/testing_commands.py
@@ -17,7 +17,6 @@
 from __future__ import annotations
 
 import os
-import re
 import sys
 from datetime import datetime
 
@@ -65,12 +64,11 @@ from airflow_breeze.utils.docker_command_utils import (
 from airflow_breeze.utils.parallel import (
     GenericRegexpProgressMatcher,
     SummarizeAfter,
-    bytes2human,
     check_async_run_results,
     run_with_pool,
 )
 from airflow_breeze.utils.path_utils import FILES_DIR, 
cleanup_python_generated_files
-from airflow_breeze.utils.run_tests import run_docker_compose_tests
+from airflow_breeze.utils.run_tests import file_name_from_test_type, 
run_docker_compose_tests
 from airflow_breeze.utils.run_utils import get_filesystem_type, run_command
 
 LOW_MEMORY_CONDITION = 8 * 1024 * 1024 * 1024
@@ -143,7 +141,7 @@ def _run_test(
             "[error]Only 'Providers' test type can specify actual tests with 
\\[\\][/]"
         )
         sys.exit(1)
-    project_name = _file_name_from_test_type(exec_shell_params.test_type)
+    project_name = file_name_from_test_type(exec_shell_params.test_type)
     down_cmd = [
         *DOCKER_COMPOSE_COMMAND,
         "--project-name",
@@ -209,11 +207,6 @@ def _run_test(
     return result.returncode, f"Test: {exec_shell_params.test_type}"
 
 
-def _file_name_from_test_type(test_type: str):
-    test_type_no_brackets = test_type.lower().replace("[", "_").replace("]", 
"")
-    return re.sub("[,\.]", "_", test_type_no_brackets)[:30]
-
-
 def _run_tests_in_pool(
     tests_to_run: list[str],
     parallelism: int,
@@ -268,43 +261,12 @@ def run_tests_in_parallel(
     parallel_test_types_list: list[str],
     extra_pytest_args: tuple,
     db_reset: bool,
-    full_tests_needed: bool,
     test_timeout: int,
     include_success_outputs: bool,
     debug_resources: bool,
     parallelism: int,
     skip_cleanup: bool,
 ) -> None:
-    import psutil
-
-    memory_available = psutil.virtual_memory()
-    if memory_available.available < LOW_MEMORY_CONDITION and 
exec_shell_params.backend in ["mssql", "mysql"]:
-        # Run heavy tests sequentially
-        heavy_test_types_to_run = {"Core", "Providers"} & 
set(parallel_test_types_list)
-        if heavy_test_types_to_run:
-            # some of those are requested
-            get_console().print(
-                f"[warning]Running {heavy_test_types_to_run} tests 
sequentially"
-                f"for {exec_shell_params.backend}"
-                f" backend due to low memory available: 
{bytes2human(memory_available.available)}"
-            )
-            tests_to_run_sequentially = []
-            for heavy_test_type in heavy_test_types_to_run:
-                for test_type in parallel_test_types_list:
-                    if test_type.startswith(heavy_test_type):
-                        parallel_test_types_list.remove(test_type)
-                        tests_to_run_sequentially.append(test_type)
-            _run_tests_in_pool(
-                tests_to_run=tests_to_run_sequentially,
-                parallelism=1,
-                exec_shell_params=exec_shell_params,
-                extra_pytest_args=extra_pytest_args,
-                test_timeout=test_timeout,
-                db_reset=db_reset,
-                include_success_outputs=include_success_outputs,
-                debug_resources=debug_resources,
-                skip_cleanup=skip_cleanup,
-            )
     _run_tests_in_pool(
         tests_to_run=parallel_test_types_list,
         parallelism=parallelism,
@@ -336,8 +298,9 @@ def run_tests_in_parallel(
 @option_mount_sources
 @click.option(
     "--test-type",
-    help="Type of test to run. Note that with Providers, you can also specify 
which provider "
-    'tests should be run - for example --test-type "Providers[airbyte,http]"',
+    help="Type of test to run. With Providers, you can specify tests of which 
providers "
+    "should be run: `Providers[airbyte,http]` or "
+    "excluded from the full test suite: `Providers[-amazon,google]`",
     default="All",
     type=NotVerifiedBetterChoice(ALLOWED_TEST_TYPE_CHOICES),
 )
@@ -361,12 +324,6 @@ def run_tests_in_parallel(
     show_default=True,
     envvar="PARALLEL_TEST_TYPES",
 )
[email protected](
-    "--full-tests-needed",
-    help="Whether full set of tests is run.",
-    is_flag=True,
-    envvar="FULL_TESTS_NEEDED",
-)
 @click.option(
     "--upgrade-boto",
     help="Remove aiobotocore and upgrade botocore and boto to the latest 
version.",
@@ -405,7 +362,6 @@ def command_for_tests(
     debug_resources: bool,
     include_success_outputs: bool,
     parallel_test_types: str,
-    full_tests_needed: bool,
     mount_sources: str,
     extra_pytest_args: tuple,
     upgrade_boto: bool,
@@ -434,16 +390,11 @@ def command_for_tests(
     perform_environment_checks()
     if run_in_parallel:
         test_list = parallel_test_types.split(" ")
-        test_list.sort(key=lambda x: x in ["Providers", "WWW"], reverse=True)
         run_tests_in_parallel(
             exec_shell_params=exec_shell_params,
             parallel_test_types_list=test_list,
             extra_pytest_args=extra_pytest_args,
             db_reset=db_reset,
-            # Allow to pass information on whether to use full tests in the 
parallel execution mode
-            # or not - this will allow to skip some heavy tests on more 
resource-heavy configurations
-            # in case full tests are not required, some of those will be 
skipped
-            full_tests_needed=full_tests_needed,
             test_timeout=test_timeout,
             include_success_outputs=include_success_outputs,
             parallelism=parallelism,
diff --git a/dev/breeze/src/airflow_breeze/commands/testing_commands_config.py 
b/dev/breeze/src/airflow_breeze/commands/testing_commands_config.py
index 5696510939..793175e5f2 100644
--- a/dev/breeze/src/airflow_breeze/commands/testing_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/testing_commands_config.py
@@ -46,7 +46,6 @@ TESTING_PARAMETERS: dict[str, list[dict[str, str | 
list[str]]]] = {
                 "--skip-cleanup",
                 "--debug-resources",
                 "--include-success-outputs",
-                "--full-tests-needed",
             ],
         },
         {
diff --git a/dev/breeze/src/airflow_breeze/params/shell_params.py 
b/dev/breeze/src/airflow_breeze/params/shell_params.py
index e854c3db83..ff941b4493 100644
--- a/dev/breeze/src/airflow_breeze/params/shell_params.py
+++ b/dev/breeze/src/airflow_breeze/params/shell_params.py
@@ -47,6 +47,7 @@ from airflow_breeze.utils.path_utils import (
     MSSQL_TMP_DIR_NAME,
     SCRIPTS_CI_DIR,
 )
+from airflow_breeze.utils.run_tests import file_name_from_test_type
 from airflow_breeze.utils.run_utils import get_filesystem_type, run_command
 from airflow_breeze.utils.shared_options import get_verbose
 
@@ -267,9 +268,13 @@ class ShellParams:
     @property
     def mssql_data_volume(self) -> str:
         docker_filesystem = get_filesystem_type("/var/lib/docker")
-        # in case of Providers[....], only leave Providers
-        base_test_type = self.test_type.split("[")[0] if self.test_type else 
None
-        volume_name = f"tmp-mssql-volume-{base_test_type}" if base_test_type 
else "tmp-mssql-volume"
+        # Make sure the test type is not too long to be used as a volume name 
in docker-compose
+        # The tmp directory in our self-hosted runners can be quite long, so 
we should limit the volume name
+        volume_name = (
+            "tmp-mssql-volume-" + file_name_from_test_type(self.test_type)[:20]
+            if self.test_type
+            else "tmp-mssql-volume"
+        )
         if docker_filesystem == "tmpfs":
             return os.fspath(Path.home() / MSSQL_TMP_DIR_NAME / 
f"{volume_name}-{self.mssql_version}")
         else:
diff --git a/dev/breeze/src/airflow_breeze/utils/run_tests.py 
b/dev/breeze/src/airflow_breeze/utils/run_tests.py
index 3687e58e93..ac2c160fa5 100644
--- a/dev/breeze/src/airflow_breeze/utils/run_tests.py
+++ b/dev/breeze/src/airflow_breeze/utils/run_tests.py
@@ -17,6 +17,7 @@
 from __future__ import annotations
 
 import os
+import re
 import sys
 from subprocess import DEVNULL
 
@@ -75,3 +76,8 @@ def run_docker_compose_tests(image_name: str, 
extra_pytest_args: tuple) -> tuple
         check=False,
     )
     return command_result.returncode, f"Testing docker-compose python with 
{image_name}"
+
+
+def file_name_from_test_type(test_type: str):
+    test_type_no_brackets = test_type.lower().replace("[", "_").replace("]", 
"")
+    return re.sub("[,.]", "_", test_type_no_brackets)[:30]
diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py 
b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
index 36a85d56dc..36b85f5f76 100644
--- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
+++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
@@ -588,6 +588,36 @@ class SelectiveChecks:
         get_console().print(sorted_candidate_test_types)
         return sorted_candidate_test_types
 
+    @staticmethod
+    def _extract_long_provider_tests(current_test_types: set[str]):
+        """
+        In case there are Provider tests in the list of test to run (either in 
the form of
+        Providers or Providers[...] we subtract them from the test type,
+        and add them to the list of tests to run individually.
+
+        In case of Providers, we need to replace it with 
Providers[-<list_of_long_tests>], but
+        in case of Providers[list_of_tests] we need to remove the long tests 
from the list.
+
+        """
+        long_tests = ["amazon", "google"]
+        for original_test_type in tuple(current_test_types):
+            if original_test_type == "Providers":
+                current_test_types.remove(original_test_type)
+                for long_test in long_tests:
+                    current_test_types.add(f"Providers[{long_test}]")
+                current_test_types.add(f"Providers[-{','.join(long_tests)}]")
+            elif original_test_type.startswith("Providers["):
+                provider_tests_to_run = (
+                    original_test_type.replace("Providers[", "").replace("]", 
"").split(",")
+                )
+                if any(long_test in provider_tests_to_run for long_test in 
long_tests):
+                    current_test_types.remove(original_test_type)
+                    for long_test in long_tests:
+                        if long_test in provider_tests_to_run:
+                            current_test_types.add(f"Providers[{long_test}]")
+                            provider_tests_to_run.remove(long_test)
+                    
current_test_types.add(f"Providers[{','.join(provider_tests_to_run)}]")
+
     @cached_property
     def parallel_test_types(self) -> str:
         if not self.run_tests:
@@ -606,7 +636,25 @@ class SelectiveChecks:
                     )
                     test_types_to_remove.add(test_type)
             current_test_types = current_test_types - test_types_to_remove
-        return " ".join(sorted(current_test_types))
+
+        self._extract_long_provider_tests(current_test_types)
+
+        # this should be hard-coded as we want to have very specific sequence 
of tests
+        sorting_order = ["Core", "Providers[-amazon,google]", "Other", 
"Providers[amazon]", "WWW"]
+
+        def sort_key(t: str) -> str:
+            # Put the test types in the order we want them to run
+            if t in sorting_order:
+                return str(sorting_order.index(t))
+            else:
+                return str(len(sorting_order)) + t
+
+        return " ".join(
+            sorted(
+                current_test_types,
+                key=sort_key,
+            )
+        )
 
     @cached_property
     def basic_checks_only(self) -> bool:
diff --git a/dev/breeze/tests/test_selective_checks.py 
b/dev/breeze/tests/test_selective_checks.py
index c468e5a78a..ff22b2c1c5 100644
--- a/dev/breeze/tests/test_selective_checks.py
+++ b/dev/breeze/tests/test_selective_checks.py
@@ -16,15 +16,27 @@
 # under the License.
 from __future__ import annotations
 
+import re
+
 import pytest
 
 from airflow_breeze.global_constants import GithubEvents
 from airflow_breeze.utils.selective_checks import SelectiveChecks
 
+ANSI_COLORS_MATCHER = re.compile(r"(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]")
+
+
+def escape_ansi_colors(line):
+    return ANSI_COLORS_MATCHER.sub("", line)
+
 
 def assert_outputs_are_printed(expected_outputs: dict[str, str], stderr: str):
     for name, value in expected_outputs.items():
-        assert f"{name}={value}" in stderr
+        search_string = rf"^{re.escape(name)}={re.escape(value)}$"
+        escaped_stderr = escape_ansi_colors(stderr)
+        assert re.search(
+            search_string, escaped_stderr, re.MULTILINE
+        ), f"Expected {name}={value} not found in {escaped_stderr}"
 
 
 @pytest.mark.parametrize(
@@ -44,7 +56,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "run-amazon-tests": "false",
                     "docs-build": "false",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "",
+                    "parallel-test-types": "",
                 },
                 id="No tests on simple change",
             )
@@ -63,7 +75,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "run-amazon-tests": "false",
                     "docs-build": "true",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "API Always",
+                    "parallel-test-types": "API Always",
                 },
                 id="Only API tests and DOCS should run",
             )
@@ -85,7 +97,8 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "run-amazon-tests": "true",
                     "docs-build": "true",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "API Always 
Providers[amazon,common.sql,google,postgres]",
+                    "parallel-test-types": "Providers[amazon] "
+                    "API Always Providers[common.sql,postgres] 
Providers[google]",
                 },
                 id="API and providers tests and docs should run",
             )
@@ -105,7 +118,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "docs-build": "false",
                     "run-kubernetes-tests": "false",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "Always Providers[apache.beam,google]",
+                    "parallel-test-types": "Always Providers[apache.beam] 
Providers[google]",
                 },
                 id="Selected Providers and docs should run",
             )
@@ -125,7 +138,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "docs-build": "true",
                     "run-kubernetes-tests": "false",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "",
+                    "parallel-test-types": "",
                 },
                 id="Only docs builds should run - no tests needed",
             )
@@ -148,7 +161,8 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "docs-build": "true",
                     "run-kubernetes-tests": "true",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "Always 
Providers[amazon,common.sql,google,postgres]",
+                    "parallel-test-types": "Providers[amazon] "
+                    "Always Providers[common.sql,postgres] Providers[google]",
                 },
                 id="Helm tests, providers (both upstream and downstream),"
                 "kubernetes tests and docs should run",
@@ -173,7 +187,8 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "docs-build": "true",
                     "run-kubernetes-tests": "true",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "Always 
Providers[airbyte,apache.livy,dbt.cloud,dingding,discord,http]",
+                    "parallel-test-types": "Always "
+                    
"Providers[airbyte,apache.livy,dbt.cloud,dingding,discord,http]",
                 },
                 id="Helm tests, http and all relevant providers, kubernetes 
tests and "
                 "docs should run even if unimportant files were added",
@@ -198,7 +213,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "docs-build": "true",
                     "run-kubernetes-tests": "true",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "Always Providers[airbyte,http]",
+                    "parallel-test-types": "Always Providers[airbyte,http]",
                 },
                 id="Helm tests, airbyte/http providers, kubernetes tests and "
                 "docs should run even if unimportant files were added",
@@ -223,7 +238,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "run-amazon-tests": "false",
                     "run-kubernetes-tests": "true",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "Always",
+                    "parallel-test-types": "Always",
                 },
                 id="Docs should run even if unimportant files were added",
             )
@@ -242,7 +257,8 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "run-amazon-tests": "true",
                     "docs-build": "true",
                     "upgrade-to-newer-dependencies": "true",
-                    "test-types": "API Always CLI Core Other Providers WWW",
+                    "parallel-test-types": "Core Providers[-amazon,google] 
Other Providers[amazon] WWW "
+                    "API Always CLI Providers[google]",
                 },
                 id="Everything should run - including all providers and 
upgrading to "
                 "newer requirements as setup.py changed and all Python 
versions",
@@ -262,7 +278,8 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                     "run-amazon-tests": "true",
                     "docs-build": "true",
                     "upgrade-to-newer-dependencies": "true",
-                    "test-types": "API Always CLI Core Other Providers WWW",
+                    "parallel-test-types": "Core Providers[-amazon,google] 
Other Providers[amazon] WWW "
+                    "API Always CLI Providers[google]",
                 },
                 id="Everything should run and upgrading to newer requirements 
as dependencies change",
             )
@@ -281,8 +298,9 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                 "run-kubernetes-tests": "false",
                 "upgrade-to-newer-dependencies": "false",
                 "run-amazon-tests": "true",
-                "test-types": "Always 
Providers[amazon,apache.hive,cncf.kubernetes,"
-                
"common.sql,exasol,ftp,google,imap,mongo,mysql,postgres,salesforce,ssh]",
+                "parallel-test-types": "Providers[amazon] Always "
+                
"Providers[apache.hive,cncf.kubernetes,common.sql,exasol,ftp,imap,"
+                "mongo,mysql,postgres,salesforce,ssh] Providers[google]",
             },
             id="Providers tests run including amazon tests if amazon provider 
files changed",
         ),
@@ -300,9 +318,9 @@ def assert_outputs_are_printed(expected_outputs: dict[str, 
str], stderr: str):
                 "docs-build": "false",
                 "run-kubernetes-tests": "false",
                 "upgrade-to-newer-dependencies": "false",
-                "test-types": "Always Providers[airbyte,http]",
+                "parallel-test-types": "Always Providers[airbyte,http]",
             },
-            id="Providers tests run including amazon tests if amazon tests 
provider files changed",
+            id="Providers tests tests run without amazon tests if no amazon 
file changed",
         ),
         pytest.param(
             ("airflow/providers/amazon/file.py",),
@@ -318,10 +336,11 @@ def assert_outputs_are_printed(expected_outputs: 
dict[str, str], stderr: str):
                 "docs-build": "true",
                 "run-kubernetes-tests": "false",
                 "upgrade-to-newer-dependencies": "false",
-                "test-types": "Always 
Providers[amazon,apache.hive,cncf.kubernetes,"
-                
"common.sql,exasol,ftp,google,imap,mongo,mysql,postgres,salesforce,ssh]",
+                "parallel-test-types": "Providers[amazon] Always "
+                "Providers[apache.hive,cncf.kubernetes,common.sql,exasol,ftp,"
+                "imap,mongo,mysql,postgres,salesforce,ssh] Providers[google]",
             },
-            id="Providers tests run without amazon tests if no amazon file 
changed",
+            id="Providers tests run including amazon tests if amazon provider 
files changed",
         ),
     ],
 )
@@ -358,7 +377,8 @@ def test_expected_output_pull_request_main(
                     "full-tests-needed": "true",
                     "providers-package-format-exclude": "[]",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "API Always CLI Core Other Providers WWW",
+                    "parallel-test-types": "Core Providers[-amazon,google] 
Other Providers[amazon] WWW "
+                    "API Always CLI Providers[google]",
                 },
                 id="Everything should run including all providers when full 
tests are needed",
             )
@@ -382,7 +402,8 @@ def test_expected_output_pull_request_main(
                     "full-tests-needed": "true",
                     "providers-package-format-exclude": "[]",
                     "upgrade-to-newer-dependencies": "false",
-                    "test-types": "API Always CLI Core Other Providers WWW",
+                    "parallel-test-types": "Core Providers[-amazon,google] 
Other Providers[amazon] WWW "
+                    "API Always CLI Providers[google]",
                 },
                 id="Everything should run including full providers when full "
                 "tests are needed even with different label set as well",
@@ -404,7 +425,8 @@ def test_expected_output_pull_request_main(
                     "full-tests-needed": "true",
                     "upgrade-to-newer-dependencies": "false",
                     "providers-package-format-exclude": "[]",
-                    "test-types": "API Always CLI Core Other Providers WWW",
+                    "parallel-test-types": "Core Providers[-amazon,google] 
Other Providers[amazon] WWW "
+                    "API Always CLI Providers[google]",
                 },
                 id="Everything should run including full providers when"
                 "full tests are needed even if no files are changed",
@@ -426,7 +448,7 @@ def test_expected_output_pull_request_main(
                     "full-tests-needed": "true",
                     "upgrade-to-newer-dependencies": "false",
                     "providers-package-format-exclude": "[]",
-                    "test-types": "API Always CLI Core Other WWW",
+                    "parallel-test-types": "Core Other WWW API Always CLI",
                 },
                 id="Everything should run except Providers when full tests are 
needed for non-main branch",
             )
@@ -465,7 +487,7 @@ def test_expected_output_full_tests_needed(
                 "providers-package-format-exclude": "[{'package-format': 
'sdist'}]",
                 "upgrade-to-newer-dependencies": "false",
                 "skip-provider-tests": "true",
-                "test-types": "",
+                "parallel-test-types": "",
             },
             id="Nothing should run if only non-important files changed",
         ),
@@ -486,7 +508,7 @@ def test_expected_output_full_tests_needed(
                 "run-kubernetes-tests": "true",
                 "upgrade-to-newer-dependencies": "false",
                 "skip-provider-tests": "true",
-                "test-types": "Always",
+                "parallel-test-types": "Always",
             },
             id="No Helm tests, No providers should run if only chart/providers 
changed in non-main",
         ),
@@ -508,7 +530,7 @@ def test_expected_output_full_tests_needed(
                 "run-kubernetes-tests": "true",
                 "upgrade-to-newer-dependencies": "false",
                 "skip-provider-tests": "true",
-                "test-types": "Always CLI",
+                "parallel-test-types": "Always CLI",
             },
             id="Only CLI tests and Kubernetes tests should run if cli/chart 
files changed in non-main branch",
         ),
@@ -529,7 +551,7 @@ def test_expected_output_full_tests_needed(
                 "run-kubernetes-tests": "false",
                 "upgrade-to-newer-dependencies": "false",
                 "skip-provider-tests": "true",
-                "test-types": "API Always CLI Core Other WWW",
+                "parallel-test-types": "Core Other WWW API Always CLI",
             },
             id="All tests except Providers should run if core file changed in 
non-main branch",
         ),
@@ -563,7 +585,7 @@ def test_expected_output_pull_request_v2_3(
                 "docs-build": "false",
                 "upgrade-to-newer-dependencies": "false",
                 "skip-provider-tests": "false",
-                "test-types": "",
+                "parallel-test-types": "",
             },
             id="Nothing should run if only non-important files changed",
         ),
@@ -578,7 +600,7 @@ def test_expected_output_pull_request_v2_3(
                 "docs-build": "true",
                 "upgrade-to-newer-dependencies": "false",
                 "skip-provider-tests": "false",
-                "test-types": "Always",
+                "parallel-test-types": "Always",
             },
             id="Only Always and docs build should run if only system tests 
changed",
         ),
@@ -598,9 +620,12 @@ def test_expected_output_pull_request_v2_3(
                 "run-kubernetes-tests": "true",
                 "upgrade-to-newer-dependencies": "false",
                 "skip-provider-tests": "false",
-                "test-types": "Always CLI",
+                "parallel-test-types": "Providers[amazon] Always CLI "
+                
"Providers[apache.beam,apache.cassandra,cncf.kubernetes,common.sql,facebook,"
+                
"hashicorp,microsoft.azure,microsoft.mssql,mysql,oracle,postgres,presto,"
+                "salesforce,sftp,ssh,trino] Providers[google]",
             },
-            id="CLI tests and Kubernetes tests should run if cli/chart files 
changed",
+            id="CLI tests and Google-related provider tests should run if 
cli/chart files changed",
         ),
         pytest.param(
             (
@@ -617,7 +642,8 @@ def test_expected_output_pull_request_v2_3(
                 "run-kubernetes-tests": "false",
                 "upgrade-to-newer-dependencies": "false",
                 "skip-provider-tests": "false",
-                "test-types": "API Always CLI Core Other Providers WWW",
+                "parallel-test-types": "Core Providers[-amazon,google] Other 
Providers[amazon] WWW "
+                "API Always CLI Providers[google]",
             },
             id="All tests should run if core file changed",
         ),
@@ -652,7 +678,8 @@ def test_expected_output_pull_request_target(
                 "run-tests": "true",
                 "docs-build": "true",
                 "upgrade-to-newer-dependencies": "true",
-                "test-types": "API Always CLI Core Other Providers WWW",
+                "parallel-test-types": "Core Providers[-amazon,google] Other 
Providers[amazon] WWW "
+                "API Always CLI Providers[google]",
             },
             id="All tests run on push even if unimportant file changed",
         ),
@@ -668,7 +695,7 @@ def test_expected_output_pull_request_target(
                 "run-tests": "true",
                 "docs-build": "true",
                 "upgrade-to-newer-dependencies": "true",
-                "test-types": "API Always CLI Core Other WWW",
+                "parallel-test-types": "Core Other WWW API Always CLI",
             },
             id="All tests except Providers and Helm run on push"
             " even if unimportant file changed in non-main branch",
@@ -685,7 +712,8 @@ def test_expected_output_pull_request_target(
                 "run-tests": "true",
                 "docs-build": "true",
                 "upgrade-to-newer-dependencies": "true",
-                "test-types": "API Always CLI Core Other Providers WWW",
+                "parallel-test-types": "Core Providers[-amazon,google] Other 
Providers[amazon] WWW "
+                "API Always CLI Providers[google]",
             },
             id="All tests run on push if core file changed",
         ),
@@ -736,7 +764,8 @@ def 
test_no_commit_provided_trigger_full_build_for_any_event_type(github_event):
             "upgrade-to-newer-dependencies": "true"
             if github_event in [GithubEvents.PUSH, GithubEvents.SCHEDULE]
             else "false",
-            "test-types": "API Always CLI Core Other Providers WWW",
+            "parallel-test-types": "Core Providers[-amazon,google] Other 
Providers[amazon] WWW "
+            "API Always CLI Providers[google]",
         },
         str(stderr),
     )
diff --git a/images/breeze/output-commands-hash.txt 
b/images/breeze/output-commands-hash.txt
index 7a36b71736..de1f4ec2a5 100644
--- a/images/breeze/output-commands-hash.txt
+++ b/images/breeze/output-commands-hash.txt
@@ -60,5 +60,5 @@ stop:e5aa686b4e53707ced4039d8414d5cd6
 testing:docker-compose-tests:b86c044b24138af0659a05ed6331576c
 testing:helm-tests:936cf28fd84ce4ff5113795fdae9624b
 testing:integration-tests:225ddb6243cce5fc64f4824b87adfd98
-testing:tests:86441445a2b521e8d5aee04d74978451
-testing:2d95034763ee699f2e2fc1804f2fd7f0
+testing:tests:b96f54a7e08986e2309af33141099e8d
+testing:8d1f02ebc1119bdf93e027a4f291237f
diff --git a/images/breeze/output_testing_tests.svg 
b/images/breeze/output_testing_tests.svg
index 434b6d43b6..d303079df2 100644
--- a/images/breeze/output_testing_tests.svg
+++ b/images/breeze/output_testing_tests.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 1318.8" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 1294.3999999999999" 
xmlns="http://www.w3.org/2000/svg";>
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -37,13 +37,13 @@
 .breeze-testing-tests-r3 { fill: #d0b344;font-weight: bold }
 .breeze-testing-tests-r4 { fill: #68a0b3;font-weight: bold }
 .breeze-testing-tests-r5 { fill: #868887 }
-.breeze-testing-tests-r6 { fill: #8d7b39 }
-.breeze-testing-tests-r7 { fill: #98a84b;font-weight: bold }
+.breeze-testing-tests-r6 { fill: #98a84b;font-weight: bold }
+.breeze-testing-tests-r7 { fill: #8d7b39 }
     </style>
 
     <defs>
     <clipPath id="breeze-testing-tests-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="1267.8" />
+      <rect x="0" y="0" width="1463.0" height="1243.3999999999999" />
     </clipPath>
     <clipPath id="breeze-testing-tests-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -195,12 +195,9 @@
 <clipPath id="breeze-testing-tests-line-49">
     <rect x="0" y="1197.1" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="breeze-testing-tests-line-50">
-    <rect x="0" y="1221.5" width="1464" height="24.65"/>
-            </clipPath>
     </defs>
 
-    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="1316.8" rx="8"/><text 
class="breeze-testing-tests-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;testing&#160;tests</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="1292.4" rx="8"/><text 
class="breeze-testing-tests-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;testing&#160;tests</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -216,52 +213,51 @@
 </text><text class="breeze-testing-tests-r2" x="12.2" y="93.2" 
textLength="439.2" 
clip-path="url(#breeze-testing-tests-line-3)">Run&#160;the&#160;specified&#160;unit&#160;test&#160;targets.</text><text
 class="breeze-testing-tests-r2" x="1464" y="93.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-3)">
 </text><text class="breeze-testing-tests-r2" x="1464" y="117.6" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-4)">
 </text><text class="breeze-testing-tests-r5" x="0" y="142" textLength="24.4" 
clip-path="url(#breeze-testing-tests-line-5)">╭─</text><text 
class="breeze-testing-tests-r5" x="24.4" y="142" textLength="366" 
clip-path="url(#breeze-testing-tests-line-5)">&#160;Basic&#160;flag&#160;for&#160;tests&#160;command&#160;</text><text
 class="breeze-testing-tests-r5" x="390.4" y="142" textLength="1049.2" 
clip-path="url(#breeze-testing-tests-line-5)">─────────────────────────────────────────────────────
 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="166.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-6)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="166.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-6)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="166.4" textLength="61" 
clip-path="url(#breeze-testing-tests-line-6)">-test</text><text 
class="breeze-testing-tests-r4" x="97.6" y="166.4" textLength="61" 
clip-path="url(#breeze-tes [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="190.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-7)">│</text><text 
class="breeze-testing-tests-r2" x="317.2" y="190.8" textLength="341.6" 
clip-path="url(#breeze-testing-tests-line-7)">should&#160;be&#160;run&#160;-&#160;for&#160;example&#160;</text><text
 class="breeze-testing-tests-r4" x="658.8" y="190.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-7)">-</text><text 
class="breeze-testing-tests-r4" x=" [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="215.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-8)">│</text><text 
class="breeze-testing-tests-r6" x="317.2" y="215.2" textLength="1122.4" 
clip-path="url(#breeze-testing-tests-line-8)">(All&#160;|&#160;API&#160;|&#160;Always&#160;|&#160;CLI&#160;|&#160;Core&#160;|&#160;Other&#160;|&#160;Providers&#160;|&#160;WWW&#160;|&#160;PlainAsserts&#160;|&#160;Postgres&#160;|&#160;MySQL</text><text
 class="breeze-testing-tests-r5 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="239.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-9)">│</text><text 
class="breeze-testing-tests-r6" x="317.2" y="239.6" textLength="1122.4" 
clip-path="url(#breeze-testing-tests-line-9)">|&#160;Quarantine)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="166.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-6)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="166.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-6)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="166.4" textLength="61" 
clip-path="url(#breeze-testing-tests-line-6)">-test</text><text 
class="breeze-testing-tests-r4" x="97.6" y="166.4" textLength="61" 
clip-path="url(#breeze-tes [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="190.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-7)">│</text><text 
class="breeze-testing-tests-r2" x="317.2" y="190.8" textLength="915" 
clip-path="url(#breeze-testing-tests-line-7)">`Providers[airbyte,http]`&#160;or&#160;excluded&#160;from&#160;the&#160;full&#160;test&#160;suite:&#160;`Providers[</text><text
 class="breeze-testing-tests-r6" x="1232.2" y="190.8" textLength="85.4" 
clip-path="url(#breeze-testing-tests-li [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="215.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-8)">│</text><text 
class="breeze-testing-tests-r7" x="317.2" y="215.2" textLength="1122.4" 
clip-path="url(#breeze-testing-tests-line-8)">(All&#160;|&#160;API&#160;|&#160;Always&#160;|&#160;CLI&#160;|&#160;Core&#160;|&#160;Other&#160;|&#160;Providers&#160;|&#160;WWW&#160;|&#160;PlainAsserts&#160;|&#160;Postgres&#160;|&#160;MySQL</text><text
 class="breeze-testing-tests-r5 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="239.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-9)">│</text><text 
class="breeze-testing-tests-r7" x="317.2" y="239.6" textLength="1122.4" 
clip-path="url(#breeze-testing-tests-line-9)">|&#160;Quarantine)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="264" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-10)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="264" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-10)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="264" textLength="61" 
clip-path="url(#breeze-testing-tests-line-10)">-test</text><text 
class="breeze-testing-tests-r4" x="97.6" y="264" textLength="97.6" 
clip-path="url(#breeze-testin [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="288.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-11)">│</text><text 
class="breeze-testing-tests-r6" x="317.2" y="288.4" textLength="988.2" 
clip-path="url(#breeze-testing-tests-line-11)">(INTEGER&#160;RANGE)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="288.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-11)">│</text><text 
class="breeze-testing-tests-r7" x="317.2" y="288.4" textLength="988.2" 
clip-path="url(#breeze-testing-tests-line-11)">(INTEGER&#160;RANGE)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="312.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-12)">│</text><text 
class="breeze-testing-tests-r5" x="317.2" y="312.8" textLength="988.2" 
clip-path="url(#breeze-testing-tests-line-12)">[default:&#160;60;&#160;x&gt;=0]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="337.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-13)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="337.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-13)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="337.2" textLength="97.6" 
clip-path="url(#breeze-testing-tests-line-13)">-collect</text><text 
class="breeze-testing-tests-r4" x="134.2" y="337.2" textLength="61" 
clip-path="url(#b [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="361.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-14)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="361.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-14)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="361.6" textLength="36.6" 
clip-path="url(#breeze-testing-tests-line-14)">-db</text><text 
class="breeze-testing-tests-r4" x="73.2" y="361.6" textLength="73.2" 
clip-path="url(#breez [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="386" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-15)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="386" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-15)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="386" textLength="97.6" 
clip-path="url(#breeze-testing-tests-line-15)">-backend</text><text 
class="breeze-testing-tests-r7" x="268.4" y="386" textLength="24.4" 
clip-path="url(#breeze- [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="410.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-16)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="410.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-16)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="410.4" textLength="85.4" 
clip-path="url(#breeze-testing-tests-line-16)">-python</text><text 
class="breeze-testing-tests-r7" x="268.4" y="410.4" textLength="24.4" 
clip-path="url(# [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="361.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-14)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="361.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-14)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="361.6" textLength="36.6" 
clip-path="url(#breeze-testing-tests-line-14)">-db</text><text 
class="breeze-testing-tests-r4" x="73.2" y="361.6" textLength="73.2" 
clip-path="url(#breez [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="386" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-15)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="386" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-15)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="386" textLength="97.6" 
clip-path="url(#breeze-testing-tests-line-15)">-backend</text><text 
class="breeze-testing-tests-r6" x="268.4" y="386" textLength="24.4" 
clip-path="url(#breeze- [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="410.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-16)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="410.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-16)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="410.4" textLength="85.4" 
clip-path="url(#breeze-testing-tests-line-16)">-python</text><text 
class="breeze-testing-tests-r6" x="268.4" y="410.4" textLength="24.4" 
clip-path="url(# [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="434.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-17)">│</text><text 
class="breeze-testing-tests-r5" x="317.2" y="434.8" textLength="732" 
clip-path="url(#breeze-testing-tests-line-17)">[default:&#160;3.7]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="459.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-18)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="459.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-18)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="459.2" textLength="109.8" 
clip-path="url(#breeze-testing-tests-line-18)">-postgres</text><text 
class="breeze-testing-tests-r4" x="146.4" y="459.2" textLength="97.6" 
clip-path="ur [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="483.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-19)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="483.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-19)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="483.6" textLength="73.2" 
clip-path="url(#breeze-testing-tests-line-19)">-mysql</text><text 
class="breeze-testing-tests-r4" x="109.8" y="483.6" textLength="97.6" 
clip-path="url(#b [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="508" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-20)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="508" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-20)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="508" textLength="73.2" 
clip-path="url(#breeze-testing-tests-line-20)">-mssql</text><text 
class="breeze-testing-tests-r4" x="109.8" y="508" textLength="97.6" 
clip-path="url(#breeze-te [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="459.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-18)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="459.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-18)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="459.2" textLength="109.8" 
clip-path="url(#breeze-testing-tests-line-18)">-postgres</text><text 
class="breeze-testing-tests-r4" x="146.4" y="459.2" textLength="97.6" 
clip-path="ur [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="483.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-19)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="483.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-19)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="483.6" textLength="73.2" 
clip-path="url(#breeze-testing-tests-line-19)">-mysql</text><text 
class="breeze-testing-tests-r4" x="109.8" y="483.6" textLength="97.6" 
clip-path="url(#b [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="508" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-20)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="508" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-20)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="508" textLength="73.2" 
clip-path="url(#breeze-testing-tests-line-20)">-mssql</text><text 
class="breeze-testing-tests-r4" x="109.8" y="508" textLength="97.6" 
clip-path="url(#breeze-te [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="532.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-21)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="532.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-21)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="532.4" textLength="146.4" 
clip-path="url(#breeze-testing-tests-line-21)">-integration</text><text 
class="breeze-testing-tests-r2" x="317.2" y="532.4" textLength="1122.4" 
clip-pat [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="556.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-22)">│</text><text 
class="breeze-testing-tests-r6" x="317.2" y="556.8" textLength="1122.4" 
clip-path="url(#breeze-testing-tests-line-22)">(all&#160;|&#160;all-testable&#160;|&#160;cassandra&#160;|&#160;celery&#160;|&#160;kerberos&#160;|&#160;mongo&#160;|&#160;otel&#160;|&#160;pinot&#160;|&#160;statsd&#160;|&#160;statsd</text><text
 class="breeze-testing-tests-r5" x="145 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="581.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-23)">│</text><text 
class="breeze-testing-tests-r6" x="317.2" y="581.2" textLength="1122.4" 
clip-path="url(#breeze-testing-tests-line-23)">|&#160;trino)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="556.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-22)">│</text><text 
class="breeze-testing-tests-r7" x="317.2" y="556.8" textLength="1122.4" 
clip-path="url(#breeze-testing-tests-line-22)">(all&#160;|&#160;all-testable&#160;|&#160;cassandra&#160;|&#160;celery&#160;|&#160;kerberos&#160;|&#160;mongo&#160;|&#160;otel&#160;|&#160;pinot&#160;|&#160;statsd&#160;|&#160;statsd</text><text
 class="breeze-testing-tests-r5" x="145 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="581.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-23)">│</text><text 
class="breeze-testing-tests-r7" x="317.2" y="581.2" textLength="1122.4" 
clip-path="url(#breeze-testing-tests-line-23)">|&#160;trino)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="605.6" textLength="1464" 
clip-path="url(#breeze-testing-tests-line-24)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-testing-tests-r2" x="1464" y="605.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-24)">
 </text><text class="breeze-testing-tests-r5" x="0" y="630" textLength="24.4" 
clip-path="url(#breeze-testing-tests-line-25)">╭─</text><text 
class="breeze-testing-tests-r5" x="24.4" y="630" textLength="439.2" 
clip-path="url(#breeze-testing-tests-line-25)">&#160;Options&#160;for&#160;parallel&#160;test&#160;commands&#160;</text><text
 class="breeze-testing-tests-r5" x="463.6" y="630" textLength="976" 
clip-path="url(#breeze-testing-tests-line-25)">─────────────────────────────────────────────
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="654.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-26)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="654.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-26)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="654.4" textLength="48.8" 
clip-path="url(#breeze-testing-tests-line-26)">-run</text><text 
class="breeze-testing-tests-r4" x="85.4" y="654.4" textLength="146.4" 
clip-path="url(#bre [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="678.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-27)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="678.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-27)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="678.8" textLength="146.4" 
clip-path="url(#breeze-testing-tests-line-27)">-parallelism</text><text 
class="breeze-testing-tests-r2" x="378.2" y="678.8" textLength="915" 
clip-path=" [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="703.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-28)">│</text><text 
class="breeze-testing-tests-r6" x="378.2" y="703.2" textLength="915" 
clip-path="url(#breeze-testing-tests-line-28)">(INTEGER&#160;RANGE)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="703.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-28)">│</text><text 
class="breeze-testing-tests-r7" x="378.2" y="703.2" textLength="915" 
clip-path="url(#breeze-testing-tests-line-28)">(INTEGER&#160;RANGE)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="727.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-29)">│</text><text 
class="breeze-testing-tests-r5" x="378.2" y="727.6" textLength="915" 
clip-path="url(#breeze-testing-tests-line-29)">[default:&#160;4;&#160;1&lt;=x&lt;=8]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="752" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-30)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="752" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-30)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="752" textLength="109.8" 
clip-path="url(#breeze-testing-tests-line-30)">-parallel</text><text 
class="breeze-testing-tests-r4" x="146.4" y="752" textLength="134.2" 
clip-path="url(#bree [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="752" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-30)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="752" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-30)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="752" textLength="109.8" 
clip-path="url(#breeze-testing-tests-line-30)">-parallel</text><text 
class="breeze-testing-tests-r4" x="146.4" y="752" textLength="134.2" 
clip-path="url(#bree [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="776.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-31)">│</text><text 
class="breeze-testing-tests-r5" x="378.2" y="776.4" textLength="780.8" 
clip-path="url(#breeze-testing-tests-line-31)">[default:&#160;API&#160;Always&#160;CLI&#160;Core&#160;Other&#160;Providers&#160;WWW&#160;PlainAsserts]&#160;</text><text
 class="breeze-testing-tests-r5" x="1451.8" y="776.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="800.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-32)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="800.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-32)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="800.8" textLength="61" 
clip-path="url(#breeze-testing-tests-line-32)">-skip</text><text 
class="breeze-testing-tests-r4" x="97.6" y="800.8" textLength="97.6" 
clip-path="url(#breez [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="825.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-33)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="825.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-33)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="825.2" textLength="73.2" 
clip-path="url(#breeze-testing-tests-line-33)">-debug</text><text 
class="breeze-testing-tests-r4" x="109.8" y="825.2" textLength="122" 
clip-path="url(#br [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="849.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-34)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="849.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-34)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="849.6" textLength="97.6" 
clip-path="url(#breeze-testing-tests-line-34)">-include</text><text 
class="breeze-testing-tests-r4" x="134.2" y="849.6" textLength="195.2" 
clip-path="url [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="874" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-35)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="874" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-35)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="874" textLength="61" 
clip-path="url(#breeze-testing-tests-line-35)">-full</text><text 
class="breeze-testing-tests-r4" x="97.6" y="874" textLength="158.6" 
clip-path="url(#breeze-testi [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="898.4" textLength="1464" 
clip-path="url(#breeze-testing-tests-line-36)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-testing-tests-r2" x="1464" y="898.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-36)">
-</text><text class="breeze-testing-tests-r5" x="0" y="922.8" textLength="24.4" 
clip-path="url(#breeze-testing-tests-line-37)">╭─</text><text 
class="breeze-testing-tests-r5" x="24.4" y="922.8" textLength="402.6" 
clip-path="url(#breeze-testing-tests-line-37)">&#160;Advanced&#160;flag&#160;for&#160;tests&#160;command&#160;</text><text
 class="breeze-testing-tests-r5" x="427" y="922.8" textLength="1012.6" 
clip-path="url(#breeze-testing-tests-line-37)">─────────────────────────────────────────
 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="947.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-38)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="947.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-38)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="947.2" textLength="73.2" 
clip-path="url(#breeze-testing-tests-line-38)">-image</text><text 
class="breeze-testing-tests-r4" x="109.8" y="947.2" textLength="48.8" 
clip-path="url(#b [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="971.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-39)">│</text><text 
class="breeze-testing-tests-r5" x="353.8" y="971.6" textLength="963.8" 
clip-path="url(#breeze-testing-tests-line-39)">[default:&#160;latest]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="996" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-40)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="996" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-40)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="996" textLength="73.2" 
clip-path="url(#breeze-testing-tests-line-40)">-mount</text><text 
class="breeze-testing-tests-r4" x="109.8" y="996" textLength="97.6" 
clip-path="url(#breeze-te [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="1020.4" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-41)">│</text><text 
class="breeze-testing-tests-r2" x="353.8" y="1020.4" textLength="1085.8" 
clip-path="url(#breeze-testing-tests-line-41)">selected).&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="1044.8" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-42)">│</text><text 
class="breeze-testing-tests-r6" x="353.8" y="1044.8" textLength="1085.8" 
clip-path="url(#breeze-testing-tests-line-42)">(selected&#160;|&#160;all&#160;|&#160;skip&#160;|&#160;remove)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="1069.2" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-43)">│</text><text 
class="breeze-testing-tests-r5" x="353.8" y="1069.2" textLength="1085.8" 
clip-path="url(#breeze-testing-tests-line-43)">[default:&#160;selected]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="1093.6" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-44)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="1093.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-44)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="1093.6" textLength="97.6" 
clip-path="url(#breeze-testing-tests-line-44)">-upgrade</text><text 
class="breeze-testing-tests-r4" x="134.2" y="1093.6" textLength="61" 
clip-path="ur [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="1118" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-45)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="1118" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-45)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="1118" textLength="85.4" 
clip-path="url(#breeze-testing-tests-line-45)">-remove</text><text 
class="breeze-testing-tests-r4" x="122" y="1118" textLength="158.6" 
clip-path="url(#breez [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="1142.4" 
textLength="1464" 
clip-path="url(#breeze-testing-tests-line-46)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-testing-tests-r2" x="1464" y="1142.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-46)">
-</text><text class="breeze-testing-tests-r5" x="0" y="1166.8" 
textLength="24.4" clip-path="url(#breeze-testing-tests-line-47)">╭─</text><text 
class="breeze-testing-tests-r5" x="24.4" y="1166.8" textLength="195.2" 
clip-path="url(#breeze-testing-tests-line-47)">&#160;Common&#160;options&#160;</text><text
 class="breeze-testing-tests-r5" x="219.6" y="1166.8" textLength="1220" 
clip-path="url(#breeze-testing-tests-line-47)">──────────────────────────────────────────────────────────────────────
 [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="1191.2" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-48)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="1191.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-48)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="1191.2" textLength="97.6" 
clip-path="url(#breeze-testing-tests-line-48)">-verbose</text><text 
class="breeze-testing-tests-r7" x="158.6" y="1191.2" textLength="24.4" 
clip-path=" [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="1215.6" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-49)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="1215.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-49)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="1215.6" textLength="48.8" 
clip-path="url(#breeze-testing-tests-line-49)">-dry</text><text 
class="breeze-testing-tests-r4" x="85.4" y="1215.6" textLength="48.8" 
clip-path="url(# [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="1240" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-50)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="1240" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-50)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="1240" textLength="61" 
clip-path="url(#breeze-testing-tests-line-50)">-help</text><text 
class="breeze-testing-tests-r7" x="158.6" y="1240" textLength="24.4" 
clip-path="url(#breeze-t [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="1264.4" 
textLength="1464" 
clip-path="url(#breeze-testing-tests-line-51)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-testing-tests-r2" x="1464" y="1264.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-51)">
+</text><text class="breeze-testing-tests-r5" x="0" y="874" textLength="1464" 
clip-path="url(#breeze-testing-tests-line-35)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-testing-tests-r2" x="1464" y="874" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-35)">
+</text><text class="breeze-testing-tests-r5" x="0" y="898.4" textLength="24.4" 
clip-path="url(#breeze-testing-tests-line-36)">╭─</text><text 
class="breeze-testing-tests-r5" x="24.4" y="898.4" textLength="402.6" 
clip-path="url(#breeze-testing-tests-line-36)">&#160;Advanced&#160;flag&#160;for&#160;tests&#160;command&#160;</text><text
 class="breeze-testing-tests-r5" x="427" y="898.4" textLength="1012.6" 
clip-path="url(#breeze-testing-tests-line-36)">─────────────────────────────────────────
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="922.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-37)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="922.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-37)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="922.8" textLength="73.2" 
clip-path="url(#breeze-testing-tests-line-37)">-image</text><text 
class="breeze-testing-tests-r4" x="109.8" y="922.8" textLength="48.8" 
clip-path="url(#b [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="947.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-38)">│</text><text 
class="breeze-testing-tests-r5" x="353.8" y="947.2" textLength="963.8" 
clip-path="url(#breeze-testing-tests-line-38)">[default:&#160;latest]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="971.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-39)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="971.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-39)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="971.6" textLength="73.2" 
clip-path="url(#breeze-testing-tests-line-39)">-mount</text><text 
class="breeze-testing-tests-r4" x="109.8" y="971.6" textLength="97.6" 
clip-path="url(#b [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="996" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-40)">│</text><text 
class="breeze-testing-tests-r2" x="353.8" y="996" textLength="1085.8" 
clip-path="url(#breeze-testing-tests-line-40)">selected).&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="1020.4" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-41)">│</text><text 
class="breeze-testing-tests-r7" x="353.8" y="1020.4" textLength="1085.8" 
clip-path="url(#breeze-testing-tests-line-41)">(selected&#160;|&#160;all&#160;|&#160;skip&#160;|&#160;remove)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="1044.8" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-42)">│</text><text 
class="breeze-testing-tests-r5" x="353.8" y="1044.8" textLength="1085.8" 
clip-path="url(#breeze-testing-tests-line-42)">[default:&#160;selected]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="1069.2" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-43)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="1069.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-43)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="1069.2" textLength="97.6" 
clip-path="url(#breeze-testing-tests-line-43)">-upgrade</text><text 
class="breeze-testing-tests-r4" x="134.2" y="1069.2" textLength="61" 
clip-path="ur [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="1093.6" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-44)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="1093.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-44)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="1093.6" textLength="85.4" 
clip-path="url(#breeze-testing-tests-line-44)">-remove</text><text 
class="breeze-testing-tests-r4" x="122" y="1093.6" textLength="158.6" 
clip-path="ur [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="1118" textLength="1464" 
clip-path="url(#breeze-testing-tests-line-45)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-testing-tests-r2" x="1464" y="1118" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-45)">
+</text><text class="breeze-testing-tests-r5" x="0" y="1142.4" 
textLength="24.4" clip-path="url(#breeze-testing-tests-line-46)">╭─</text><text 
class="breeze-testing-tests-r5" x="24.4" y="1142.4" textLength="195.2" 
clip-path="url(#breeze-testing-tests-line-46)">&#160;Common&#160;options&#160;</text><text
 class="breeze-testing-tests-r5" x="219.6" y="1142.4" textLength="1220" 
clip-path="url(#breeze-testing-tests-line-46)">──────────────────────────────────────────────────────────────────────
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="1166.8" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-47)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="1166.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-47)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="1166.8" textLength="97.6" 
clip-path="url(#breeze-testing-tests-line-47)">-verbose</text><text 
class="breeze-testing-tests-r6" x="158.6" y="1166.8" textLength="24.4" 
clip-path=" [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="1191.2" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-48)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="1191.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-48)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="1191.2" textLength="48.8" 
clip-path="url(#breeze-testing-tests-line-48)">-dry</text><text 
class="breeze-testing-tests-r4" x="85.4" y="1191.2" textLength="48.8" 
clip-path="url(# [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="1215.6" 
textLength="12.2" clip-path="url(#breeze-testing-tests-line-49)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="1215.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-49)">-</text><text 
class="breeze-testing-tests-r4" x="36.6" y="1215.6" textLength="61" 
clip-path="url(#breeze-testing-tests-line-49)">-help</text><text 
class="breeze-testing-tests-r6" x="158.6" y="1215.6" textLength="24.4" 
clip-path="url(# [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="1240" textLength="1464" 
clip-path="url(#breeze-testing-tests-line-50)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-testing-tests-r2" x="1464" y="1240" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-50)">
 </text>
     </g>
     </g>
diff --git a/scripts/docker/entrypoint_ci.sh b/scripts/docker/entrypoint_ci.sh
index 642b6f002c..9acd01754d 100755
--- a/scripts/docker/entrypoint_ci.sh
+++ b/scripts/docker/entrypoint_ci.sh
@@ -478,6 +478,19 @@ else
             ${TEST_TYPE} == "Postgres" || ${TEST_TYPE} == "MySQL" || \
             ${TEST_TYPE} == "Long" ]]; then
         SELECTED_TESTS=("${ALL_TESTS[@]}")
+    elif [[ ${TEST_TYPE} =~ Providers\[\-(.*)\] ]]; then
+        # When providers start with `-` it means that we should run all 
provider tests except those
+        SELECTED_TESTS=("${PROVIDERS_TESTS[@]}")
+        for provider in ${BASH_REMATCH[1]//,/ }
+        do
+            providers_dir="tests/providers/${provider//./\/}"
+            if [[ -d ${providers_dir} ]]; then
+                echo "${COLOR_BLUE}Ignoring ${providers_dir} as it has been 
deselected.${COLOR_RESET}"
+                
EXTRA_PYTEST_ARGS+=("--ignore=tests/providers/${provider//./\/}")
+            else
+                echo "${COLOR_YELLOW}Skipping ${providers_dir} as the 
directory does not exist.${COLOR_RESET}"
+            fi
+        done
     elif [[ ${TEST_TYPE} =~ Providers\[(.*)\] ]]; then
         SELECTED_TESTS=()
         for provider in ${BASH_REMATCH[1]//,/ }

Reply via email to