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

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


The following commit(s) were added to refs/heads/master by this push:
     new 25d9caad0 IMPALA-14667: Remove reference to pytest.config
25d9caad0 is described below

commit 25d9caad006165cdd0b650fc9da53d209c00dc2e
Author: Riza Suminto <[email protected]>
AuthorDate: Wed Jan 7 16:31:41 2026 -0800

    IMPALA-14667: Remove reference to pytest.config
    
    pytest.config global variable has been removed since pytest 5.0.
    https://docs.pytest.org/en/stable/deprecations.html#pytest-config-global
    
    This patch remove direct reference to pytest.config. Instead, it hook
    pytest config object to ImpalaTestClusterProperties singleton at
    pytest_configure() method at conftest.py.
    
    Added pytest_config() classmethod in BaseTestSuite as a shortcut to
    access ImpalaTestClusterProperties.get_instance().pytest_config().
    
    Testing:
    - Pass core tests.
    
    Change-Id: Ieb09a9c8c1f474c355188b46a0ea913da6c2a38b
    Reviewed-on: http://gerrit.cloudera.org:8080/23840
    Reviewed-by: Impala Public Jenkins <[email protected]>
    Tested-by: Impala Public Jenkins <[email protected]>
---
 .../catalog_service/test_catalog_service_client.py |  5 +-
 tests/common/base_test_suite.py                    |  6 ++
 tests/common/custom_cluster_test_suite.py          |  6 +-
 tests/common/environ.py                            | 46 +++++++----
 tests/common/impala_test_suite.py                  | 89 ++++++++++++----------
 tests/common/kudu_test_suite.py                    |  5 +-
 tests/common/skip.py                               |  6 +-
 tests/common/test_dimensions.py                    | 14 ++--
 tests/conftest.py                                  | 39 ++++++----
 tests/custom_cluster/test_event_processing_perf.py |  7 +-
 tests/custom_cluster/test_insert_behaviour.py      |  6 +-
 tests/custom_cluster/test_kudu.py                  |  5 +-
 tests/custom_cluster/test_saml2_sso.py             | 10 ++-
 tests/metadata/test_partition_metadata.py          |  4 +-
 tests/query_test/test_kudu.py                      |  3 +-
 tests/run-tests.py                                 | 19 +++--
 tests/shell/util.py                                |  8 +-
 17 files changed, 165 insertions(+), 113 deletions(-)

diff --git a/tests/catalog_service/test_catalog_service_client.py 
b/tests/catalog_service/test_catalog_service_client.py
index eaf244dc0..43cf19266 100644
--- a/tests/catalog_service/test_catalog_service_client.py
+++ b/tests/catalog_service/test_catalog_service_client.py
@@ -20,7 +20,6 @@
 from __future__ import absolute_import, division, print_function
 import logging
 
-import pytest
 from thrift.protocol import TBinaryProtocol
 
 from impala_thrift_gen.CatalogService import CatalogService
@@ -51,11 +50,11 @@ class TestCatalogServiceClient(ImpalaTestSuite):
         v.get_value('table_format').compression_codec == 'none')
 
   @SkipIfDockerizedCluster.catalog_service_not_exposed
-  def test_get_functions(self, vector, unique_database):
+  def test_get_functions(self, unique_database):
     impala_cluster = ImpalaCluster.get_e2e_test_cluster()
     catalogd = impala_cluster.catalogd.service
     trans_type = 'buffered'
-    if pytest.config.option.use_kerberos:
+    if self.pytest_config().option.use_kerberos:
       trans_type = 'kerberos'
     transport = create_transport(host=catalogd.hostname, 
port=catalogd.service_port,
                                  service='impala', transport_type=trans_type)
diff --git a/tests/common/base_test_suite.py b/tests/common/base_test_suite.py
index 5612dbb02..2cb36be02 100644
--- a/tests/common/base_test_suite.py
+++ b/tests/common/base_test_suite.py
@@ -19,6 +19,7 @@
 from __future__ import absolute_import, division, print_function
 import logging
 
+from tests.common.environ import ImpalaTestClusterProperties
 from tests.common.test_vector import HS2, ImpalaTestMatrix
 
 LOG = logging.getLogger('base_test_suite')
@@ -42,3 +43,8 @@ class BaseTestSuite(object):
   def default_test_protocol(cls):
     """See documentation in ImpalaTestSuite.default_test_protocol()."""
     return HS2
+
+  @classmethod
+  def pytest_config(cls):
+    """Return a pytest config object."""
+    return ImpalaTestClusterProperties.get_instance().pytest_config()
diff --git a/tests/common/custom_cluster_test_suite.py 
b/tests/common/custom_cluster_test_suite.py
index a5a1198e6..f597cd8fa 100644
--- a/tests/common/custom_cluster_test_suite.py
+++ b/tests/common/custom_cluster_test_suite.py
@@ -213,7 +213,7 @@ class CustomClusterTestSuite(ImpalaTestSuite):
       args[LOG_SYMLINKS] = True
     if workload_mgmt:
       args[WORKLOAD_MGMT] = True
-    if force_restart or pytest.config.option.shard_tests:
+    if force_restart or cls.pytest_config().option.shard_tests:
       # When sharding tests, always restart the cluster to avoid issues with 
tests
       # that depend on a specific test order within a shard.
       args[FORCE_RESTART] = True
@@ -368,7 +368,7 @@ class CustomClusterTestSuite(ImpalaTestSuite):
       kwargs[IMPALAD_TIMEOUT_S] = args[IMPALAD_TIMEOUT_S]
     if FORCE_RESTART in args:
       kwargs[FORCE_RESTART] = args[FORCE_RESTART]
-      if args[FORCE_RESTART] is True and not pytest.config.option.shard_tests:
+      if args[FORCE_RESTART] is True and not 
cls.pytest_config().option.shard_tests:
         LOG.warning("Test uses force_restart=True to avoid restarting the 
cluster. "
                     "Test reorganization/assertion rewrite is needed")
     else:
@@ -643,7 +643,7 @@ class CustomClusterTestSuite(ImpalaTestSuite):
     if add_impalads:
       cmd.append("--add_impalads")
 
-    if pytest.config.option.use_local_catalog:
+    if cls.pytest_config().option.use_local_catalog:
       cmd.append("--impalad_args=--use_local_catalog=1")
       cmd.append("--catalogd_args=--catalog_topic_mode=minimal")
 
diff --git a/tests/common/environ.py b/tests/common/environ.py
index f15ba4727..bba7df8fc 100644
--- a/tests/common/environ.py
+++ b/tests/common/environ.py
@@ -20,7 +20,6 @@ import distro
 import json
 import logging
 import os
-import pytest
 import re
 import requests
 
@@ -128,6 +127,7 @@ IS_TUPLE_CACHE_CORRECT_CHECK = (
     os.getenv("TUPLE_CACHE_DEBUG_DUMP_DIR", "") != ""
 )
 
+
 class ImpalaBuildFlavors:
   """
   Represents the possible CMAKE_BUILD_TYPE values. These build flavors are 
needed
@@ -200,7 +200,7 @@ class ImpalaTestClusterFlagsDetector:
         build_type = build_flags[0].strip().lower()
         build_shared_libs = build_flags[1].strip().lower()
     except IOError:
-      LOG.debug("Unable to read .cmake_build_type file, fetching build flags 
from " +
+      LOG.debug("Unable to read .cmake_build_type file, fetching build flags 
from "
               "web ui on localhost")
       build_type, build_shared_libs = 
ImpalaTestClusterFlagsDetector.detect_using_web_ui(
           DEFAULT_LOCAL_WEB_UI_URL)
@@ -261,24 +261,18 @@ class ImpalaTestClusterProperties(object):
   and its likely effects on its responsiveness to automated test timings.
   TODO: Support remote urls for catalogd web UI."""
 
-  def __init__(self, build_flavor, library_link_type, web_ui_url,
+  def __init__(self, build_flavor, library_link_type, web_ui_url, 
pytest_config,
       catalogd_web_ui_url=DEFAULT_LOCAL_CATALOGD_WEB_UI_URL):
     self._build_flavor = build_flavor
     self._library_link_type = library_link_type
+    self._pytest_config = pytest_config
     self._web_ui_url = web_ui_url
     self._catalogd_web_ui_url = catalogd_web_ui_url
     self._runtime_flags = None  # Lazily populated to avoid unnecessary web UI 
calls.
     self._catalogd_runtime_flags = None  # Lazily populated
 
   @classmethod
-  def get_instance(cls):
-    """Implements lazy initialization of a singleton instance of this class. 
We cannot
-    initialize the instances when this module is imported because some 
dependencies may
-    not be available yet, e.g. the pytest.config object. Thus we instead 
initialize it
-    the first time that a test needs it."""
-    if cls._instance is not None:
-      return cls._instance
-
+  def create_new_instance(cls, pytest_config=None):
     web_ui_url = IMPALA_REMOTE_URL or DEFAULT_LOCAL_WEB_UI_URL
     if IMPALA_REMOTE_URL:
       # If IMPALA_REMOTE_URL is set, prefer detecting from the web UI.
@@ -287,7 +281,21 @@ class ImpalaTestClusterProperties(object):
     else:
       build_flavor, link_type =\
           
ImpalaTestClusterFlagsDetector.detect_using_build_root_or_web_ui(IMPALA_HOME)
-    cls._instance = ImpalaTestClusterProperties(build_flavor, link_type, 
web_ui_url)
+    return ImpalaTestClusterProperties(
+      build_flavor, link_type, web_ui_url, pytest_config=pytest_config)
+
+  @classmethod
+  def get_instance(cls, pytest_config=None):
+    """Implements lazy initialization of a singleton instance of this class. 
We cannot
+    initialize the instances when this module is imported because some 
dependencies may
+    not be available yet, e.g. the pytest config object. Thus we instead 
initialize it
+    the first time that a test needs it."""
+    if cls._instance is not None:
+      return cls._instance
+
+    assert pytest_config is not None, (
+      "Initial pytest_config must be provided for singleton")
+    cls._instance = cls.create_new_instance(pytest_config)
     return cls._instance
 
   @property
@@ -304,6 +312,10 @@ class ImpalaTestClusterProperties(object):
     """
     return self._library_link_type
 
+  def pytest_config(self):
+    """Return pytest config object."""
+    return self._pytest_config
+
   def has_code_coverage(self):
     """
     Return whether the Impala under test was compiled with code coverage 
enabled.
@@ -364,10 +376,10 @@ class ImpalaTestClusterProperties(object):
     This should only be called from python tests once pytest has been 
initialised
     and pytest command line arguments are available.
     """
-    assert hasattr(pytest, 'config'), "Must only be called from Python tests"
+    assert self._pytest_config is not None, "Must only be called from Python 
tests"
     # A remote cluster build can be indicated in multiple ways.
-    return (IMPALA_REMOTE_URL or os.getenv("REMOTE_LOAD") or
-            pytest.config.option.testing_remote_cluster)
+    return (IMPALA_REMOTE_URL or os.getenv("REMOTE_LOAD")
+            or self._pytest_config.option.testing_remote_cluster)
 
   @property
   def runtime_flags(self):
@@ -439,6 +451,7 @@ class ImpalaTestClusterProperties(object):
         return False
       raise
 
+
 def build_flavor_timeout(default_timeout, slow_build_timeout=None,
         asan_build_timeout=None, code_coverage_build_timeout=None):
   """
@@ -463,7 +476,8 @@ def build_flavor_timeout(default_timeout, 
slow_build_timeout=None,
   code_coverage_build_timeout - timeout to use if Impala with code coverage is 
running
   (both debug and release code coverage)
   """
-  cluster_properties = ImpalaTestClusterProperties.get_instance()
+  # Create new instance to avoid issues with pytest config not being available 
yet.
+  cluster_properties = ImpalaTestClusterProperties.create_new_instance()
   if cluster_properties.is_asan() and asan_build_timeout is not None:
     timeout_val = asan_build_timeout
   elif cluster_properties.has_code_coverage() and\
diff --git a/tests/common/impala_test_suite.py 
b/tests/common/impala_test_suite.py
index f59b4185d..233465a0d 100644
--- a/tests/common/impala_test_suite.py
+++ b/tests/common/impala_test_suite.py
@@ -47,7 +47,8 @@ from tests.common.environ import (
     HIVE_MAJOR_VERSION,
     MANAGED_WAREHOUSE_DIR,
     EXTERNAL_WAREHOUSE_DIR,
-    ICEBERG_DEFAULT_FORMAT_VERSION)
+    ICEBERG_DEFAULT_FORMAT_VERSION,
+    ImpalaTestClusterProperties)
 from tests.common.errors import Timeout
 from tests.common.impala_connection import create_connection
 from tests.common.impala_service import ImpaladService
@@ -123,7 +124,8 @@ if IS_ADLS:
   except ImportError:
     LOG.error("Need the ADLSClient for testing with ADLS")
 
-IMPALAD_HOST_PORT_LIST = pytest.config.option.impalad.split(',')
+PYTEST_CONFIG = ImpalaTestClusterProperties.get_instance().pytest_config()
+IMPALAD_HOST_PORT_LIST = PYTEST_CONFIG.option.impalad.split(',')
 assert len(IMPALAD_HOST_PORT_LIST) > 0, 'Must specify at least 1 impalad to 
target'
 IMPALAD = IMPALAD_HOST_PORT_LIST[0]
 IMPALAD_HOSTNAME = IMPALAD.split(':')[0]
@@ -132,7 +134,7 @@ IMPALAD_BEESWAX_PORT_LIST = [int(s.split(':')[1]) for s in 
IMPALAD_HOST_PORT_LIS
 IMPALAD_BEESWAX_PORT = IMPALAD_BEESWAX_PORT_LIST[0]
 IMPALAD_BEESWAX_HOST_PORT = IMPALAD_HOST_PORT_LIST[0]
 
-IMPALAD_HS2_PORT = int(pytest.config.option.impalad_hs2_port)
+IMPALAD_HS2_PORT = int(PYTEST_CONFIG.option.impalad_hs2_port)
 IMPALAD_HS2_HOST_PORT = IMPALAD_HOSTNAME + ":" + str(IMPALAD_HS2_PORT)
 # Calculate the hs2 ports based on the first hs2 port and the deltas of the 
beeswax ports
 IMPALAD_HS2_HOST_PORT_LIST = [
@@ -141,7 +143,7 @@ IMPALAD_HS2_HOST_PORT_LIST = [
     for i in range(len(IMPALAD_HOST_PORT_LIST))
 ]
 
-IMPALAD_HS2_HTTP_PORT = int(pytest.config.option.impalad_hs2_http_port)
+IMPALAD_HS2_HTTP_PORT = int(PYTEST_CONFIG.option.impalad_hs2_http_port)
 IMPALAD_HS2_HTTP_HOST_PORT = IMPALAD_HOSTNAME + ":" + 
str(IMPALAD_HS2_HTTP_PORT)
 # Calculate the hs2-http ports based on the first hs2-http port and the deltas 
of the
 # beeswax ports
@@ -152,12 +154,12 @@ IMPALAD_HS2_HTTP_HOST_PORT_LIST = [
 ]
 
 STRICT_HS2_HOST_PORT =\
-    IMPALAD_HOSTNAME + ":" + pytest.config.option.strict_hs2_port
+    IMPALAD_HOSTNAME + ":" + PYTEST_CONFIG.option.strict_hs2_port
 STRICT_HS2_HTTP_HOST_PORT =\
-    IMPALAD_HOSTNAME + ":" + pytest.config.option.strict_hs2_http_port
-HIVE_HS2_HOST_PORT = pytest.config.option.hive_server2
+    IMPALAD_HOSTNAME + ":" + PYTEST_CONFIG.option.strict_hs2_http_port
+HIVE_HS2_HOST_PORT = PYTEST_CONFIG.option.hive_server2
 WORKLOAD_DIR = os.environ['IMPALA_WORKLOAD_DIR']
-HDFS_CONF = HdfsConfig(pytest.config.option.minicluster_xml_conf)
+HDFS_CONF = HdfsConfig(PYTEST_CONFIG.option.minicluster_xml_conf)
 TARGET_FILESYSTEM = os.getenv("TARGET_FILESYSTEM") or "hdfs"
 IMPALA_HOME = os.getenv("IMPALA_HOME")
 INTERNAL_LISTEN_HOST = os.getenv("INTERNAL_LISTEN_HOST")
@@ -217,7 +219,7 @@ class ImpalaTestSuite(BaseTestSuite):
   @classmethod
   def default_test_protocol(cls):
     """This method is used to allow test subclasses to override
-    pytest.config.option.default_test_protocol as the default 'protocol' 
dimension.
+    cls.pytest_config().option.default_test_protocol as the default 'protocol' 
dimension.
     If subclass override this method, return value must either be 'beeswax', 
'hs2',
     or 'hs2-http'.
     The protocol kind of self.client is always match with return value of this 
method.
@@ -232,27 +234,27 @@ class ImpalaTestSuite(BaseTestSuite):
     - create_impala_client_from_vector()
     Most method in ImpalaTestSuite that has optional 'protocol' argument will 
default
     to the return value of this method.
-    Default to return pytest.config.option.default_test_protocol."""
+    Default to return cls.pytest_config().option.default_test_protocol."""
     # default_test_protocol is usually 'beeswax', unless user specify 
otherwise.
     # Individual tests that have been converted to work with the HS2 client 
can add HS2
     # in addition to or instead of beeswax.
-    return pytest.config.option.default_test_protocol
+    return cls.pytest_config().option.default_test_protocol
 
   @staticmethod
   def create_hive_client(port=None):
     """
     Creates a HMS client to a external running metastore service.
     """
-    metastore_host, metastore_port = 
pytest.config.option.metastore_server.split(':')
+    metastore_host, metastore_port = 
PYTEST_CONFIG.option.metastore_server.split(':')
     if port is not None:
       metastore_port = port
     trans_type = 'buffered'
-    if pytest.config.option.use_kerberos:
+    if PYTEST_CONFIG.option.use_kerberos:
       trans_type = 'kerberos'
     hive_transport = create_transport(
       host=metastore_host,
       port=metastore_port,
-      service=pytest.config.option.hive_service_name,
+      service=PYTEST_CONFIG.option.hive_service_name,
       transport_type=trans_type)
     protocol = TBinaryProtocol.TBinaryProtocol(hive_transport)
     hive_client = ThriftHiveMetastore.Client(protocol)
@@ -387,8 +389,9 @@ class ImpalaTestSuite(BaseTestSuite):
       host = cls.impalad_test_service.external_interface
       host_port = to_host_port(host, cls._get_default_port(protocol))
     use_ssl = cls.impalad_test_service.use_ssl_for_clients()
+    use_kerberos = cls.pytest_config().option.use_kerberos
     client = create_connection(
-        host_port=host_port, use_kerberos=pytest.config.option.use_kerberos,
+        host_port=host_port, use_kerberos=use_kerberos,
         protocol=protocol, is_hive=is_hive, user=user, use_ssl=use_ssl)
     client.connect()
     return client
@@ -511,10 +514,10 @@ class ImpalaTestSuite(BaseTestSuite):
 
   @classmethod
   def create_hdfs_client(cls):
-    if pytest.config.option.namenode_http_address is None:
+    if cls.pytest_config().option.namenode_http_address is None:
       webhdfs_client = get_webhdfs_client_from_conf(HDFS_CONF)
     else:
-      host, port = pytest.config.option.namenode_http_address.split(":")
+      host, port = cls.pytest_config().option.namenode_http_address.split(":")
       webhdfs_client = get_webhdfs_client(host, port)
     return DelegatingHdfsClient(webhdfs_client, HadoopFsCommandLineClient())
 
@@ -750,7 +753,8 @@ class ImpalaTestSuite(BaseTestSuite):
               '$DATABASE', use_db)
     result_section, type_section = 'RESULTS', 'TYPES'
     verify_raw_results(test_section, result, vector,
-                       result_section, type_section, 
pytest.config.option.update_results,
+                       result_section, type_section,
+                       self.pytest_config().option.update_results,
                        replace_filenames_with_placeholder)
 
   def run_test_case(self, test_file_name, vector, use_db=None, 
multiple_impalad=False,
@@ -790,7 +794,7 @@ class ImpalaTestSuite(BaseTestSuite):
     for impalad_client in target_impalad_clients:
       ImpalaTestSuite.__change_client_database(
         impalad_client, table_format=table_format_info, db_name=use_db,
-        scale_factor=pytest.config.option.scale_factor)
+        scale_factor=self.pytest_config().option.scale_factor)
       impalad_client.set_configuration(exec_options)
 
     def __exec_in_impala(query, user=None):
@@ -927,7 +931,7 @@ class ImpalaTestSuite(BaseTestSuite):
         # If --update_results, then replace references to the namenode URI 
with $NAMENODE.
         # TODO(todd) consider running do_replacements in reverse, though that 
may cause
         # some false replacements for things like username.
-        if pytest.config.option.update_results and 'RESULTS' in test_section:
+        if self.pytest_config().option.update_results and 'RESULTS' in 
test_section:
           test_section['RESULTS'] = test_section['RESULTS'] \
               .replace(NAMENODE, '$NAMENODE') \
               .replace(IMPALA_HOME, '$IMPALA_HOME') \
@@ -946,10 +950,10 @@ class ImpalaTestSuite(BaseTestSuite):
             # only do test_file_vars replacement if it exist.
             test_section[rt_profile_info] = self.__do_replacements(
                 test_section[rt_profile_info], extra=test_file_vars)
-          rt_profile = verify_runtime_profile(test_section[rt_profile_info],
-              result.runtime_profile,
-              update_section=pytest.config.option.update_results)
-          if pytest.config.option.update_results:
+          rt_profile = verify_runtime_profile(
+            test_section[rt_profile_info], result.runtime_profile,
+            update_section=self.pytest_config().option.update_results)
+          if self.pytest_config().option.update_results:
             test_section[rt_profile_info] = "".join(rt_profile)
 
         if 'LINEAGE' in test_section:
@@ -960,7 +964,7 @@ class ImpalaTestSuite(BaseTestSuite):
           assert current_query_lineage != "", (
               "No lineage found for query {} in dir {}".format(
                 result.query_id, lineage_log_dir))
-          if pytest.config.option.update_results:
+          if self.pytest_config().option.update_results:
             test_section['LINEAGE'] = json.dumps(current_query_lineage, 
indent=2,
                 separators=(',', ': '))
           else:
@@ -974,22 +978,22 @@ class ImpalaTestSuite(BaseTestSuite):
           dml_results_query = "select * from %s limit 1000" % \
               test_section['DML_RESULTS_TABLE']
           dml_result = exec_fn(dml_results_query)
-          verify_raw_results(test_section, dml_result, vector,
-                             result_section='DML_RESULTS',
-                             
update_section=pytest.config.option.update_results)
+          verify_raw_results(
+            test_section, dml_result, vector, result_section='DML_RESULTS',
+            update_section=self.pytest_config().option.update_results)
       except Exception as e:
         # When the calcite report mode is off, fail fast when hitting an error.
-        if not pytest.config.option.calcite_report_mode:
+        if not self.pytest_config().option.calcite_report_mode:
           raise
         current_error = str(e)
         failed_count += 1
       finally:
-        if pytest.config.option.calcite_report_mode:
+        if self.pytest_config().option.calcite_report_mode:
           result_list.append({"section": test_section, "error": current_error})
         total_count += 1
 
     # Write out the output information
-    if pytest.config.option.calcite_report_mode:
+    if self.pytest_config().option.calcite_report_mode:
       report = {}
       report["test_node_id"] = tests.common.nodeid
       report["test_file"] = os.path.join("testdata", "workloads", 
self.get_workload(),
@@ -998,7 +1002,7 @@ class ImpalaTestSuite(BaseTestSuite):
       # The node ids are unique, so there should not be hash collisions
       nodeid_hash = hashlib.sha256(tests.common.nodeid.encode()).hexdigest()
       output_file = "output_{0}.json".format(nodeid_hash)
-      output_directory = pytest.config.option.calcite_report_output_dir
+      output_directory = self.pytest_config().option.calcite_report_output_dir
       if output_directory is None:
         output_directory = os.path.join(IMPALA_LOGS_DIR, "calcite_report")
       if not os.path.exists(output_directory):
@@ -1011,7 +1015,7 @@ class ImpalaTestSuite(BaseTestSuite):
       if failed_count != 0:
         raise Exception("{0} out of {1} tests failed".format(failed_count, 
total_count))
 
-    if pytest.config.option.update_results:
+    if self.pytest_config().option.update_results:
       # Print updated test results to path like
       # 
$EE_TEST_LOGS_DIR/impala_updated_results/tpcds/queries/tpcds-decimal_v2-q98.test
       output_file = os.path.join(
@@ -1344,8 +1348,8 @@ class ImpalaTestSuite(BaseTestSuite):
 
   def run_impala_stmt_in_beeline(self, stmt, username=None, 
default_db='default'):
     """ Run a statement in impala by Beeline. """
-    url = 'jdbc:hive2://localhost:' + pytest.config.option.impalad_hs2_port + 
'/'\
-      + default_db + ";auth=noSasl"
+    url = ('jdbc:hive2://localhost:' + 
self.pytest_config().option.impalad_hs2_port
+           + '/' + default_db + ";auth=noSasl")
     return self.run_stmt_in_beeline(url, username, stmt)
 
   # TODO(todd) make this use Thrift to connect to HS2 instead of shelling
@@ -1354,7 +1358,7 @@ class ImpalaTestSuite(BaseTestSuite):
   def run_stmt_in_hive(cls, stmt, username=None):
     """Run a statement in Hive by Beeline."""
     LOG.info("-- executing in HiveServer2\n\n" + stmt + "\n")
-    url = 'jdbc:hive2://' + pytest.config.option.hive_server2
+    url = 'jdbc:hive2://' + cls.pytest_config().option.hive_server2
     return cls.run_stmt_in_beeline(url, username, stmt)
 
   @classmethod
@@ -1407,9 +1411,9 @@ class ImpalaTestSuite(BaseTestSuite):
   def create_table_info_dimension(cls, exploration_strategy):
     # If the user has specified a specific set of table formats to run 
against, then
     # use those. Otherwise, load from the workload test vectors.
-    if pytest.config.option.table_formats:
+    if cls.pytest_config().option.table_formats:
       table_formats = list()
-      for tf in pytest.config.option.table_formats.split(','):
+      for tf in cls.pytest_config().option.table_formats.split(','):
         dataset = get_dataset_from_workload(cls.get_workload())
         table_formats.append(TableFormatInfo.create_from_string(dataset, tf))
       tf_dimensions = ImpalaTestDimension(TABLE_FORMAT, *table_formats)
@@ -1417,7 +1421,7 @@ class ImpalaTestSuite(BaseTestSuite):
       tf_dimensions = load_table_info_dimension(cls.get_workload(), 
exploration_strategy)
     # If 'skip_hbase' is specified or the filesystem is isilon, s3, GCS(gs), 
COS(cosn) or
     # local, we don't need the hbase dimension.
-    if pytest.config.option.skip_hbase or TARGET_FILESYSTEM.lower() \
+    if cls.pytest_config().option.skip_hbase or TARGET_FILESYSTEM.lower() \
         in ['s3', 'isilon', 'local', 'abfs', 'adls', 'gs', 'cosn', 'ozone', 
'obs']:
       for tf_dimension in tf_dimensions:
         if tf_dimension.value.file_format == "hbase":
@@ -1447,9 +1451,10 @@ class ImpalaTestSuite(BaseTestSuite):
   #       clear how it should be used (IMPALA-13929)
   @classmethod
   def exploration_strategy(cls):
-    default_strategy = pytest.config.option.exploration_strategy
-    if pytest.config.option.workload_exploration_strategy:
-      workload_strategies = 
pytest.config.option.workload_exploration_strategy.split(',')
+    default_strategy = cls.pytest_config().option.exploration_strategy
+    if cls.pytest_config().option.workload_exploration_strategy:
+      strategy = cls.pytest_config().option.workload_exploration_strategy
+      workload_strategies = strategy.split(',')
       for workload_strategy in workload_strategies:
         workload_strategy = workload_strategy.split(':')
         if len(workload_strategy) != 2:
diff --git a/tests/common/kudu_test_suite.py b/tests/common/kudu_test_suite.py
index a9d381846..af3b73f98 100644
--- a/tests/common/kudu_test_suite.py
+++ b/tests/common/kudu_test_suite.py
@@ -18,7 +18,6 @@
 from __future__ import absolute_import, division, print_function
 from builtins import range
 import os
-import pytest
 import requests
 import string
 from contextlib import contextmanager
@@ -39,6 +38,7 @@ from kudu.client import Partitioning
 from random import choice, sample
 from string import ascii_lowercase, digits
 
+from tests.common.environ import ImpalaTestClusterProperties
 from tests.common.impala_test_suite import ImpalaTestSuite
 from tests.common.test_dimensions import HS2, create_kudu_dimension
 
@@ -46,7 +46,8 @@ DEFAULT_KUDU_MASTER_WEBUI_PORT = 
os.getenv('KUDU_MASTER_WEBUI_PORT', '8051')
 
 
 def get_kudu_master_webpage(page_name):
-  kudu_master = pytest.config.option.kudu_master_hosts
+  pytest_config = ImpalaTestClusterProperties.get_instance().pytest_config()
+  kudu_master = pytest_config.option.kudu_master_hosts
 
   if "," in kudu_master:
     raise NotImplementedError("Multi-master not supported yet")
diff --git a/tests/common/skip.py b/tests/common/skip.py
index a2fcb0737..4b2a0f87e 100644
--- a/tests/common/skip.py
+++ b/tests/common/skip.py
@@ -113,7 +113,8 @@ class SkipIfKudu:
 
 
 class SkipIf:
-  skip_hbase = pytest.mark.skipif(pytest.config.option.skip_hbase,
+  skip_hbase = pytest.mark.skipif(
+      IMPALA_TEST_CLUSTER_PROPERTIES.pytest_config().option.skip_hbase,
       reason="--skip_hbase argument specified")
   not_s3 = pytest.mark.skipif(not IS_S3, reason="S3 Filesystem needed")
   not_hdfs = pytest.mark.skipif(not IS_HDFS, reason="HDFS admin needed")
@@ -164,7 +165,8 @@ class SkipIfNotHdfsMinicluster:
       or IS_EC or IMPALA_TEST_CLUSTER_PROPERTIES.is_remote_cluster(),
       reason="Test is tuned for 3-node HDFS minicluster with no EC")
   scheduling = pytest.mark.skipif(
-      not (IS_HDFS or IS_OZONE) or IS_EC or 
pytest.config.option.testing_remote_cluster,
+      not (IS_HDFS or IS_OZONE) or IS_EC
+      or 
IMPALA_TEST_CLUSTER_PROPERTIES.pytest_config().option.testing_remote_cluster,
       reason="Test is tuned for scheduling decisions made on a 3-node HDFS 
minicluster "
              "with no EC")
 
diff --git a/tests/common/test_dimensions.py b/tests/common/test_dimensions.py
index 4137347f9..800cb3a48 100644
--- a/tests/common/test_dimensions.py
+++ b/tests/common/test_dimensions.py
@@ -23,8 +23,8 @@ from itertools import product
 import os
 
 from builtins import range
-import pytest
 
+from tests.common.environ import ImpalaTestClusterProperties
 from tests.common.test_vector import (
     assert_exec_option_key,
     BEESWAX,
@@ -166,7 +166,8 @@ def create_kudu_dimension(workload):
 
 
 def default_client_protocol_dimension():
-  return ImpalaTestDimension(PROTOCOL, 
pytest.config.option.default_test_protocol)
+  pytest_config = ImpalaTestClusterProperties.get_instance().pytest_config()
+  return ImpalaTestDimension(PROTOCOL, 
pytest_config.option.default_test_protocol)
 
 
 def hs2_client_protocol_dimension():
@@ -174,8 +175,9 @@ def hs2_client_protocol_dimension():
 
 
 def create_client_protocol_dimension():
+  pytest_config = ImpalaTestClusterProperties.get_instance().pytest_config()
   protocols_to_test = [HS2]
-  if pytest.config.option.default_test_protocol == BEESWAX:
+  if pytest_config.option.default_test_protocol == BEESWAX:
     protocols_to_test.append(BEESWAX)
   # IMPALA-8864: Older python versions do not support SSLContext object that 
the thrift
   # http client implementation depends on. Otherwise, include HS2_HTTP.
@@ -205,7 +207,8 @@ def create_client_protocol_no_strict_dimension():
 def default_protocol_or_parquet_constraint(v):
   """Constraint function, used to limit non-default test protocol against 
uncompressed
   parquet format, because file format and the client protocol are 
orthogonal."""
-  return (v.get_protocol() == pytest.config.option.default_test_protocol
+  pytest_config = ImpalaTestClusterProperties.get_instance().pytest_config()
+  return (v.get_protocol() == pytest_config.option.default_test_protocol
           or (v.get_table_format().file_format == 'parquet'
               and v.get_table_format().compression_codec == 'none'))
 
@@ -213,7 +216,8 @@ def default_protocol_or_parquet_constraint(v):
 def default_protocol_or_text_constraint(v):
   """Constraint function, used to limit non-default test protocol against 
uncompressed
   text format, because file format and the client protocol are orthogonal."""
-  return (v.get_protocol() == pytest.config.option.default_test_protocol
+  pytest_config = ImpalaTestClusterProperties.get_instance().pytest_config()
+  return (v.get_protocol() == pytest_config.option.default_test_protocol
           or (v.get_table_format().file_format == 'text'
               and v.get_table_format().compression_codec == 'none'))
 
diff --git a/tests/conftest.py b/tests/conftest.py
index 4d395b658..c10f0bc2c 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -67,10 +67,17 @@ PYTEST_TIMEOUT_S = \
 
 
 def pytest_configure(config):
-  """ Hook startup of pytest. Sets up log format and per-test timeout. """
+  """ Hook startup of pytest. Sets up log format,per-test timeout,
+  and ImpalaTestClusterProperties singleton."""
   configure_logging()
   config.option.timeout = PYTEST_TIMEOUT_S
 
+  # Initialize the ImpalaTestClusterProperties singleton.
+  # Don't import at top level to avoid circular dependency between conftest and
+  # tests.common.environ, which uses command-line flags set up by conftest.
+  from tests.common.environ import ImpalaTestClusterProperties
+  ImpalaTestClusterProperties.get_instance(config)
+
 
 def configure_logging():
   # Use a "--" since most of our tests output SQL commands, and it's nice to
@@ -454,11 +461,11 @@ def unique_name(request, testid_checksum):
 
 
 @pytest.yield_fixture
-def kudu_client():
+def kudu_client(request):
   """Provides a new Kudu client as a pytest fixture. The client only exists 
for the
      duration of the method it is used in.
   """
-  kudu_master = pytest.config.option.kudu_master_hosts
+  kudu_master = request.config.option.kudu_master_hosts
 
   if "," in kudu_master:
     raise Exception("Multi-master not supported yet")
@@ -498,10 +505,10 @@ def conn(request):
   timeout = __call_cls_method_if_exists(request.cls, "get_conn_timeout") or \
       DEFAULT_CONN_TIMEOUT
   if use_unique_conn:
-    with __unique_conn(db_name=db_name, timeout=timeout) as conn:
+    with __unique_conn(request.config, db_name=db_name, timeout=timeout) as 
conn:
       yield conn
   else:
-    with __auto_closed_conn(db_name=db_name, timeout=timeout) as conn:
+    with __auto_closed_conn(request.config, db_name=db_name, timeout=timeout) 
as conn:
       yield conn
 
 
@@ -515,7 +522,7 @@ def __call_cls_method_if_exists(cls, method_name):
 
 
 @contextlib.contextmanager
-def __unique_conn(db_name=None, timeout=DEFAULT_CONN_TIMEOUT):
+def __unique_conn(pytest_config, db_name=None, timeout=DEFAULT_CONN_TIMEOUT):
   """Connects to Impala and creates a new database, then returns a connection 
to it.
      This is intended to be used in a "with" block. Upon exit, the database 
will be
      dropped. A database name can be provided by 'db_name', a database by that 
name
@@ -533,10 +540,10 @@ def __unique_conn(db_name=None, 
timeout=DEFAULT_CONN_TIMEOUT):
   """
   if not db_name:
     db_name = choice(ascii_lowercase) + "".join(sample(ascii_lowercase + 
digits, 5))
-  with __auto_closed_conn(timeout=timeout) as conn:
+  with __auto_closed_conn(pytest_config, timeout=timeout) as conn:
     with __auto_closed_cursor(conn) as cur:
       cur.execute("CREATE DATABASE %s" % db_name)
-  with __auto_closed_conn(db_name=db_name, timeout=timeout) as conn:
+  with __auto_closed_conn(pytest_config, db_name=db_name, timeout=timeout) as 
conn:
     try:
       yield conn
     finally:
@@ -552,7 +559,7 @@ def __unique_conn(db_name=None, 
timeout=DEFAULT_CONN_TIMEOUT):
 
 
 @contextlib.contextmanager
-def __auto_closed_conn(db_name=None, timeout=DEFAULT_CONN_TIMEOUT):
+def __auto_closed_conn(pytest_config, db_name=None, 
timeout=DEFAULT_CONN_TIMEOUT):
   """Returns a connection to Impala. This is intended to be used in a "with" 
block.
      The connection will be closed upon exiting the block.
 
@@ -562,9 +569,9 @@ def __auto_closed_conn(db_name=None, 
timeout=DEFAULT_CONN_TIMEOUT):
      See the 'unique_database' fixture above to use Impala's custom python
      API instead of DB-API.
   """
-  default_impalad = pytest.config.option.impalad.split(',')[0]
+  default_impalad = pytest_config.option.impalad.split(',')[0]
   impalad_host = default_impalad.split(':')[0]
-  hs2_port = pytest.config.option.impalad_hs2_port
+  hs2_port = pytest_config.option.impalad_hs2_port
 
   conn = impala_connect(host=impalad_host, port=hs2_port, database=db_name,
                         timeout=timeout)
@@ -611,7 +618,7 @@ def cls_cursor(conn):
 
 
 @pytest.yield_fixture
-def unique_cursor():
+def unique_cursor(request):
   """Provides a new DB-API compliant cursor to a newly created Impala 
database. The
      cursor only exists for the duration of the method it is used in. The 
database will
      be dropped after the test executes.
@@ -623,7 +630,7 @@ def unique_cursor():
      See the 'unique_database' fixture above to use Impala's custom python
      API instead of DB-API.
   """
-  with __unique_conn() as conn:
+  with __unique_conn(request.config) as conn:
     with __auto_closed_cursor(conn) as cur:
       yield cur
 
@@ -662,13 +669,13 @@ def impala_testinfra_cursor():
 
 
 @pytest.fixture(autouse=True, scope='session')
-def validate_pytest_config():
+def validate_pytest_config(request):
   """
   Validate that pytest command line options make sense.
   """
-  if pytest.config.option.testing_remote_cluster:
+  if request.config.option.testing_remote_cluster:
     local_prefixes = ('localhost', '127.', '0.0.0.0')
-    if any(pytest.config.option.impalad.startswith(loc) for loc in 
local_prefixes):
+    if any(request.config.option.impalad.startswith(loc) for loc in 
local_prefixes):
       logging.error("--testing_remote_cluster can not be used with a local 
impalad")
       pytest.exit("Invalid pytest config option: --testing_remote_cluster")
 
diff --git a/tests/custom_cluster/test_event_processing_perf.py 
b/tests/custom_cluster/test_event_processing_perf.py
index 78ee1cdf4..1123999e1 100644
--- a/tests/custom_cluster/test_event_processing_perf.py
+++ b/tests/custom_cluster/test_event_processing_perf.py
@@ -274,9 +274,10 @@ class TestEventProcessingPerf(CustomClusterTestSuite):
     test_self = self
 
     class ThreadLocalClient(threading.local):
-      def __init__(self, is_hive):
+      def __init__(self, is_hive, hive_server2_host_port):
         # called for main thread and each thread in the pool
         self.is_hive = is_hive
+        self.hive_server2_host_port = hive_server2_host_port
         self.name = threading.currentThread().name
         LOG.info("Initializing for thread %s", self.name)
 
@@ -308,7 +309,7 @@ class TestEventProcessingPerf(CustomClusterTestSuite):
           is_hive = False
 
         if is_hive:
-          with 
test_self.create_impala_client(host_port=pytest.config.option.hive_server2,
+          with 
test_self.create_impala_client(host_port=self.hive_server2_host_port,
                                               protocol=HS2,
                                               is_hive=is_hive) as hive_client:
             for query in query.split(';'):
@@ -324,7 +325,7 @@ class TestEventProcessingPerf(CustomClusterTestSuite):
               LOG.debug(e)
 
     pool = multiprocessing.pool.ThreadPool(processes=8)
-    with ThreadLocalClient(is_hive) as tls:
+    with ThreadLocalClient(is_hive, self.pytest_config().option.hive_server2) 
as tls:
       dbs = []
       for iter in range(self.db_count):
         dbs.append(self.db_prefix + str(iter))
diff --git a/tests/custom_cluster/test_insert_behaviour.py 
b/tests/custom_cluster/test_insert_behaviour.py
index 77937450c..7cce54d93 100644
--- a/tests/custom_cluster/test_insert_behaviour.py
+++ b/tests/custom_cluster/test_insert_behaviour.py
@@ -37,11 +37,11 @@ class 
TestInsertBehaviourCustomCluster(CustomClusterTestSuite):
   @classmethod
   def setup_class(cls):
     super(TestInsertBehaviourCustomCluster, cls).setup_class()
-    if pytest.config.option.namenode_http_address is None:
-      hdfs_conf = HdfsConfig(pytest.config.option.minicluster_xml_conf)
+    if cls.pytest_config().option.namenode_http_address is None:
+      hdfs_conf = HdfsConfig(cls.pytest_config().option.minicluster_xml_conf)
       cls.hdfs_client = get_webhdfs_client_from_conf(hdfs_conf)
     else:
-      host, port = pytest.config.option.namenode_http_address.split(":")
+      host, port = cls.pytest_config().option.namenode_http_address.split(":")
       cls.hdfs_client = get_webhdfs_client(host, port)
 
   def _check_partition_perms(self, part, perms):
diff --git a/tests/custom_cluster/test_kudu.py 
b/tests/custom_cluster/test_kudu.py
index d87534b03..9db2e08fd 100644
--- a/tests/custom_cluster/test_kudu.py
+++ b/tests/custom_cluster/test_kudu.py
@@ -23,15 +23,18 @@ from copy import deepcopy
 from kudu.schema import INT32
 
 from tests.common.custom_cluster_test_suite import CustomClusterTestSuite
+from tests.common.environ import ImpalaTestClusterProperties
 from tests.common.impala_connection import FINISHED, 
IMPALA_CONNECTION_EXCEPTION
 from tests.common.kudu_test_suite import KuduTestSuite
 from tests.common.skip import SkipIfKudu, SkipIfBuildType, SkipIf
 from tests.common.test_dimensions import HS2, add_mandatory_exec_option
 from tests.common.test_result_verifier import error_msg_startswith
 
-KUDU_MASTER_HOSTS = pytest.config.option.kudu_master_hosts
 LOG = logging.getLogger(__name__)
 
+IMPALA_TEST_CLUSTER_PROPERTIES = ImpalaTestClusterProperties.get_instance()
+KUDU_MASTER_HOSTS = \
+  IMPALA_TEST_CLUSTER_PROPERTIES.pytest_config().option.kudu_master_hosts
 
 class CustomKuduTest(CustomClusterTestSuite, KuduTestSuite):
 
diff --git a/tests/custom_cluster/test_saml2_sso.py 
b/tests/custom_cluster/test_saml2_sso.py
index 8b0dc7fad..c135dc048 100644
--- a/tests/custom_cluster/test_saml2_sso.py
+++ b/tests/custom_cluster/test_saml2_sso.py
@@ -20,7 +20,6 @@ from __future__ import absolute_import, division, 
print_function
 import base64
 import datetime
 import os
-import pytest
 import sys
 import uuid
 import xml.etree.ElementTree as ET
@@ -92,7 +91,6 @@ class TestClientSaml(CustomClusterTestSuite):
   SP_CALLBACK_URL = "http://localhost:28000/SAML2/SSO/POST";
   IDP_URL = "https://localhost:8443/simplesaml/saml2/idp/SSOService.php";
   CLIENT_PORT = 12345
-  HOST_PORT = pytest.config.option.impalad_hs2_http_port
   ASSERTATION_ERROR_MESSAGE = \
       "SAML assertion could not be validated. Check server logs for more 
details."
 
@@ -112,6 +110,10 @@ class TestClientSaml(CustomClusterTestSuite):
       "{} --saml2_group_filter=group1,group2 "
       "--saml2_group_attribute_name=eduPersonAffiliation").format(SSO_ARGS)
 
+  @classmethod
+  def hs2_http_port(cls):
+    return cls.pytest_config().option.impalad_hs2_http_port
+
   @CustomClusterTestSuite.with_args(impalad_args=SSO_ARGS, cluster_size=1)
   def test_saml2_browser_profile_no_group_filter(self, vector):
     # Iterate over test vector within test function to avoid restarting 
cluster.
@@ -166,7 +168,7 @@ class TestClientSaml(CustomClusterTestSuite):
         to IDP and contain the authnrequest. """
     opener = build_opener(NoRedirection)
     payload = encode_if_needed(" ")
-    req = Request("http://localhost:%s"; % TestClientSaml.HOST_PORT, payload)
+    req = Request("http://localhost:%s"; % self.hs2_http_port(), payload)
     req.add_header('X-Hive-Token-Response-Port', TestClientSaml.CLIENT_PORT)
     response = opener.open(req)
     relay_state, client_id, saml_req_xml = \
@@ -200,7 +202,7 @@ class TestClientSaml(CustomClusterTestSuite):
     """ Send POST request to hs2-http port again, this time with bearer tokan.
         The response should contain a security cookie if the validation 
succeeded """
     payload = encode_if_needed(" ")
-    req = Request("http://localhost:%s"; % TestClientSaml.HOST_PORT, payload)
+    req = Request("http://localhost:%s"; % self.hs2_http_port(), payload)
     req.add_header('X-Hive-Client-Identifier', client_id)
     req.add_header('Authorization', "Bearer " + bearer_token)
     opener = build_opener(NoRedirection)
diff --git a/tests/metadata/test_partition_metadata.py 
b/tests/metadata/test_partition_metadata.py
index 757468d96..4cf5460ae 100644
--- a/tests/metadata/test_partition_metadata.py
+++ b/tests/metadata/test_partition_metadata.py
@@ -126,8 +126,8 @@ class TestMixedPartitions(ImpalaTestSuite):
   @pytest.mark.parametrize('main_table_format', ['parquetfile', 'textfile'])
   def test_incompatible_avro_partition_in_non_avro_table(
       self, vector, unique_database, main_table_format):
-    if main_table_format == 'parquetfile' and \
-        not pytest.config.option.use_local_catalog:
+    if (main_table_format == 'parquetfile'
+        and not self.pytest_config().option.use_local_catalog):
       pytest.xfail("IMPALA-7309: adding an avro partition to a parquet table "
                    "changes its schema")
     self.run_test_case("QueryTest/incompatible_avro_partition", vector,
diff --git a/tests/query_test/test_kudu.py b/tests/query_test/test_kudu.py
index 2b659f127..1fbe5327c 100644
--- a/tests/query_test/test_kudu.py
+++ b/tests/query_test/test_kudu.py
@@ -59,8 +59,9 @@ from tests.common.test_dimensions import (
   create_single_exec_option_dimension)
 from tests.verifiers.metric_verifier import MetricVerifier
 
-KUDU_MASTER_HOSTS = pytest.config.option.kudu_master_hosts
 IMPALA_TEST_CLUSTER_PROPERTIES = ImpalaTestClusterProperties.get_instance()
+KUDU_MASTER_HOSTS = \
+  IMPALA_TEST_CLUSTER_PROPERTIES.pytest_config().option.kudu_master_hosts
 
 LOG = logging.getLogger(__name__)
 
diff --git a/tests/run-tests.py b/tests/run-tests.py
index 56a2602df..b63dc9bfc 100755
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -33,7 +33,8 @@ import os
 import pytest
 import sys
 from _pytest.main import EXIT_NOTESTSCOLLECTED
-from _pytest.config import FILE_OR_DIR
+# change to "from _pytest.config.argparsing import Parser" in pytest >= 6.2.0
+from _pytest.config import Parser
 
 # We whitelist valid test directories. If a new test directory is added, 
update this.
 VALID_TEST_DIRS = ['failure', 'query_test', 'stress', 'unittests', 
'aux_query_tests',
@@ -127,6 +128,13 @@ class TestExecutor(object):
       sys.exit(pytest_exit_code)
     self.tests_failed = 0 < pytest_exit_code < EXIT_NOTESTSCOLLECTED or 
self.tests_failed
 
+
+def get_explicit_tests(args):
+  pytest_arg_parser = Parser()
+  parsed_args = pytest_arg_parser.parse_known_args(args)
+  return parsed_args.file_or_dir
+
+
 def build_test_args(base_name, valid_dirs=VALID_TEST_DIRS):
   """
   Prepare the list of arguments that will be passed to pytest.main().
@@ -146,7 +154,7 @@ def build_test_args(base_name, valid_dirs=VALID_TEST_DIRS):
   - verifiers.test_verify_metrics.TestValidateMetrics.test_metrics_are_zero
   - verifiers.test_verify_metrics.TestValidateMetrics.test_num_unused_buffers
 
-  then we instead need to filter out args that specifiy other tests (otherwise,
+  then we instead need to filter out args that specify other tests (otherwise,
   they will be run again), but still retain the basic config args.
   """
 
@@ -177,20 +185,21 @@ def build_test_args(base_name, 
valid_dirs=VALID_TEST_DIRS):
     # to filter out any command line args that specify other test modules, 
classes,
     # and functions. The list of these can be found by calling
     #
-    #    pytest.config.getoption(FILE_OR_DIR)
+    #    _pytest.config.Parser().parse_known_args(commandline_args).file_or_dir
     #
+    # get_explicit_test() does this for us.
     # For example, with the following command line invocation:
     #
     # $ ./run-tests.py query_test/test_limit.py::TestLimit::test_limit \
     #   query_test/test_queries.py::TestHdfsQueries --verbose -n 4 \
     #   --table_formats=parquet/none --exploration_strategy core
     #
-    # then pytest.config.getoption(FILE_OR_DIR) will return a list of two 
elements:
+    # then get_explicit_test(commandline_args) will return a list of two 
elements:
     #
     # ['query_test/test_limit.py::TestLimit::test_limit',
     #  'query_test/test_queries.py::TestHdfsQueries']
     #
-    explicit_tests = pytest.config.getoption(FILE_OR_DIR)
+    explicit_tests = get_explicit_tests(commandline_args)
     config_options = [arg for arg in commandline_args if arg not in 
explicit_tests]
     # We also want to strip out any --shard_tests option and its corresponding 
value.
     while "--shard_tests" in config_options:
diff --git a/tests/shell/util.py b/tests/shell/util.py
index 0d4bd0b0b..16fee4509 100755
--- a/tests/shell/util.py
+++ b/tests/shell/util.py
@@ -360,15 +360,13 @@ def wait_for_query_state(vector, stmt, state, 
max_retry=15):
 
 # Returns shell executable, and whether to include pypi variants
 def get_dev_impala_shell_executable():
-  # Note that pytest.config.getoption is deprecated usage. We use this
-  # in a couple of other places. Ultimately, it needs to be addressed if
-  # we ever want to get off of pytest 2.9.2.
-  impala_shell_executable = pytest.config.getoption('shell_executable')
+  test_prop = ImpalaTestClusterProperties.get_instance()
+  impala_shell_executable = 
test_prop.pytest_config().getoption('shell_executable')
 
   if impala_shell_executable is not None:
     return impala_shell_executable, False
 
-  if ImpalaTestClusterProperties.get_instance().is_remote_cluster():
+  if test_prop.is_remote_cluster():
     # With remote cluster testing, we cannot assume that the shell was built 
locally.
     return os.path.join(IMPALA_HOME, "bin/impala-shell.sh"), False
   else:


Reply via email to