You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by di...@apache.org on 2020/10/11 14:41:36 UTC

[airflow] branch master updated: Split tests to more sub-types (#11402)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 5bc5994  	Split tests to more sub-types (#11402)
5bc5994 is described below

commit 5bc5994c2c1a8f73a644e29e98d3d132c6097ab2
Author: Jarek Potiuk <ja...@polidea.com>
AuthorDate: Sun Oct 11 16:40:31 2020 +0200

    	Split tests to more sub-types (#11402)
    
    We seem to have a problem with running all tests at once - most
    likely due to some resource problems in our CI, therefore it makes
    sense to split the tests into more batches. This is not yet full
    implementation of selective tests but it is going in this direction
    by splitting to Core/Providers/API/CLI tests. The full selective
    tests approach will be implemented as part of #10507 issue.
    
    This split is possible thanks to #10422 which moved building image
    to a separate workflow - this way each image is only built once
    and it is uploaded to a shared registry, where it is quickly
    downloaded from rather than built by all the jobs separately - this
    way we can have many more jobs as there is very little per-job
    overhead before the tests start runnning.
---
 .github/workflows/ci.yml                           |  27 +++-
 BREEZE.rst                                         |  17 ++-
 TESTING.rst                                        |  57 +++++++-
 breeze                                             |  46 ++++++-
 breeze-complete                                    |  12 +-
 scripts/ci/docker-compose/base.yml                 |   7 +-
 scripts/ci/libraries/_docker.env                   |   4 +
 scripts/ci/libraries/_initialization.sh            |  23 ++--
 scripts/ci/libraries/_parameters.sh                |  28 ++--
 scripts/ci/libraries/_push_pull_remove_images.sh   |  14 ++
 scripts/ci/testing/ci_run_airflow_testing.sh       |   9 +-
 scripts/in_container/entrypoint_ci.sh              | 143 +++++++++++++++------
 scripts/in_container/run_ci_tests.sh               |  57 ++++++--
 tests/bats/test_breeze_complete.bats               |   8 ++
 tests/cli/commands/test_connection_command.py      |  22 +++-
 tests/{ => core}/test_config_templates.py          |   0
 tests/{ => core}/test_configuration.py             |   0
 tests/{ => core}/test_core.py                      |   0
 tests/{ => core}/test_core_to_contrib.py           |   0
 tests/{ => core}/test_example_dags.py              |   0
 tests/{ => core}/test_example_dags_system.py       |   0
 .../test_impersonation_tests.py}                   |   0
 tests/{ => core}/test_local_settings.py            |   0
 tests/{ => core}/test_logging_config.py            |   0
 tests/{ => core}/test_project_structure.py         |   4 +-
 tests/{ => core}/test_sentry.py                    |   0
 tests/{ => core}/test_sqlalchemy_config.py         |   3 +-
 tests/{ => core}/test_stats.py                     |  18 +--
 tests/jobs/test_backfill_job.py                    |   1 +
 tests/jobs/test_local_task_job.py                  |   3 +-
 tests/jobs/test_scheduler_job.py                   |   2 +-
 tests/serialization/test_dag_serialization.py      |   2 +
 .../task/task_runner/test_standard_task_runner.py  |   6 +-
 tests/utils/test_dag_processing.py                 |   2 +-
 tests/www/test_views.py                            |   5 +-
 35 files changed, 401 insertions(+), 119 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index cb24ca5..b5d1023 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -43,7 +43,7 @@ env:
   GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
   GITHUB_REGISTRY_PULL_IMAGE_TAG: "${{ github.run_id }}"
   GITHUB_REGISTRY_PUSH_IMAGE_TAG: "latest"
-  TEST_TYPES: '["Core", "Integration", "Heisentests"]'
+  TEST_TYPES: '["Core", "Providers", "API", "CLI", "Integration", "Other", "WWW", "Heisentests"]'
 
   # You can switch between building the image in "Build Images" workflow or building them in CI workflow
   # Separately for each job.
@@ -79,7 +79,7 @@ jobs:
       postgresVersions: ${{ steps.versions.outputs.postgres-versions }}
       defaultPostgresVersion: ${{ steps.versions.outputs.default-postgres-version }}
       mysqlVersions: ${{ steps.versions.outputs.mysql-versions }}
-      defaultMysqlVersion: ${{ steps.versions.outputs.default-mysql-version }}
+      defaultMySQLVersion: ${{ steps.versions.outputs.default-mysql-version }}
       helmVersions: ${{ steps.versions.outputs.helm-versions }}
       defaultHelmVersion: ${{ steps.versions.outputs.default-helm-version }}
       kindVersions: ${{ steps.versions.outputs.kind-versions }}
@@ -369,6 +369,12 @@ jobs:
         postgres-version: ${{ fromJson(needs.build-info.outputs.postgresVersions) }}
         test-type: ${{ fromJson(needs.build-info.outputs.testTypes) }}
         exclude: ${{ fromJson(needs.build-info.outputs.postgresExclude) }}
+        # Additionally include all postgres-only tests but only for default versions
+        # in case the regular tests are excluded in the future
+        include:
+          - python_version: ${{ needs.build-info.outputs.defaultPythonVersion }}
+            postgres-version: ${{ needs.build-info.outputs.defaultPostgresVersion }}
+            test-type: "Postgres"
       fail-fast: false
     env:
       BACKEND: postgres
@@ -416,6 +422,12 @@ jobs:
         mysql-version: ${{ fromJson(needs.build-info.outputs.mysqlVersions) }}
         test-type: ${{ fromJson(needs.build-info.outputs.testTypes) }}
         exclude: ${{ fromJson(needs.build-info.outputs.mysqlExclude) }}
+        # Additionally include all mysql-only tests but only for default versions
+        # in case the regular tests are excluded in the future
+        include:
+          - python_version: ${{ needs.build-info.outputs.defaultPythonVersion }}
+            postgres-version: ${{ needs.build-info.outputs.defaultMySQLVersion }}
+            test-type: "MySQL"
       fail-fast: false
     env:
       BACKEND: mysql
@@ -500,9 +512,16 @@ jobs:
     runs-on: ubuntu-latest
     continue-on-error: true
     needs: [build-info, trigger-tests, ci-images]
+    strategy:
+      matrix:
+        include:
+          - backend: mysql
+          - backend: postgres
+          - backend: sqlite
     env:
-      PYTHON_MAJOR_MINOR_VERSION: ${{needs.build-info.outputs.defaultPythonVersion}}
-      BACKEND: postgres
+      BACKEND: ${{ matrix.backend }}
+      PYTHON_MAJOR_MINOR_VERSION: ${{ needs.build-info.outputs.defaultPythonVersion }}
+      MYSQL_VERSION: ${{needs.build-info.outputs.defaultMySQLVersion}}
       POSTGRES_VERSION: ${{needs.build-info.outputs.defaultPostgresVersion}}
       RUN_TESTS: true
       TEST_TYPE: Quarantined
diff --git a/BREEZE.rst b/BREEZE.rst
index 5b75b14..819057b 100644
--- a/BREEZE.rst
+++ b/BREEZE.rst
@@ -1990,7 +1990,12 @@ This is the current syntax for  `./breeze <./breeze>`_:
 
   Flags:
 
-  Run 'breeze flags' to see all applicable flags.
+  --test-type TEST_TYPE
+          Type of the test to run. One of:
+
+                 All,Core,Providers,API,CLI,Integration,Other,WWW,Heisentests,Postgres,MySQL
+
+          Default: All
 
 
   ####################################################################################################
@@ -2339,6 +2344,16 @@ This is the current syntax for  `./breeze <./breeze>`_:
           Default: latest.
 
   ****************************************************************************************************
+   Flags for running tests
+
+  --test-type TEST_TYPE
+          Type of the test to run. One of:
+
+                 All,Core,Providers,API,CLI,Integration,Other,WWW,Heisentests,Postgres,MySQL
+
+          Default: All
+
+  ****************************************************************************************************
    Flags for generation of the backport packages
 
   -S, --version-suffix-for-pypi SUFFIX
diff --git a/TESTING.rst b/TESTING.rst
index 7b3386a..831d467 100644
--- a/TESTING.rst
+++ b/TESTING.rst
@@ -131,23 +131,70 @@ Running Tests for a Specified Target Using Breeze from the Host
 ---------------------------------------------------------------
 
 If you wish to only run tests and not to drop into shell, apply the
-``tests`` command. You can add extra targets and pytest flags after the ``tests`` command.
+``tests`` command. You can add extra targets and pytest flags after the ``--`` command. Note that
+often you want to run the tests with a clean/reset db, so usually you want to add ``--db-reset`` flag
+to breeze.
 
 .. code-block:: bash
 
-     ./breeze tests tests/hooks/test_druid_hook.py tests/tests_core.py --logging-level=DEBUG
+     ./breeze tests tests/hooks/test_druid_hook.py tests/tests_core.py --db-reset -- --logging-level=DEBUG
 
-You can run the whole test suite with a 'tests' test target:
+You can run the whole test suite without adding the test target:
 
 .. code-block:: bash
 
-    ./breeze tests tests
+    ./breeze tests --db-reset
 
 You can also specify individual tests or a group of tests:
 
 .. code-block:: bash
 
-    ./breeze tests tests/test_core.py::TestCore
+    ./breeze tests --db-reset tests/test_core.py::TestCore
+
+
+Running Tests of a specified type from the Host
+-----------------------------------------------
+
+You can also run tests for a specific test type. For the stability and performance point of view
+we separated tests to different test types so that they can be run separately.
+
+You can select the test type by adding ``--test-type TEST_TYPE`` before the test command. There are two
+kinds of test types:
+
+* Per-directories types are added to select subset of the tests based on sub-directories in ``tests`` folder.
+  Example test types there - Core, Providers, CLI. The only action that happens when you choose the right
+  test folders are pre-selected. For those types of tests it is only useful to choose the test type
+  when you do not specify test to run.
+
+Runs all core tests:
+
+.. code-block:: bash
+
+     ./breeze --test-type Core  --db-reset tests
+
+Runs all provider tests:
+
+.. code-block:: bash
+
+     ./breeze --test-type Providers --db-reset tests
+
+* Special kinds of tests - Integration, Heisentests, Quarantined, Postgres, MySQL which are marked with pytest
+  marks and for those you need to select the type using test-type switch. If you want to run such tests
+  using breeze, you need to pass appropriate ``--test-type`` otherwise the test will be skipped.
+  Similarly to the per-directory tests if you do not specify the test or tests to run,
+  all tests of a given type are run
+
+Run quarantined test_task_command.py test:
+
+.. code-block:: bash
+
+     ./breeze --test-type Quarantined tests tests/cli/commands/test_task_command.py --db-reset
+
+Run all Quarantined tests:
+
+.. code-block:: bash
+
+     ./breeze --test-type Quarantined tests --db-reset
 
 
 Airflow Integration Tests
diff --git a/breeze b/breeze
index 77afb0d..fff8538 100755
--- a/breeze
+++ b/breeze
@@ -1072,6 +1072,7 @@ function breeze::parse_arguments() {
             export SKIP_BUILDING_PROD_IMAGE="true"
             export MOUNT_LOCAL_SOURCES="false"
             export SKIP_CHECK_REMOTE_IMAGE="true"
+            export FAIL_ON_GITHUB_DOCKER_PULL_ERROR="true"
             shift 2
             ;;
         --init-script)
@@ -1128,6 +1129,12 @@ function breeze::parse_arguments() {
             echo
             shift
             ;;
+        --test-type)
+            export TEST_TYPE="${2}"
+            echo "Selected test type: ${TEST_TYPE}"
+            echo
+            shift 2
+            ;;
         --)
             shift
             break
@@ -1288,12 +1295,8 @@ function breeze::parse_arguments() {
             ;;
         tests)
             last_subcommand="${1}"
-            if [[ $# -lt 2 ]]; then
-                run_help="true"
-            else
-                shift
-            fi
             command_to_run="run_tests"
+            shift
             ;;
         toggle-suppress-cheatsheet)
             last_subcommand="${1}"
@@ -1437,6 +1440,11 @@ function breeze::prepare_formatted_versions() {
     FORMATTED_DEFAULT_PROD_EXTRAS=$(echo "${DEFAULT_PROD_EXTRAS=}" |
         tr ',' ' ' | fold -w "${indented_screen_width}" -s | sed "s/ /,/g; s/^/${list_prefix}/")
     readonly FORMATTED_DEFAULT_PROD_EXTRAS
+
+    FORMATTED_TEST_TYPES=$(echo "${_breeze_allowed_test_types=""}" |
+        tr ',' ' ' | fold -w "${indented_screen_width}" -s | sed "s/ /,/g; s/^/${list_prefix}/")
+    readonly FORMATTED_TEST_TYPES
+
 }
 
 #######################################################################################################
@@ -1835,7 +1843,7 @@ ${CMDNAME} tests [FLAGS] [TEST_TARGET ..] [-- <EXTRA_ARGS>]
       '${CMDNAME} tests tests
 
 Flags:
-$(breeze::flag_footer)
+$(breeze::flag_tests)
 "
     readonly DETAILED_USAGE_TESTS
     export DETAILED_USAGE_TOGGLE_SUPPRESS_CHEATSHEET="
@@ -2477,6 +2485,25 @@ function breeze::flag_start_airflow() {
 "
 }
 
+#####################################################################################################
+#
+# Prints flags that control tests
+#
+# Outputs:
+#    Flag information.
+#######################################################################################################
+function breeze::flag_tests() {
+    echo "
+--test-type TEST_TYPE
+        Type of the test to run. One of:
+
+${FORMATTED_TEST_TYPES}
+
+        Default: ${_breeze_default_test_type:=}
+
+"
+}
+
 #######################################################################################################
 #
 # Prints all flags
@@ -2539,6 +2566,10 @@ $(breeze::print_star_line)
 $(breeze::flag_pull_push_docker_images)
 
 $(breeze::print_star_line)
+ Flags for running tests
+$(breeze::flag_tests)
+
+$(breeze::print_star_line)
  Flags for generation of the backport packages
 $(breeze::flag_version_suffix)
 
@@ -2698,6 +2729,7 @@ function breeze::check_and_save_all_params() {
         fi
     fi
 
+
     parameters::check_and_save_allowed_param "BACKEND" "backend" "--backend"
     parameters::check_and_save_allowed_param "KUBERNETES_MODE" "Kubernetes mode" "--kubernetes-mode"
     parameters::check_and_save_allowed_param "KUBERNETES_VERSION" "Kubernetes version" "--kubernetes-version"
@@ -2706,6 +2738,8 @@ function breeze::check_and_save_all_params() {
     parameters::check_and_save_allowed_param "POSTGRES_VERSION" "Postgres version" "--postgres-version"
     parameters::check_and_save_allowed_param "MYSQL_VERSION" "Mysql version" "--mysql-version"
 
+    parameters::check_allowed_param TEST_TYPE "Type of tests" "--test-type"
+
     # Can't verify those - they can be anything, so let's just save them
     parameters::save_to_file DOCKERHUB_USER
     parameters::save_to_file DOCKERHUB_REPO
diff --git a/breeze-complete b/breeze-complete
index 81dc223..78d598b 100644
--- a/breeze-complete
+++ b/breeze-complete
@@ -33,6 +33,7 @@ _breeze_allowed_kind_versions="v0.8.0"
 _breeze_allowed_mysql_versions="5.7 8"
 _breeze_allowed_postgres_versions="9.6 10"
 _breeze_allowed_kind_operations="start stop restart status deploy test shell"
+_breeze_allowed_test_types="All Core Providers API CLI Integration Other WWW Heisentests Postgres MySQL"
 
 # shellcheck disable=SC2034
 {
@@ -44,6 +45,7 @@ _breeze_allowed_kind_operations="start stop restart status deploy test shell"
     _breeze_default_kind_version=$(echo "${_breeze_allowed_kind_versions}" | awk '{print $1}')
     _breeze_default_postgres_version=$(echo "${_breeze_allowed_postgres_versions}" | awk '{print $1}')
     _breeze_default_mysql_version=$(echo "${_breeze_allowed_mysql_versions}" | awk '{print $1}')
+    _breeze_default_test_type=$(echo "${_breeze_allowed_test_types}" | awk '{print $1}')
 }
 
 _breeze_allowed_install_airflow_versions=$(cat <<-EOF
@@ -156,6 +158,7 @@ dev-apt-deps: additional-dev-apt-deps: dev-apt-command: additional-dev-apt-comma
 runtime-apt-deps: additional-runtime-apt-deps: runtime-apt-command: additional-runtime-apt-command: additional-runtime-apt-env:
 load-default-connections load-example-dags
 install-wheels no-rbac-ui
+test-type:
 "
 
 _breeze_commands="
@@ -180,7 +183,8 @@ kind-cluster
 prepare-backport-readme
 prepare-backport-packages
 static-check
-tests"
+tests
+"
 
 _breeze_help_commands="
 flags
@@ -265,6 +269,12 @@ function breeze_complete::get_known_values_breeze() {
     kind-cluster)
         _breeze_known_values="${_breeze_allowed_kind_operations}"
         ;;
+    tests)
+        _breeze_known_values="$(find tests -name '*.py')"
+        ;;
+    --test-type)
+        _breeze_known_values="${_breeze_allowed_test_types}"
+        ;;
     *)
         _breeze_known_values=""
         ;;
diff --git a/scripts/ci/docker-compose/base.yml b/scripts/ci/docker-compose/base.yml
index f89aefd..8a0781e 100644
--- a/scripts/ci/docker-compose/base.yml
+++ b/scripts/ci/docker-compose/base.yml
@@ -39,9 +39,7 @@ services:
       - ENABLE_KIND_CLUSTER
       - ENABLED_INTEGRATIONS
       - RUN_INTEGRATION_TESTS
-      - ONLY_RUN_LONG_RUNNING_TESTS
-      - ONLY_RUN_QUARANTINED_TESTS
-      - ONLY_RUN_HEISEN_TESTS
+      - TEST_TYPE
       - GITHUB_TOKEN
       - GITHUB_REPOSITORY
       - ISSUE_ID
@@ -64,6 +62,9 @@ services:
       - HOST_OS
       - PYTHONDONTWRITEBYTECODE
       - INIT_SCRIPT_FILE
+      - GITHUB_REGISTRY_PULL_IMAGE_TAG
+      - POSTGRES_VERSION
+      - MYSQL_VERSION
     volumes:
       # Pass docker to inside of the container so that Kind and Moto tests can use it.
       - /var/run/docker.sock:/var/run/docker.sock
diff --git a/scripts/ci/libraries/_docker.env b/scripts/ci/libraries/_docker.env
index 986b7b4..86461d0 100644
--- a/scripts/ci/libraries/_docker.env
+++ b/scripts/ci/libraries/_docker.env
@@ -24,9 +24,13 @@ HOST_OS
 HOST_HOME
 HOST_AIRFLOW_SOURCES
 PYTHON_MAJOR_MINOR_VERSION
+BACKEND
 VERSION_SUFFIX_FOR_PYPI
 VERSION_SUFFIX_FOR_SVN
 PRINT_INFO_FROM_SCRIPTS
 CI
 LOAD_DEFAULT_CONNECTIONS
 LOAD_EXAMPLES
+GITHUB_REGISTRY_PULL_IMAGE_TAG
+POSTGRES_VERSION
+MYSQL_VERSION
diff --git a/scripts/ci/libraries/_initialization.sh b/scripts/ci/libraries/_initialization.sh
index bac69a9..e7ec0c9 100644
--- a/scripts/ci/libraries/_initialization.sh
+++ b/scripts/ci/libraries/_initialization.sh
@@ -101,7 +101,7 @@ function initialization::initialize_base_variables() {
     CURRENT_POSTGRES_VERSIONS+=("9.6" "10")
     export CURRENT_POSTGRES_VERSIONS
 
-   # Currently supported versions of MySQL
+    # Currently supported versions of MySQL
     CURRENT_MYSQL_VERSIONS+=("5.7" "8")
     export CURRENT_MYSQL_VERSIONS
 
@@ -175,7 +175,6 @@ function initialization::initialize_available_integrations() {
     export AVAILABLE_INTEGRATIONS="cassandra kerberos mongo openldap presto rabbitmq redis"
 }
 
-
 # Needs to be declared outside of function for MacOS
 FILES_FOR_REBUILD_CHECK=()
 
@@ -193,7 +192,6 @@ function initialization::initialize_files_for_rebuild_check() {
     )
 }
 
-
 # Needs to be declared outside of function for MacOS
 
 # extra flags passed to docker run for PROD image
@@ -262,6 +260,8 @@ function initialization::initialize_force_variables() {
     # Can be set to true to skip if the image is newer in registry
     export SKIP_CHECK_REMOTE_IMAGE=${SKIP_CHECK_REMOTE_IMAGE:="false"}
 
+    # Should be set to true if you expect image frm GitHub to be present and downloaded
+    export FAIL_ON_GITHUB_DOCKER_PULL_ERROR=${FAIL_ON_GITHUB_DOCKER_PULL_ERROR:="false"}
 }
 
 # Determine information about the host
@@ -442,8 +442,10 @@ function initialization::initialize_github_variables() {
     # Used only in CI environment
     export GITHUB_TOKEN="${GITHUB_TOKEN=""}"
     export GITHUB_USERNAME="${GITHUB_USERNAME=""}"
+}
 
-
+function initialization::initialize_test_variables() {
+    export TEST_TYPE=${TEST_TYPE:="All"}
 }
 
 # Common environment that is initialized by both Breeze and CI scripts
@@ -462,6 +464,7 @@ function initialization::initialize_common_environment() {
     initialization::initialize_kubernetes_variables
     initialization::initialize_git_variables
     initialization::initialize_github_variables
+    initialization::initialize_test_variables
 }
 
 function initialization::set_default_python_version_if_empty() {
@@ -500,6 +503,7 @@ Force variables:
     FORCE_BUILD_IMAGES: ${FORCE_BUILD_IMAGES}
     FORCE_ANSWER_TO_QUESTIONS: ${FORCE_ANSWER_TO_QUESTIONS}
     SKIP_CHECK_REMOTE_IMAGE: ${SKIP_CHECK_REMOTE_IMAGE}
+    FAIL_ON_GITHUB_DOCKER_PULL_ERROR: ${FAIL_ON_GITHUB_DOCKER_PULL_ERROR}
 
 Host variables:
 
@@ -564,6 +568,10 @@ Initialization variables:
     INSTALL_WHEELS: ${INSTALL_WHEELS}
     DISABLE_RBAC: ${DISABLE_RBAC}
 
+Test variables:
+
+    TEST_TYPE: ${TEST_TYPE}
+
 EOF
 
 }
@@ -635,7 +643,6 @@ function initialization::make_constants_read_only() {
     readonly POSTGRES_HOST_PORT
     readonly MYSQL_HOST_PORT
 
-
     readonly HOST_USER_ID
     readonly HOST_GROUP_ID
     readonly HOST_AIRFLOW_SOURCES
@@ -717,7 +724,6 @@ function initialization::make_constants_read_only() {
     readonly GITHUB_TOKEN
     readonly GITHUB_USERNAME
 
-
     readonly FORWARD_CREDENTIALS
     readonly USE_GITHUB_REGISTRY
 
@@ -741,21 +747,18 @@ function initialization::make_constants_read_only() {
 
 }
 
-
 # converts parameters to json array
 function initialization::parameters_to_json() {
     echo -n "["
     local separator=""
     local var
-    for var in "${@}"
-    do
+    for var in "${@}"; do
         echo -n "${separator}\"${var}\""
         separator=","
     done
     echo "]"
 }
 
-
 # output parameter name and value - both to stdout and to be set by GitHub Actions
 function initialization::ga_output() {
     echo "::set-output name=${1}::${2}"
diff --git a/scripts/ci/libraries/_parameters.sh b/scripts/ci/libraries/_parameters.sh
index 3f2f02d..d655853 100644
--- a/scripts/ci/libraries/_parameters.sh
+++ b/scripts/ci/libraries/_parameters.sh
@@ -17,21 +17,22 @@
 # under the License.
 
 # Reads environment variable passed as first parameter from the .build cache file
-function parameters::read_from_file {
+function parameters::read_from_file() {
     cat "${BUILD_CACHE_DIR}/.$1" 2>/dev/null || true
 }
 
 # Saves environment variable passed as first parameter to the .build cache file
-function parameters::save_to_file {
+function parameters::save_to_file() {
     # shellcheck disable=SC2005
-    echo "$(eval echo "\$$1")" > "${BUILD_CACHE_DIR}/.$1"
+    echo "$(eval echo "\$$1")" >"${BUILD_CACHE_DIR}/.$1"
 }
 
 # check if parameter set for the variable is allowed (should be on the _breeze_allowed list)
-# and if it is, it saves it to .build cache file. In case the parameter is wrong, the
-# saved variable is removed (so that bad value is not used again in case it comes from there)
-# and exits with an error
-function parameters::check_and_save_allowed_param {
+# parameters:
+# $1 - name of the variable
+# $2 - descriptive name of the parameter
+# $3 - flag used to set te parameter
+function parameters::check_allowed_param() {
     _VARIABLE_NAME="${1}"
     _VARIABLE_DESCRIPTIVE_NAME="${2}"
     _FLAG="${3}"
@@ -44,9 +45,7 @@ function parameters::check_and_save_allowed_param {
         echo >&2
         echo >&2 "Switch to supported value with ${_FLAG} flag."
 
-        if [[ -n ${!_VARIABLE_NAME} && \
-            -f "${BUILD_CACHE_DIR}/.${_VARIABLE_NAME}" && \
-            ${!_VARIABLE_NAME} == $(cat "${BUILD_CACHE_DIR}/.${_VARIABLE_NAME}" ) ]]; then
+        if [[ -n ${!_VARIABLE_NAME} && -f "${BUILD_CACHE_DIR}/.${_VARIABLE_NAME}" && ${!_VARIABLE_NAME} == $(cat "${BUILD_CACHE_DIR}/.${_VARIABLE_NAME}") ]]; then
             echo >&2
             echo >&2 "Removing ${BUILD_CACHE_DIR}/.${_VARIABLE_NAME}. Next time you run it, it should be OK."
             echo >&2
@@ -54,5 +53,12 @@ function parameters::check_and_save_allowed_param {
         fi
         exit 1
     fi
-    parameters::save_to_file "${_VARIABLE_NAME}"
+}
+# check if parameter set for the variable is allowed (should be on the _breeze_allowed list)
+# and if it is, it saves it to .build cache file. In case the parameter is wrong, the
+# saved variable is removed (so that bad value is not used again in case it comes from there)
+# and exits with an error
+function parameters::check_and_save_allowed_param() {
+    parameters::check_allowed_param "${@}"
+    parameters::save_to_file "${1}"
 }
diff --git a/scripts/ci/libraries/_push_pull_remove_images.sh b/scripts/ci/libraries/_push_pull_remove_images.sh
index 5810303..fae0807 100644
--- a/scripts/ci/libraries/_push_pull_remove_images.sh
+++ b/scripts/ci/libraries/_push_pull_remove_images.sh
@@ -63,6 +63,20 @@ function push_pull_remove_images::pull_image_if_not_present_or_forced() {
         echo
         docker pull "${IMAGE_TO_PULL}"
         EXIT_VALUE="$?"
+        if [[ ${EXIT_VALUE} != "0" && ${FAIL_ON_GITHUB_DOCKER_PULL_ERROR} == "true" ]]; then
+            >&2 echo
+            >&2 echo "ERROR! Exiting on docker pull error"
+            >&2 echo
+            >&2 echo "If you have authorisation problems, you might want to run:"
+            >&2 echo
+            >&2 echo "docker login ${IMAGE_TO_PULL%%\/*}"
+            >&2 echo
+            >&2 echo "You need to use generate token as the password, not your personal password."
+            >&2 echo "You can generete one at https://github.com/settings/tokens"
+            >&2 echo "Make sure to choose 'read:packages' scope".
+            >&2 echo
+            exit ${EXIT_VALUE}
+        fi
         echo
         return ${EXIT_VALUE}
     fi
diff --git a/scripts/ci/testing/ci_run_airflow_testing.sh b/scripts/ci/testing/ci_run_airflow_testing.sh
index 559ddb3..6f3cbdd 100755
--- a/scripts/ci/testing/ci_run_airflow_testing.sh
+++ b/scripts/ci/testing/ci_run_airflow_testing.sh
@@ -27,13 +27,6 @@ ENABLED_INTEGRATIONS=${ENABLED_INTEGRATIONS:=""}
 if [[ ${TEST_TYPE:=} == "Integration" ]]; then
     export ENABLED_INTEGRATIONS="${AVAILABLE_INTEGRATIONS}"
     export RUN_INTEGRATION_TESTS="${AVAILABLE_INTEGRATIONS}"
-elif [[ ${TEST_TYPE:=} == "Long" ]]; then
-    export ONLY_RUN_LONG_RUNNING_TESTS="true"
-elif [[ ${TEST_TYPE:=} == "Heisentests" ]]; then
-    export ONLY_RUN_HEISEN_TESTS="true"
-elif [[ ${TEST_TYPE:=} == "Quarantined" ]]; then
-    export ONLY_RUN_QUARANTINED_TESTS="true"
-    # Do not fail in quarantined tests
 fi
 
 for _INT in ${ENABLED_INTEGRATIONS}
@@ -83,7 +76,7 @@ function run_airflow_testing_in_docker() {
             break
         fi
     done
-    if [[ ${ONLY_RUN_QUARANTINED_TESTS:=} == "true" ]]; then
+    if [[ ${TEST_TYPE:=} == "Quarantined" ]]; then
         if [[ ${exit_code} == "1" ]]; then
             echo
             echo "Some Quarantined tests failed. but we recorded it in an issue"
diff --git a/scripts/in_container/entrypoint_ci.sh b/scripts/in_container/entrypoint_ci.sh
index 6a62c21..1a1522f 100755
--- a/scripts/in_container/entrypoint_ci.sh
+++ b/scripts/in_container/entrypoint_ci.sh
@@ -200,17 +200,102 @@ if [[ "${GITHUB_ACTIONS}" == "true" ]]; then
         "--pythonwarnings=ignore::DeprecationWarning"
         "--pythonwarnings=ignore::PendingDeprecationWarning"
         "--junitxml=${RESULT_LOG_FILE}"
+        # timeouts in seconds for individual tests
+        "--setup-timeout=20"
+        "--execution-timeout=60"
+        "--teardown-timeout=20"
+        # Only display summary for non-expected case
+        # f - failed
+        # E - error
+        # X - xpessed (passed even if expected to fail)
+        # The following cases are not displayed:
+        # s - skipped
+        # x - xfailed (expected to fail and failed)
+        # p - passed
+        # P - passed with output
+        "-rfEX"
         )
 else
-    EXTRA_PYTEST_ARGS=()
+    EXTRA_PYTEST_ARGS=(
+        "-rfEX"
+    )
 fi
 
-declare -a TESTS_TO_RUN
-TESTS_TO_RUN=("tests")
+declare -a SELECTED_TESTS CLI_TESTS API_TESTS PROVIDERS_TESTS CORE_TESTS WWW_TESTS \
+    ALL_TESTS ALL_PRESELECTED_TESTS ALL_OTHER_TESTS
+
+# Finds all directories that are not on the list of tests
+# - so that we do not skip any in the future if new directories are added
+function find_all_other_tests() {
+    local all_tests_dirs
+    all_tests_dirs=$(find "tests" -type d)
+    all_tests_dirs=$(echo "${all_tests_dirs}" | sed "/tests$/d" )
+    all_tests_dirs=$(echo "${all_tests_dirs}" | sed "/tests\/dags/d" )
+    local path
+    for path in "${ALL_PRESELECTED_TESTS[@]}"
+    do
+        escaped_path="${path//\//\\\/}"
+        all_tests_dirs=$(echo "${all_tests_dirs}" | sed "/${escaped_path}/d" )
+    done
+    for path in ${all_tests_dirs}
+    do
+        ALL_OTHER_TESTS+=("${path}")
+    done
+}
 
 if [[ ${#@} -gt 0 && -n "$1" ]]; then
-    TESTS_TO_RUN=("${@}")
+    SELECTED_TESTS=("${@}")
+else
+    CLI_TESTS=("tests/cli")
+    API_TESTS=("tests/api" "tests/api_connexion")
+    PROVIDERS_TESTS=("tests/providers")
+    CORE_TESTS=(
+        "tests/core"
+        "tests/executors"
+        "tests/jobs"
+        "tests/models"
+        "tests/serialization"
+        "tests/ti_deps"
+        "tests/utils"
+    )
+    WWW_TESTS=("tests/www")
+    ALL_TESTS=("tests")
+    ALL_PRESELECTED_TESTS=(
+        "${CLI_TESTS[@]}"
+        "${API_TESTS[@]}"
+        "${PROVIDERS_TESTS[@]}"
+        "${CORE_TESTS[@]}"
+        "${WWW_TESTS[@]}"
+    )
+
+    if [[ ${TEST_TYPE:=""} == "CLI" ]]; then
+        SELECTED_TESTS=("${CLI_TESTS[@]}")
+    elif [[ ${TEST_TYPE:=""} == "API" ]]; then
+        SELECTED_TESTS=("${API_TESTS[@]}")
+    elif [[ ${TEST_TYPE:=""} == "Providers" ]]; then
+        SELECTED_TESTS=("${PROVIDERS_TESTS[@]}")
+    elif [[ ${TEST_TYPE:=""} == "Core" ]]; then
+        SELECTED_TESTS=("${CORE_TESTS[@]}")
+    elif [[ ${TEST_TYPE:=""} == "WWW" ]]; then
+        SELECTED_TESTS=("${WWW_TESTS[@]}")
+    elif [[ ${TEST_TYPE:=""} == "Other" ]]; then
+        find_all_other_tests
+        SELECTED_TESTS=("${ALL_OTHER_TESTS[@]}")
+    elif [[ ${TEST_TYPE:=""} == "All" || ${TEST_TYPE} == "Quarantined" || \
+            ${TEST_TYPE} == "Postgres" || ${TEST_TYPE} == "MySQL" || \
+            ${TEST_TYPE} == "Heisentests" || ${TEST_TYPE} == "Long" || \
+            ${TEST_TYPE} == "Integration" ]]; then
+        SELECTED_TESTS=("${ALL_TESTS[@]}")
+    else
+        >&2 echo
+        >&2 echo "Wrong test type ${TEST_TYPE}"
+        >&2 echo
+        exit 1
+    fi
+
 fi
+readonly SELECTED_TESTS CLI_TESTS API_TESTS PROVIDERS_TESTS CORE_TESTS WWW_TESTS \
+    ALL_TESTS ALL_PRESELECTED_TESTS
 
 if [[ -n ${RUN_INTEGRATION_TESTS=} ]]; then
     # Integration tests
@@ -218,52 +303,38 @@ if [[ -n ${RUN_INTEGRATION_TESTS=} ]]; then
     do
         EXTRA_PYTEST_ARGS+=("--integration" "${INT}")
     done
-    EXTRA_PYTEST_ARGS+=(
-        # timeouts in seconds for individual tests
-        "--setup-timeout=20"
-        "--execution-timeout=60"
-        "--teardown-timeout=20"
-        # Do not display skipped tests
-        "-rfExFpP"
-    )
-
-elif [[ ${ONLY_RUN_LONG_RUNNING_TESTS:=""} == "true" ]]; then
+elif [[ ${TEST_TYPE:=""} == "Long" ]]; then
     EXTRA_PYTEST_ARGS+=(
         "-m" "long_running"
         "--include-long-running"
-        "--verbosity=1"
-        "--setup-timeout=30"
-        "--execution-timeout=120"
-        "--teardown-timeout=30"
     )
-elif [[ ${ONLY_RUN_HEISEN_TESTS:=""} == "true" ]]; then
+elif [[ ${TEST_TYPE:=""} == "Heisentests" ]]; then
     EXTRA_PYTEST_ARGS+=(
         "-m" "heisentests"
         "--include-heisentests"
-        "--verbosity=1"
-        "--setup-timeout=20"
-        "--execution-timeout=50"
-        "--teardown-timeout=20"
     )
-elif [[ ${ONLY_RUN_QUARANTINED_TESTS:=""} == "true" ]]; then
+elif [[ ${TEST_TYPE:=""} == "Postgres" ]]; then
     EXTRA_PYTEST_ARGS+=(
-        "-m" "quarantined"
-        "--include-quarantined"
-        "--verbosity=1"
-        "--setup-timeout=10"
-        "--execution-timeout=50"
-        "--teardown-timeout=10"
+        "--backend"
+        "postgres"
     )
-else
-    # Core tests
+elif [[ ${TEST_TYPE:=""} == "MySQL" ]]; then
     EXTRA_PYTEST_ARGS+=(
-        "--setup-timeout=10"
-        "--execution-timeout=30"
-        "--teardown-timeout=10"
+        "--backend"
+        "mysql"
+    )
+elif [[ ${TEST_TYPE:=""} == "Quarantined" ]]; then
+    EXTRA_PYTEST_ARGS+=(
+        "-m" "quarantined"
+        "--include-quarantined"
     )
 fi
 
-ARGS=("${EXTRA_PYTEST_ARGS[@]}" "${TESTS_TO_RUN[@]}")
+echo
+echo "Running tests ${SELECTED_TESTS[*]}"
+echo
+
+ARGS=("${EXTRA_PYTEST_ARGS[@]}" "${SELECTED_TESTS[@]}")
 
 if [[ ${RUN_SYSTEM_TESTS:="false"} == "true" ]]; then
     "${IN_CONTAINER_DIR}/run_system_tests.sh" "${ARGS[@]}"
diff --git a/scripts/in_container/run_ci_tests.sh b/scripts/in_container/run_ci_tests.sh
index 2a4e0a1..7494eec 100755
--- a/scripts/in_container/run_ci_tests.sh
+++ b/scripts/in_container/run_ci_tests.sh
@@ -31,11 +31,58 @@ set +x
 if [[ "${RES}" == "0" && ${CI:="false"} == "true" ]]; then
     echo "All tests successful"
     cp .coverage /files
+elif [[ "${RES}" != "0" ]]; then
+    EXTRA_ARGS=""
+    if [[ ${BACKEND} == "postgres" ]]; then
+        EXTRA_ARGS="--postgres-version ${POSTGRES_VERSION} "
+    elif [[ ${BACKEND} == "mysql" ]]; then
+        EXTRA_ARGS="--mysql-version ${MYSQL_VERSION} "
+    fi
+
+    >&2 echo "***********************************************************************************************"
+    >&2 echo "*"
+    >&2 echo "* ERROR! Some tests failed, unfortunately. Those might be transient errors,"
+    >&2 echo "*        but usually you have to fix something."
+    >&2 echo "*        See the above log for details."
+    >&2 echo "*"
+    >&2 echo "***********************************************************************************************"
+    >&2 echo "*  You can easily reproduce the failed tests on your dev machine/"
+    >&2 echo "*"
+    >&2 echo "*   When you have the source branch checked out locally:"
+    >&2 echo "*"
+    >&2 echo "*     Run all tests:"
+    >&2 echo "*"
+    >&2 echo "*       ./breeze --backend ${BACKEND} ${EXTRA_ARGS}--python ${PYTHON_MAJOR_MINOR_VERSION} --db-reset --test-type ${TEST_TYPE}  tests"
+    >&2 echo "*"
+    >&2 echo "*     Enter docker shell:"
+    >&2 echo "*"
+    >&2 echo "*       ./breeze --backend ${BACKEND} ${EXTRA_ARGS}--python ${PYTHON_MAJOR_MINOR_VERSION} --db-reset --test-type ${TEST_TYPE}  shell"
+    >&2 echo "*"
+    if [[ ${GITHUB_REGISTRY_PULL_IMAGE_TAG=} != "" ]]; then
+        >&2 echo "*   When you do not have sources:"
+        >&2 echo "*"
+        >&2 echo "*     Run all tests:"
+        >&2 echo "*"
+        >&2 echo "*      ./breeze --github-image-id ${GITHUB_REGISTRY_PULL_IMAGE_TAG} --backend ${BACKEND} ${EXTRA_ARGS}--python ${PYTHON_MAJOR_MINOR_VERSION} --db-reset --test-type ${TEST_TYPE} tests"
+        >&2 echo "*"
+        >&2 echo "*     Enter docker shell:"
+        >&2 echo "*"
+        >&2 echo "*      ./breeze --github-image-id ${GITHUB_REGISTRY_PULL_IMAGE_TAG} --backend ${BACKEND} ${EXTRA_ARGS}--python ${PYTHON_MAJOR_MINOR_VERSION} --db-reset --test-type ${TEST_TYPE} shell"
+        >&2 echo "*"
+    fi
+    >&2 echo "*"
+    >&2 echo "*   NOTE! Once you are in the docker shell, you can run failed test with:"
+    >&2 echo "*"
+    >&2 echo "*            pytest [TEST_NAME]"
+    >&2 echo "*"
+    >&2 echo "*   You can copy the test name from the output above"
+    >&2 echo "*"
+    >&2 echo "***********************************************************************************************"
 fi
 
 MAIN_GITHUB_REPOSITORY="apache/airflow"
 
-if [[ ${ONLY_RUN_QUARANTINED_TESTS:=} = "true" ]]; then
+if [[ ${TEST_TYPE:=} == "Quarantined" ]]; then
     if [[ ${GITHUB_REPOSITORY} == "${MAIN_GITHUB_REPOSITORY}" ]]; then
         if [[ ${RES} == "1" || ${RES} == "0" ]]; then
             echo
@@ -47,15 +94,7 @@ if [[ ${ONLY_RUN_QUARANTINED_TESTS:=} = "true" ]]; then
             echo "Pytest exited with ${RES} result. NOT Updating Quarantine Issue!"
             echo
         fi
-    else
-        echo
-        echo "GitHub repository '${GITHUB_REPOSITORY}'. NOT Updating Quarantine Issue!"
-        echo
     fi
-else
-    echo
-    echo "Regular tests. NOT Updating Quarantine Issue!"
-    echo
 fi
 
 if [[ ${CI:=} == "true" ]]; then
diff --git a/tests/bats/test_breeze_complete.bats b/tests/bats/test_breeze_complete.bats
index 2fee270..163db61 100644
--- a/tests/bats/test_breeze_complete.bats
+++ b/tests/bats/test_breeze_complete.bats
@@ -254,3 +254,11 @@
 
   assert_equal "${_breeze_default_postgres_version}" "${POSTGRES_VERSION}"
 }
+
+@test "Test default test type same as TEST_TYPE" {
+  load bats_utils
+  #shellcheck source=breeze-complete
+  source "${AIRFLOW_SOURCES}/breeze-complete"
+
+  assert_equal "${_breeze_default_test_type}" "${TEST_TYPE}"
+}
diff --git a/tests/cli/commands/test_connection_command.py b/tests/cli/commands/test_connection_command.py
index fae3115..5e4fe90 100644
--- a/tests/cli/commands/test_connection_command.py
+++ b/tests/cli/commands/test_connection_command.py
@@ -339,13 +339,18 @@ class TestCliExportConnections(unittest.TestCase):
         ])
         connection_command.connections_export(args)
 
-        expected_connections = (
+        expected_connections = [
             "airflow_db=mysql://root:plainpassword@mysql/airflow\n"
-            "druid_broker_default=druid://druid-broker:8082?endpoint=druid%2Fv2%2Fsql\n")
+            "druid_broker_default=druid://druid-broker:8082?endpoint=druid%2Fv2%2Fsql\n",
+
+            "druid_broker_default=druid://druid-broker:8082?endpoint=druid%2Fv2%2Fsql\n"
+            "airflow_db=mysql://root:plainpassword@mysql/airflow\n"
+        ]
 
         mock_splittext.assert_called_once()
         mock_file_open.assert_called_once_with(output_filepath, 'w', -1, 'UTF-8', None)
-        mock_file_open.return_value.write.assert_called_once_with(expected_connections)
+        mock_file_open.return_value.write.assert_called_once_with(mock.ANY)
+        self.assertIn(mock_file_open.return_value.write.call_args_list[0][0][0], expected_connections)
 
     @mock.patch('os.path.splitext')
     @mock.patch('builtins.open', new_callable=mock.mock_open())
@@ -361,13 +366,18 @@ class TestCliExportConnections(unittest.TestCase):
         ])
         connection_command.connections_export(args)
 
-        expected_connections = (
+        expected_connections = [
             "airflow_db=mysql://root:plainpassword@mysql/airflow\n"
-            "druid_broker_default=druid://druid-broker:8082?endpoint=druid%2Fv2%2Fsql\n")
+            "druid_broker_default=druid://druid-broker:8082?endpoint=druid%2Fv2%2Fsql\n",
+
+            "druid_broker_default=druid://druid-broker:8082?endpoint=druid%2Fv2%2Fsql\n"
+            "airflow_db=mysql://root:plainpassword@mysql/airflow\n"
+        ]
 
         mock_splittext.assert_called_once()
         mock_file_open.assert_called_once_with(output_filepath, 'w', -1, 'UTF-8', None)
-        mock_file_open.return_value.write.assert_called_once_with(expected_connections)
+        mock_file_open.return_value.write.assert_called_once_with(mock.ANY)
+        self.assertIn(mock_file_open.return_value.write.call_args_list[0][0][0], expected_connections)
 
     @mock.patch('os.path.splitext')
     @mock.patch('builtins.open', new_callable=mock.mock_open())
diff --git a/tests/test_config_templates.py b/tests/core/test_config_templates.py
similarity index 100%
rename from tests/test_config_templates.py
rename to tests/core/test_config_templates.py
diff --git a/tests/test_configuration.py b/tests/core/test_configuration.py
similarity index 100%
rename from tests/test_configuration.py
rename to tests/core/test_configuration.py
diff --git a/tests/test_core.py b/tests/core/test_core.py
similarity index 100%
rename from tests/test_core.py
rename to tests/core/test_core.py
diff --git a/tests/test_core_to_contrib.py b/tests/core/test_core_to_contrib.py
similarity index 100%
rename from tests/test_core_to_contrib.py
rename to tests/core/test_core_to_contrib.py
diff --git a/tests/test_example_dags.py b/tests/core/test_example_dags.py
similarity index 100%
rename from tests/test_example_dags.py
rename to tests/core/test_example_dags.py
diff --git a/tests/test_example_dags_system.py b/tests/core/test_example_dags_system.py
similarity index 100%
rename from tests/test_example_dags_system.py
rename to tests/core/test_example_dags_system.py
diff --git a/tests/test_impersonation.py b/tests/core/test_impersonation_tests.py
similarity index 100%
rename from tests/test_impersonation.py
rename to tests/core/test_impersonation_tests.py
diff --git a/tests/test_local_settings.py b/tests/core/test_local_settings.py
similarity index 100%
rename from tests/test_local_settings.py
rename to tests/core/test_local_settings.py
diff --git a/tests/test_logging_config.py b/tests/core/test_logging_config.py
similarity index 100%
rename from tests/test_logging_config.py
rename to tests/core/test_logging_config.py
diff --git a/tests/test_project_structure.py b/tests/core/test_project_structure.py
similarity index 99%
rename from tests/test_project_structure.py
rename to tests/core/test_project_structure.py
index 03ac050..9b1d967 100644
--- a/tests/test_project_structure.py
+++ b/tests/core/test_project_structure.py
@@ -24,7 +24,7 @@ import unittest
 from parameterized import parameterized
 
 ROOT_FOLDER = os.path.realpath(
-    os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir)
+    os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir)
 )
 
 
@@ -138,7 +138,7 @@ class TestGoogleProviderProjectStructure(unittest.TestCase):
                     "Can you remove it from the list of missing example, please?"
                 )
 
-        with self.subTest("Revmoe extra elements"):
+        with self.subTest("Remove extra elements"):
             extra_example_dags = set(self.MISSING_EXAMPLE_DAGS) - set(operator_sets)
             if extra_example_dags:
                 new_example_dag_text = '\n'.join(str(f) for f in extra_example_dags)
diff --git a/tests/test_sentry.py b/tests/core/test_sentry.py
similarity index 100%
rename from tests/test_sentry.py
rename to tests/core/test_sentry.py
diff --git a/tests/test_sqlalchemy_config.py b/tests/core/test_sqlalchemy_config.py
similarity index 96%
rename from tests/test_sqlalchemy_config.py
rename to tests/core/test_sqlalchemy_config.py
index 2147ca5..03b644b 100644
--- a/tests/test_sqlalchemy_config.py
+++ b/tests/core/test_sqlalchemy_config.py
@@ -76,7 +76,8 @@ class TestSqlAlchemySettings(unittest.TestCase):
                                       mock_scoped_session,
                                       mock_setup_event_handlers):
         config = {
-            ('core', 'sql_alchemy_connect_args'): 'tests.test_sqlalchemy_config.SQL_ALCHEMY_CONNECT_ARGS',
+            ('core', 'sql_alchemy_connect_args'):
+                'tests.core.test_sqlalchemy_config.SQL_ALCHEMY_CONNECT_ARGS',
             ('core', 'sql_alchemy_pool_enabled'): 'False'
         }
         with conf_vars(config):
diff --git a/tests/test_stats.py b/tests/core/test_stats.py
similarity index 93%
rename from tests/test_stats.py
rename to tests/core/test_stats.py
index 9df0aab..0b93565 100644
--- a/tests/test_stats.py
+++ b/tests/core/test_stats.py
@@ -105,24 +105,24 @@ class TestStats(unittest.TestCase):
 
     @conf_vars({
         ("scheduler", "statsd_on"): "True",
-        ("scheduler", "statsd_custom_client_path"): "tests.test_stats.CustomStatsd",
+        ("scheduler", "statsd_custom_client_path"): "tests.core.test_stats.CustomStatsd",
     })
     def test_load_custom_statsd_client(self):
         importlib.reload(airflow.stats)
-        assert isinstance(airflow.stats.Stats.statsd, CustomStatsd)
+        self.assertEqual('CustomStatsd', type(airflow.stats.Stats.statsd).__name__)
 
     @conf_vars({
         ("scheduler", "statsd_on"): "True",
-        ("scheduler", "statsd_custom_client_path"): "tests.test_stats.CustomStatsd",
+        ("scheduler", "statsd_custom_client_path"): "tests.core.test_stats.CustomStatsd",
     })
     def test_does_use_custom_statsd_client(self):
         importlib.reload(airflow.stats)
         airflow.stats.Stats.incr("dummy_key")
-        assert CustomStatsd.incr_calls == 1
+        assert airflow.stats.Stats.statsd.incr_calls == 1
 
     @conf_vars({
         ("scheduler", "statsd_on"): "True",
-        ("scheduler", "statsd_custom_client_path"): "tests.test_stats.InvalidCustomStatsd",
+        ("scheduler", "statsd_custom_client_path"): "tests.core.test_stats.InvalidCustomStatsd",
     })
     def test_load_invalid_custom_stats_client(self):
         with self.assertRaisesRegex(
@@ -265,7 +265,7 @@ def always_valid(stat_name):
 class TestCustomStatsName(unittest.TestCase):
     @conf_vars({
         ('scheduler', 'statsd_on'): 'True',
-        ('scheduler', 'stat_name_handler'): 'tests.test_stats.always_invalid'
+        ('scheduler', 'stat_name_handler'): 'tests.core.test_stats.always_invalid'
     })
     @mock.patch("statsd.StatsClient")
     def test_does_not_send_stats_using_statsd_when_the_name_is_not_valid(self, mock_statsd):
@@ -275,7 +275,7 @@ class TestCustomStatsName(unittest.TestCase):
 
     @conf_vars({
         ('scheduler', 'statsd_datadog_enabled'): 'True',
-        ('scheduler', 'stat_name_handler'): 'tests.test_stats.always_invalid'
+        ('scheduler', 'stat_name_handler'): 'tests.core.test_stats.always_invalid'
     })
     @mock.patch("datadog.DogStatsd")
     def test_does_not_send_stats_using_dogstatsd_when_the_name_is_not_valid(self, mock_dogstatsd):
@@ -285,7 +285,7 @@ class TestCustomStatsName(unittest.TestCase):
 
     @conf_vars({
         ('scheduler', 'statsd_on'): 'True',
-        ('scheduler', 'stat_name_handler'): 'tests.test_stats.always_valid'
+        ('scheduler', 'stat_name_handler'): 'tests.core.test_stats.always_valid'
     })
     @mock.patch("statsd.StatsClient")
     def test_does_send_stats_using_statsd_when_the_name_is_valid(self, mock_statsd):
@@ -295,7 +295,7 @@ class TestCustomStatsName(unittest.TestCase):
 
     @conf_vars({
         ('scheduler', 'statsd_datadog_enabled'): 'True',
-        ('scheduler', 'stat_name_handler'): 'tests.test_stats.always_valid'
+        ('scheduler', 'stat_name_handler'): 'tests.core.test_stats.always_valid'
     })
     @mock.patch("datadog.DogStatsd")
     def test_does_send_stats_using_dogstatsd_when_the_name_is_valid(self, mock_dogstatsd):
diff --git a/tests/jobs/test_backfill_job.py b/tests/jobs/test_backfill_job.py
index 3682e34..ceb571c 100644
--- a/tests/jobs/test_backfill_job.py
+++ b/tests/jobs/test_backfill_job.py
@@ -51,6 +51,7 @@ logger = logging.getLogger(__name__)
 DEFAULT_DATE = timezone.datetime(2016, 1, 1)
 
 
+@pytest.mark.heisentests
 class TestBackfillJob(unittest.TestCase):
 
     def _get_dummy_dag(self, dag_id, pool=Pool.DEFAULT_POOL_NAME, task_concurrency=None):
diff --git a/tests/jobs/test_local_task_job.py b/tests/jobs/test_local_task_job.py
index 02e8696..104d3e2 100644
--- a/tests/jobs/test_local_task_job.py
+++ b/tests/jobs/test_local_task_job.py
@@ -175,7 +175,7 @@ class TestLocalTaskJob(unittest.TestCase):
                 delta = (time2 - time1).total_seconds()
                 self.assertAlmostEqual(delta, job.heartrate, delta=0.05)
 
-    @pytest.mark.xfail(condition=True, reason="This test might be flaky in postgres/mysql")
+    @pytest.mark.quarantined
     def test_mark_success_no_kill(self):
         """
         Test that ensures that mark_success in the UI doesn't cause
@@ -360,6 +360,7 @@ class TestLocalTaskJob(unittest.TestCase):
         self.assertNotIn('reached_end_of_sleep', data,
                          'Task should not have been allowed to run to completion')
 
+    @pytest.mark.quarantined
     def test_mark_success_on_success_callback(self):
         """
         Test that ensures that where a task is marked suceess in the UI
diff --git a/tests/jobs/test_scheduler_job.py b/tests/jobs/test_scheduler_job.py
index 8aabba2..b46c80d 100644
--- a/tests/jobs/test_scheduler_job.py
+++ b/tests/jobs/test_scheduler_job.py
@@ -3547,7 +3547,6 @@ class TestSchedulerJobQueriesCount(unittest.TestCase):
         clear_db_serialized_dags()
         clear_db_dags()
 
-    @pytest.mark.quarantined
     @parameterized.expand(
         [
             # pylint: disable=bad-whitespace
@@ -3560,6 +3559,7 @@ class TestSchedulerJobQueriesCount(unittest.TestCase):
             (95, 10, 10),  # noqa
         ]
     )
+    @pytest.mark.quarantined
     def test_execute_queries_count_with_harvested_dags(self, expected_query_count, dag_count, task_count):
         with mock.patch.dict("os.environ", {
             "PERF_DAGS_COUNT": str(dag_count),
diff --git a/tests/serialization/test_dag_serialization.py b/tests/serialization/test_dag_serialization.py
index fbad5e0..93d1110 100644
--- a/tests/serialization/test_dag_serialization.py
+++ b/tests/serialization/test_dag_serialization.py
@@ -25,6 +25,7 @@ from datetime import datetime, timedelta, timezone
 from glob import glob
 from unittest import mock
 
+import pytest
 from dateutil.relativedelta import FR, relativedelta
 from kubernetes.client import models as k8s
 from parameterized import parameterized
@@ -294,6 +295,7 @@ class TestStringifiedDAGs(unittest.TestCase):
 
         assert sorted_serialized_dag(ground_truth_dag) == sorted_serialized_dag(json_dag)
 
+    @pytest.mark.quarantined
     def test_deserialization_across_process(self):
         """A serialized DAG can be deserialized in another process."""
 
diff --git a/tests/task/task_runner/test_standard_task_runner.py b/tests/task/task_runner/test_standard_task_runner.py
index f6b777b..2d96400 100644
--- a/tests/task/task_runner/test_standard_task_runner.py
+++ b/tests/task/task_runner/test_standard_task_runner.py
@@ -68,7 +68,11 @@ class TestStandardTaskRunner(unittest.TestCase):
 
     @classmethod
     def tearDownClass(cls):
-        clear_db_runs()
+        try:
+            clear_db_runs()
+        except Exception:  # noqa pylint: disable=broad-except
+            # It might happen that we lost connection to the server here so we need to ignore any errors here
+            pass
 
     def test_start_and_terminate(self):
         local_task_job = mock.Mock()
diff --git a/tests/utils/test_dag_processing.py b/tests/utils/test_dag_processing.py
index 077c2fa..cc15143 100644
--- a/tests/utils/test_dag_processing.py
+++ b/tests/utils/test_dag_processing.py
@@ -41,7 +41,7 @@ from airflow.utils.dag_processing import (
 from airflow.utils.file import correct_maybe_zipped, open_maybe_zipped
 from airflow.utils.session import create_session
 from airflow.utils.state import State
-from tests.test_logging_config import SETTINGS_FILE_VALID, settings_context
+from tests.core.test_logging_config import SETTINGS_FILE_VALID, settings_context
 from tests.test_utils.config import conf_vars
 from tests.test_utils.db import clear_db_dags, clear_db_runs, clear_db_serialized_dags
 
diff --git a/tests/www/test_views.py b/tests/www/test_views.py
index 47982e0..bb6aeb6 100644
--- a/tests/www/test_views.py
+++ b/tests/www/test_views.py
@@ -56,7 +56,6 @@ from airflow.ti_deps.dependencies_states import QUEUEABLE_STATES, RUNNABLE_STATE
 from airflow.utils import dates, timezone
 from airflow.utils.log.logging_mixin import ExternalLoggingMixin
 from airflow.utils.session import create_session
-from airflow.utils.sqlalchemy import using_mysql
 from airflow.utils.state import State
 from airflow.utils.timezone import datetime
 from airflow.utils.types import DagRunType
@@ -2388,7 +2387,7 @@ class TestTriggerDag(TestBase):
         self.assertIn('/trigger?dag_id=example_bash_operator', resp.data.decode('utf-8'))
         self.assertIn("return confirmDeleteDag(this, 'example_bash_operator')", resp.data.decode('utf-8'))
 
-    @pytest.mark.xfail(condition=using_mysql, reason="This test might be flaky on mysql")
+    @pytest.mark.quarantined
     def test_trigger_dag_button(self):
 
         test_dag_id = "example_bash_operator"
@@ -2404,7 +2403,7 @@ class TestTriggerDag(TestBase):
         self.assertIn(DagRunType.MANUAL.value, run.run_id)
         self.assertEqual(run.run_type, DagRunType.MANUAL.value)
 
-    @pytest.mark.xfail(condition=using_mysql, reason="This test might be flaky on mysql")
+    @pytest.mark.quarantined
     def test_trigger_dag_conf(self):
 
         test_dag_id = "example_bash_operator"