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

laiyingchun pushed a commit to branch branch-1.17.x
in repository https://gitbox.apache.org/repos/asf/kudu.git

commit 368b070fdfd16d45da400517dd9d3ee10180d5db
Author: Marton Greber <[email protected]>
AuthorDate: Mon Mar 20 11:01:14 2023 +0000

    [Python] Refactor tests to use assertRaisesRegex
    
    The Python unittest.TestCase class offers the assertRaises() and
    assertRaisesRegex() functions to test that an exception is raised when
    callable is called [1].
    
    Currently assertRaises(exception) is used in the Python
    client tests, to assert the type of a given error. This patch refactors
    usages of assertRaises() to assertRaisesRegex(exception, regex) in order
    to assert the error message as well.
    
    In Python3.2 assertRaisesRegexp has been renamed to assertRaisesRegex
    (without the trailing 'p') [2].  To be able to use assertRaisesRegex
    throughout the Python codebase, a compatibility class called
    CompatUnitTest is added.
    
    [1] https://docs.python.org/3/library/unittest.html#unittest.TestCase
    [2] https://docs.python.org/3.9/library/unittest.html
        #unittest.TestCase.assertRaisesRegex
    
    Change-Id: I41e2d69996ee0ed0f0418ae184d95239f2739efb
    Reviewed-on: http://gerrit.cloudera.org:8080/19633
    Tested-by: Kudu Jenkins
    Reviewed-by: Attila Bukor <[email protected]>
    (cherry picked from commit 08bd36a8745d20c5aa688f5c33a05615857d40e0)
    Reviewed-on: http://gerrit.cloudera.org:8080/19981
    Reviewed-by: Marton Greber <[email protected]>
    Reviewed-by: Yingchun Lai <[email protected]>
---
 python/kudu/compat.py               | 12 +++++-
 python/kudu/tests/test_client.py    | 58 +++++++++++++++++---------
 python/kudu/tests/test_scanner.py   |  1 -
 python/kudu/tests/test_scantoken.py |  1 -
 python/kudu/tests/test_schema.py    | 83 +++++++++++++++++++++++++------------
 python/kudu/tests/util.py           |  4 +-
 6 files changed, 108 insertions(+), 51 deletions(-)

diff --git a/python/kudu/compat.py b/python/kudu/compat.py
index c3343a6cb..6f8b415ce 100644
--- a/python/kudu/compat.py
+++ b/python/kudu/compat.py
@@ -18,7 +18,7 @@
 # flake8: noqa
 
 import itertools
-
+import contextlib
 try:
     import numpy as np
 except ImportError:
@@ -97,6 +97,16 @@ else:
         return list(o.items())
 
 
+if sys.version_info < (3, 1):
+    class CompatUnitTest(unittest.TestCase):
+        @contextlib.contextmanager
+        def assertRaisesRegex(self, expected_exception, expected_regex, *args, 
**kwargs):
+            with self.assertRaisesRegexp(expected_exception, expected_regex, 
*args, **kwargs):
+                yield
+else:
+    class CompatUnitTest(unittest.TestCase):
+        pass
+
 integer_types = six.integer_types
 if np is not None:
     integer_types += (np.integer,)
diff --git a/python/kudu/tests/test_client.py b/python/kudu/tests/test_client.py
index ce76a87d3..44d8e4a29 100755
--- a/python/kudu/tests/test_client.py
+++ b/python/kudu/tests/test_client.py
@@ -16,7 +16,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-from kudu.compat import unittest, long
+from kudu.compat import CompatUnitTest, long
 from kudu.tests.common import KuduTestBase
 from kudu.client import (Partitioning,
                          RangePartition,
@@ -32,7 +32,7 @@ import datetime
 from pytz import utc
 
 
-class TestClient(KuduTestBase, unittest.TestCase):
+class TestClient(KuduTestBase, CompatUnitTest):
 
     def setUp(self):
         pass
@@ -102,7 +102,8 @@ class TestClient(KuduTestBase, unittest.TestCase):
         assert not self.client.table_exists(name)
 
         # Should raise a more meaningful exception at some point
-        with self.assertRaises(kudu.KuduNotFound):
+        error_msg = 'the table does not exist: table_name: "{0}"'.format(name)
+        with self.assertRaisesRegex(kudu.KuduNotFound, error_msg):
             self.client.delete_table(name)
 
     def test_table_nonexistent(self):
@@ -476,10 +477,12 @@ class TestClient(KuduTestBase, unittest.TestCase):
             # inserts. In this case, at the second position it would like to 
get an int64 (the type
             # of the auto-incrementing counter), therefore we get type error. 
(Specifying the
             # auto-incremeintg counter is obviously rejected from the server 
side)
-            with self.assertRaises(TypeError):
+            error_msg = 'an integer is required'
+            with self.assertRaisesRegex(TypeError, error_msg):
                 op = table.new_insert((1,'text'))
 
-            with self.assertRaises(TypeError):
+            error_msg = 'an integer is required'
+            with self.assertRaisesRegex(TypeError, error_msg):
                 op = table.new_insert([1,'text'])
 
         finally:
@@ -534,8 +537,10 @@ class TestClient(KuduTestBase, unittest.TestCase):
         self.client.new_session(flush_mode='sync')
         self.client.new_session(flush_mode='background')
 
-        with self.assertRaises(ValueError):
-            self.client.new_session(flush_mode='foo')
+        flush_mode = 'foo'
+        error_msg = 'Invalid flush mode: {0}'.format(flush_mode)
+        with self.assertRaisesRegex(ValueError, error_msg):
+            self.client.new_session(flush_mode=flush_mode)
 
     def test_session_mutation_buffer_settings(self):
         self.client.new_session(flush_mode=kudu.FLUSH_AUTO_BACKGROUND,
@@ -553,16 +558,20 @@ class TestClient(KuduTestBase, unittest.TestCase):
     def test_session_mutation_buffer_errors(self):
         session = 
self.client.new_session(flush_mode=kudu.FLUSH_AUTO_BACKGROUND)
 
-        with self.assertRaises(OverflowError):
+        error_msg = 'can\'t convert negative value to unsigned int'
+        with self.assertRaisesRegex(OverflowError, error_msg):
             session.set_mutation_buffer_max_num(-1)
 
-        with self.assertRaises(kudu.errors.KuduInvalidArgument):
+        error_msg = '120: watermark must be between 0 and 100 inclusive'
+        with self.assertRaisesRegex(kudu.errors.KuduInvalidArgument, 
error_msg):
             session.set_mutation_buffer_flush_watermark(1.2)
 
-        with self.assertRaises(OverflowError):
+        error_msg = 'can\'t convert negative value to unsigned int'
+        with self.assertRaisesRegex(OverflowError, error_msg):
             session.set_mutation_buffer_flush_interval(-1)
 
-        with self.assertRaises(OverflowError):
+        error_msg = 'can\'t convert negative value to size_t'
+        with self.assertRaisesRegex(OverflowError, error_msg):
             session.set_mutation_buffer_space(-1)
 
     def test_connect_timeouts(self):
@@ -599,11 +608,13 @@ class TestClient(KuduTestBase, unittest.TestCase):
                 op[key[0]] = 'test'
 
         # Test incorrectly typed data
-        with self.assertRaises(TypeError):
+        error_msg = 'an integer is required'
+        with self.assertRaisesRegex(TypeError, error_msg):
             op['int_val'] = 'incorrect'
 
         # Test setting NULL in a not-null column
-        with self.assertRaises(kudu.errors.KuduInvalidArgument):
+        error_msg = 'column not nullable: key'
+        with self.assertRaisesRegex(kudu.errors.KuduInvalidArgument, 
error_msg):
             op['key'] = None
 
     def test_alter_table_rename(self):
@@ -821,22 +832,30 @@ class TestClient(KuduTestBase, unittest.TestCase):
             # negatives
             alterer = self.client.new_table_alterer(table)
             alterer.drop_column(col_name)
-            with self.assertRaises(KuduInvalidArgument):
+            error_msg = 'can\'t drop column: {0}'\
+                        .format(Schema.get_auto_incrementing_column_name())
+            with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
                 alterer.alter()
 
             alterer = self.client.new_table_alterer(table)
             alterer.add_column(col_name)
-            with self.assertRaises(KuduInvalidArgument):
+            error_msg = 'can\'t add a column with reserved name: {0}'\
+                        .format(Schema.get_auto_incrementing_column_name())
+            with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
                 alterer.alter()
 
             alterer = self.client.new_table_alterer(table)
             alterer.alter_column(col_name, "new_column_name")
-            with self.assertRaises(KuduInvalidArgument):
+            error_msg = 'can\'t change name for column: {0}'\
+                        .format(Schema.get_auto_incrementing_column_name())
+            with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
                 alterer.alter()
 
             alterer = self.client.new_table_alterer(table)
             alterer.alter_column(col_name).remove_default()
-            with self.assertRaises(KuduInvalidArgument):
+            error_msg = 'can\'t change remove default for column: {0}'\
+                        .format(Schema.get_auto_incrementing_column_name())
+            with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
                 alterer.alter()
 
             # positives
@@ -869,11 +888,12 @@ class TestClient(KuduTestBase, unittest.TestCase):
     def test_require_authn(self):
         # Kerberos is not enabled on the cluster, so requiring
         # authentication is expected to fail.
-        with self.assertRaises(kudu.KuduBadStatus):
+        error_msg = 'client requires authentication, but server does not have 
Kerberos enabled'
+        with self.assertRaisesRegex(kudu.KuduBadStatus, error_msg):
             client = kudu.connect(self.master_hosts, self.master_ports,
                      require_authentication=True)
 
-class TestMonoDelta(unittest.TestCase):
+class TestMonoDelta(CompatUnitTest):
 
     def test_empty_ctor(self):
         delta = kudu.TimeDelta()
diff --git a/python/kudu/tests/test_scanner.py 
b/python/kudu/tests/test_scanner.py
index fa406252d..c4d17839b 100644
--- a/python/kudu/tests/test_scanner.py
+++ b/python/kudu/tests/test_scanner.py
@@ -18,7 +18,6 @@
 
 from __future__ import division
 
-from kudu.compat import unittest
 from kudu.tests.util import TestScanBase
 from kudu.tests.common import KuduTestBase, TimeoutError
 import kudu
diff --git a/python/kudu/tests/test_scantoken.py 
b/python/kudu/tests/test_scantoken.py
index 9214adb98..c69b43a66 100644
--- a/python/kudu/tests/test_scantoken.py
+++ b/python/kudu/tests/test_scantoken.py
@@ -16,7 +16,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-from kudu.compat import unittest
 from kudu.tests.util import TestScanBase
 from kudu.tests.common import KuduTestBase
 import kudu
diff --git a/python/kudu/tests/test_schema.py b/python/kudu/tests/test_schema.py
index 069201f64..cbee07b1e 100644
--- a/python/kudu/tests/test_schema.py
+++ b/python/kudu/tests/test_schema.py
@@ -18,13 +18,13 @@
 
 from __future__ import division
 
-from kudu.compat import unittest
+from kudu.compat import CompatUnitTest
 from kudu.errors import KuduInvalidArgument
 import kudu
 
 from kudu.schema import Schema
 
-class TestSchema(unittest.TestCase):
+class TestSchema(CompatUnitTest):
 
     def setUp(self):
         self.columns = [('one', 'int32', False),
@@ -59,8 +59,10 @@ class TestSchema(unittest.TestCase):
         assert self.schema.primary_keys() == ['one', 'two']
 
     def test_getitem_boundschecking(self):
-        with self.assertRaises(IndexError):
-            self.schema[4]
+        idx = 4
+        error_msg = 'Column index {0} is not in range'.format(idx)
+        with self.assertRaisesRegex(IndexError, error_msg):
+            self.schema[idx]
 
     def test_getitem_wraparound(self):
         # wraparound
@@ -75,7 +77,8 @@ class TestSchema(unittest.TestCase):
 
         assert result.equals(expected)
 
-        with self.assertRaises(KeyError):
+        error_msg = 'not_found'
+        with self.assertRaisesRegex(KeyError, error_msg):
             self.schema['not_found']
 
     def test_schema_equals(self):
@@ -113,8 +116,10 @@ class TestSchema(unittest.TestCase):
         bar = builder.add_column('bar', 'string')
         bar.compression(kudu.COMPRESSION_ZLIB)
 
-        with self.assertRaises(ValueError):
-            bar = builder.add_column('qux', 'string', compression='unknown')
+        compression = 'unknown'
+        error_msg = 'Invalid compression type: {0}'.format(compression)
+        with self.assertRaisesRegex(ValueError, error_msg):
+            bar = builder.add_column('qux', 'string', compression=compression)
 
         builder.set_primary_keys(['key'])
         builder.build()
@@ -136,7 +141,8 @@ class TestSchema(unittest.TestCase):
         bar = builder.add_column('bar', 'string')
         bar.encoding(kudu.ENCODING_PLAIN)
 
-        with self.assertRaises(ValueError):
+        error_msg = 'Invalid encoding type'
+        with self.assertRaisesRegex(ValueError, error_msg):
             builder.add_column('qux', 'string', encoding='unknown')
 
         builder.set_primary_keys(['key'])
@@ -169,7 +175,8 @@ class TestSchema(unittest.TestCase):
          .primary_key()
          .nullable(False))
 
-        with self.assertRaises(kudu.KuduInvalidArgument):
+        error_msg = 'no precision provided for decimal column: key'
+        with self.assertRaisesRegex(kudu.KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_precision_on_non_decimal_column(self):
@@ -181,7 +188,8 @@ class TestSchema(unittest.TestCase):
          .precision(9)
          .scale(2))
 
-        with self.assertRaises(kudu.KuduInvalidArgument):
+        error_msg = 'precision is not valid on a 2 column: key'
+        with self.assertRaisesRegex(kudu.KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_date(self):
@@ -220,7 +228,8 @@ class TestSchema(unittest.TestCase):
          .primary_key()
          .nullable(False))
 
-        with self.assertRaises(kudu.KuduInvalidArgument):
+        error_msg = 'no length provided for VARCHAR column: key'
+        with self.assertRaisesRegex(kudu.KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_varchar_invalid_length(self):
@@ -231,7 +240,8 @@ class TestSchema(unittest.TestCase):
          .length(0)
          .nullable(False))
 
-        with self.assertRaises(kudu.KuduInvalidArgument):
+        error_msg = 'length must be between 1 and 65535: key'
+        with self.assertRaisesRegex(kudu.KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_length_on_non_varchar_column(self):
@@ -242,17 +252,20 @@ class TestSchema(unittest.TestCase):
          .nullable(False)
          .length(10))
 
-        with self.assertRaises(kudu.KuduInvalidArgument):
+        error_msg = 'no precision provided for decimal column: key'
+        with self.assertRaisesRegex(kudu.KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_unsupported_col_spec_methods_for_create_table(self):
         builder = kudu.schema_builder()
         builder.add_column('test', 'int64').rename('test')
-        with self.assertRaises(kudu.KuduNotSupported):
+        error_msg = 'cannot rename a column during CreateTable: test'
+        with self.assertRaisesRegex(kudu.KuduNotSupported, error_msg):
             builder.build()
 
         builder.add_column('test', 'int64').remove_default()
-        with self.assertRaises(kudu.KuduNotSupported):
+        error_msg = 'cannot rename a column during CreateTable: test'
+        with self.assertRaisesRegex(kudu.KuduNotSupported, error_msg):
             builder.build()
 
     def test_set_column_spec_pk(self):
@@ -352,7 +365,8 @@ class TestSchema(unittest.TestCase):
         builder.add_column('key1', 'int64').nullable(False)
         builder.add_column('key2', 'double').nullable(False)
         builder.set_non_unique_primary_keys(['key2', 'key1'])
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = 'primary key columns must be listed first in the schema: 
key'
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             schema = builder.build()
 
     def test_set_non_unique_primary_keys_not_first(self):
@@ -361,7 +375,8 @@ class TestSchema(unittest.TestCase):
         (builder.add_column('key', 'int64')
          .nullable(False))
         builder.set_non_unique_primary_keys(['key'])
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = 'primary key columns must be listed first in the schema: 
key'
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             schema = builder.build()
 
     def test_set_non_unique_primary_keys_same_name_twice(self):
@@ -370,7 +385,8 @@ class TestSchema(unittest.TestCase):
          .nullable(False))
         builder.add_column('data1', 'double')
         builder.set_non_unique_primary_keys(['key', 'key'])
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = 'primary key columns must be listed first in the schema: 
key'
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             schema = builder.build()
 
     def test_unique_and_non_unique_primary_key_on_same_column(self):
@@ -403,7 +419,8 @@ class TestSchema(unittest.TestCase):
         (builder.add_column('key', 'double')
          .nullable(False)
          .non_unique_primary_key())
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = 'primary key column must be the first column'
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_unique_and_non_unique_primary_key_on_different_cols(self):
@@ -414,7 +431,8 @@ class TestSchema(unittest.TestCase):
         (builder.add_column('key2', 'double')
          .nullable(False)
          .non_unique_primary_key())
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = 'multiple columns specified for primary key: key1, key2'
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_non_unique_and_unique_primary_key_on_different_cols(self):
@@ -425,7 +443,8 @@ class TestSchema(unittest.TestCase):
         (builder.add_column('key2', 'double')
          .nullable(False)
          .primary_key())
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = 'multiple columns specified for primary key: key1, key2'
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_multiple_non_unique_primary_keys(self):
@@ -436,7 +455,8 @@ class TestSchema(unittest.TestCase):
         (builder.add_column('key2', 'double')
          .nullable(False)
          .non_unique_primary_key())
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = 'multiple columns specified for primary key: key1, key2'
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_non_unique_primary_key_and_set_non_unique_primary_keys(self):
@@ -446,7 +466,9 @@ class TestSchema(unittest.TestCase):
          .non_unique_primary_key())
         builder.add_column('data1', 'double')
         builder.set_non_unique_primary_keys(['key'])
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = ('primary key specified by both SetNonUniquePrimaryKey\(\)'
+                     ' and on a specific column: key')
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_primary_key_and_set_non_unique_primary_keys(self):
@@ -456,7 +478,9 @@ class TestSchema(unittest.TestCase):
          .primary_key())
         builder.add_column('data1', 'double')
         builder.set_non_unique_primary_keys(['key'])
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = ('primary key specified by both SetNonUniquePrimaryKey\(\)'
+                     ' and on a specific column: key')
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_primary_key_and_set_primary_keys(self):
@@ -466,7 +490,9 @@ class TestSchema(unittest.TestCase):
          .primary_key())
         builder.add_column('data1', 'double')
         builder.set_primary_keys(['key'])
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = ('primary key specified by both SetPrimaryKey\(\)'
+                     ' and on a specific column: key')
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_non_unique_primary_key_and_set_primary_keys(self):
@@ -476,7 +502,9 @@ class TestSchema(unittest.TestCase):
          .non_unique_primary_key())
         builder.add_column('data1', 'double')
         builder.set_primary_keys(['key'])
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = ('primary key specified by both SetPrimaryKey\(\)'
+                     ' and on a specific column: key')
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_set_non_unique_and_set_unique_primary_key(self):
@@ -507,7 +535,8 @@ class TestSchema(unittest.TestCase):
          .nullable(False)
          .primary_key())
         builder.add_column(Schema.get_auto_incrementing_column_name(), 
'double')
-        with self.assertRaises(KuduInvalidArgument):
+        error_msg = 'auto_incrementing_id is a reserved column name'
+        with self.assertRaisesRegex(KuduInvalidArgument, error_msg):
             builder.build()
 
     def test_default_value(self):
diff --git a/python/kudu/tests/util.py b/python/kudu/tests/util.py
index c3c91a5ae..3f6c0c5bc 100644
--- a/python/kudu/tests/util.py
+++ b/python/kudu/tests/util.py
@@ -18,14 +18,14 @@
 # under the License.
 
 from decimal import Decimal
-from kudu.compat import unittest
+from kudu.compat import CompatUnitTest
 from kudu.client import Partitioning
 from kudu.tests.common import KuduTestBase
 import kudu
 import datetime
 import pytz
 
-class TestScanBase(KuduTestBase, unittest.TestCase):
+class TestScanBase(KuduTestBase, CompatUnitTest):
 
     @classmethod
     def setUpClass(self):

Reply via email to