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

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


The following commit(s) were added to refs/heads/master by this push:
     new b918dd4c169 [Python] Cleanup Python tests in pipeline options module 
(#28158)
b918dd4c169 is described below

commit b918dd4c1691ad76b07a5d2de48e67438b48d0e1
Author: Tim Grein <t...@4greins.de>
AuthorDate: Fri Aug 25 18:30:35 2023 +0200

    [Python] Cleanup Python tests in pipeline options module (#28158)
    
    * Use @parameterized decorator instead of a manual test case for loop in 
pipeline_options_test.py.
    
    * Use @parameterized decorator instead of a manual test case for loop in 
pipeline_options_validator_test.py.
---
 .../apache_beam/options/pipeline_options_test.py   | 383 ++++++-------
 .../options/pipeline_options_validator_test.py     | 624 +++++++--------------
 2 files changed, 379 insertions(+), 628 deletions(-)

diff --git a/sdks/python/apache_beam/options/pipeline_options_test.py 
b/sdks/python/apache_beam/options/pipeline_options_test.py
index 5355e4a7d3b..2d85d055eaf 100644
--- a/sdks/python/apache_beam/options/pipeline_options_test.py
+++ b/sdks/python/apache_beam/options/pipeline_options_test.py
@@ -24,6 +24,7 @@ import logging
 import unittest
 
 import hamcrest as hc
+from parameterized import parameterized
 
 from apache_beam.options.pipeline_options import DebugOptions
 from apache_beam.options.pipeline_options import GoogleCloudOptions
@@ -72,150 +73,104 @@ class PipelineOptionsTest(unittest.TestCase):
     RuntimeValueProvider.set_runtime_options(None)
 
   TEST_CASES = [
-      {
-          'flags': ['--num_workers', '5'],
-          'expected': {
-              'num_workers': 5,
-              'mock_flag': False,
-              'mock_option': None,
-              'mock_multi_option': None
-          },
-          'display_data': [DisplayDataItemMatcher('num_workers', 5)]
-      },
-      {
-          'flags': ['--direct_num_workers', '5'],
-          'expected': {
-              'direct_num_workers': 5,
-              'mock_flag': False,
-              'mock_option': None,
-              'mock_multi_option': None
-          },
-          'display_data': [DisplayDataItemMatcher('direct_num_workers', 5)]
-      },
-      {
-          'flags': ['--direct_running_mode', 'multi_threading'],
-          'expected': {
-              'direct_running_mode': 'multi_threading',
-              'mock_flag': False,
-              'mock_option': None,
-              'mock_multi_option': None
-          },
-          'display_data': [
-              DisplayDataItemMatcher('direct_running_mode', 'multi_threading')
-          ]
-      },
-      {
-          'flags': ['--direct_running_mode', 'multi_processing'],
-          'expected': {
-              'direct_running_mode': 'multi_processing',
-              'mock_flag': False,
-              'mock_option': None,
-              'mock_multi_option': None
-          },
-          'display_data': [
-              DisplayDataItemMatcher('direct_running_mode', 'multi_processing')
-          ]
-      },
-      {
-          'flags': [
-              '--profile_cpu', '--profile_location', 'gs://bucket/', 'ignored'
-          ],
-          'expected': {
-              'profile_cpu': True,
-              'profile_location': 'gs://bucket/',
-              'mock_flag': False,
-              'mock_option': None,
-              'mock_multi_option': None
-          },
-          'display_data': [
-              DisplayDataItemMatcher('profile_cpu', True),
-              DisplayDataItemMatcher('profile_location', 'gs://bucket/')
-          ]
-      },
-      {
-          'flags': ['--num_workers', '5', '--mock_flag'],
-          'expected': {
-              'num_workers': 5,
-              'mock_flag': True,
-              'mock_option': None,
-              'mock_multi_option': None
-          },
-          'display_data': [
-              DisplayDataItemMatcher('num_workers', 5),
-              DisplayDataItemMatcher('mock_flag', True)
-          ]
-      },
-      {
-          'flags': ['--mock_option', 'abc'],
-          'expected': {
-              'mock_flag': False,
-              'mock_option': 'abc',
-              'mock_multi_option': None
-          },
-          'display_data': [DisplayDataItemMatcher('mock_option', 'abc')]
-      },
-      {
-          'flags': ['--mock_option', ' abc def '],
-          'expected': {
-              'mock_flag': False,
-              'mock_option': ' abc def ',
-              'mock_multi_option': None
-          },
-          'display_data': [DisplayDataItemMatcher('mock_option', ' abc def ')]
-      },
-      {
-          'flags': ['--mock_option= abc xyz '],
-          'expected': {
-              'mock_flag': False,
-              'mock_option': ' abc xyz ',
-              'mock_multi_option': None
-          },
-          'display_data': [DisplayDataItemMatcher('mock_option', ' abc xyz ')]
-      },
-      {
-          'flags': [
-              '--mock_option=gs://my bucket/my folder/my file',
-              '--mock_multi_option=op1',
-              '--mock_multi_option=op2'
-          ],
-          'expected': {
-              'mock_flag': False,
-              'mock_option': 'gs://my bucket/my folder/my file',
-              'mock_multi_option': ['op1', 'op2']
-          },
-          'display_data': [
-              DisplayDataItemMatcher(
-                  'mock_option', 'gs://my bucket/my folder/my file'),
-              DisplayDataItemMatcher('mock_multi_option', ['op1', 'op2'])
-          ]
-      },
-      {
-          'flags': ['--mock_multi_option=op1', '--mock_multi_option=op2'],
-          'expected': {
-              'mock_flag': False,
-              'mock_option': None,
-              'mock_multi_option': ['op1', 'op2']
-          },
-          'display_data': [
-              DisplayDataItemMatcher('mock_multi_option', ['op1', 'op2'])
-          ]
-      },
-      {
-          'flags': ['--mock_json_option={"11a": 0, "37a": 1}'],
-          'expected': {
-              'mock_flag': False,
-              'mock_option': None,
-              'mock_multi_option': None,
-              'mock_json_option': {
-                  '11a': 0, '37a': 1
-              },
-          },
-          'display_data': [
-              DisplayDataItemMatcher('mock_json_option', {
-                  '11a': 0, '37a': 1
-              })
-          ]
-      },
+      (['--num_workers', '5'],
+       {
+           'num_workers': 5,
+           'mock_flag': False,
+           'mock_option': None,
+           'mock_multi_option': None
+       }, [DisplayDataItemMatcher('num_workers', 5)]),
+      (['--direct_num_workers', '5'],
+       {
+           'direct_num_workers': 5,
+           'mock_flag': False,
+           'mock_option': None,
+           'mock_multi_option': None
+       }, [DisplayDataItemMatcher('direct_num_workers', 5)]),
+      (['--direct_running_mode', 'multi_threading'],
+       {
+           'direct_running_mode': 'multi_threading',
+           'mock_flag': False,
+           'mock_option': None,
+           'mock_multi_option': None
+       }, [DisplayDataItemMatcher('direct_running_mode', 'multi_threading')]),
+      (['--direct_running_mode', 'multi_processing'],
+       {
+           'direct_running_mode': 'multi_processing',
+           'mock_flag': False,
+           'mock_option': None,
+           'mock_multi_option': None
+       }, [DisplayDataItemMatcher('direct_running_mode', 'multi_processing')]),
+      (['--profile_cpu', '--profile_location', 'gs://bucket/', 'ignored'],
+       {
+           'profile_cpu': True,
+           'profile_location': 'gs://bucket/',
+           'mock_flag': False,
+           'mock_option': None,
+           'mock_multi_option': None
+       },
+       [
+           DisplayDataItemMatcher('profile_cpu', True),
+           DisplayDataItemMatcher('profile_location', 'gs://bucket/')
+       ]),
+      (['--num_workers', '5', '--mock_flag'],
+       {
+           'num_workers': 5,
+           'mock_flag': True,
+           'mock_option': None,
+           'mock_multi_option': None
+       },
+       [
+           DisplayDataItemMatcher('num_workers', 5),
+           DisplayDataItemMatcher('mock_flag', True)
+       ]),
+      (['--mock_option', 'abc'], {
+          'mock_flag': False, 'mock_option': 'abc', 'mock_multi_option': None
+      }, [DisplayDataItemMatcher('mock_option', 'abc')]),
+      (['--mock_option', ' abc def '],
+       {
+           'mock_flag': False,
+           'mock_option': ' abc def ',
+           'mock_multi_option': None
+       }, [DisplayDataItemMatcher('mock_option', ' abc def ')]),
+      (['--mock_option= abc xyz '],
+       {
+           'mock_flag': False,
+           'mock_option': ' abc xyz ',
+           'mock_multi_option': None
+       }, [DisplayDataItemMatcher('mock_option', ' abc xyz ')]),
+      ([
+          '--mock_option=gs://my bucket/my folder/my file',
+          '--mock_multi_option=op1',
+          '--mock_multi_option=op2'
+      ],
+       {
+           'mock_flag': False,
+           'mock_option': 'gs://my bucket/my folder/my file',
+           'mock_multi_option': ['op1', 'op2']
+       },
+       [
+           DisplayDataItemMatcher(
+               'mock_option', 'gs://my bucket/my folder/my file'),
+           DisplayDataItemMatcher('mock_multi_option', ['op1', 'op2'])
+       ]),
+      (['--mock_multi_option=op1', '--mock_multi_option=op2'],
+       {
+           'mock_flag': False,
+           'mock_option': None,
+           'mock_multi_option': ['op1', 'op2']
+       }, [DisplayDataItemMatcher('mock_multi_option', ['op1', 'op2'])]),
+      (['--mock_json_option={"11a": 0, "37a": 1}'],
+       {
+           'mock_flag': False,
+           'mock_option': None,
+           'mock_multi_option': None,
+           'mock_json_option': {
+               '11a': 0, '37a': 1
+           },
+       }, [DisplayDataItemMatcher('mock_json_option', {
+           '11a': 0, '37a': 1
+       })]),
   ]
 
   # Used for testing newly added flags.
@@ -238,59 +193,59 @@ class PipelineOptionsTest(unittest.TestCase):
       parser.add_argument(
           '--fake_multi_option', action='append', help='fake multi option')
 
-  def test_display_data(self):
-    for case in PipelineOptionsTest.TEST_CASES:
-      options = PipelineOptions(flags=case['flags'])
-      dd = DisplayData.create_from(options)
-      hc.assert_that(dd.items, hc.contains_inanyorder(*case['display_data']))
-
-  def test_get_all_options_subclass(self):
-    for case in PipelineOptionsTest.TEST_CASES:
-      options = PipelineOptionsTest.MockOptions(flags=case['flags'])
-      self.assertDictContainsSubset(case['expected'], 
options.get_all_options())
-      self.assertEqual(
-          options.view_as(PipelineOptionsTest.MockOptions).mock_flag,
-          case['expected']['mock_flag'])
-      self.assertEqual(
-          options.view_as(PipelineOptionsTest.MockOptions).mock_option,
-          case['expected']['mock_option'])
-      self.assertEqual(
-          options.view_as(PipelineOptionsTest.MockOptions).mock_multi_option,
-          case['expected']['mock_multi_option'])
-
-  def test_get_all_options(self):
-    for case in PipelineOptionsTest.TEST_CASES:
-      options = PipelineOptions(flags=case['flags'])
-      self.assertDictContainsSubset(case['expected'], 
options.get_all_options())
-      self.assertEqual(
-          options.view_as(PipelineOptionsTest.MockOptions).mock_flag,
-          case['expected']['mock_flag'])
-      self.assertEqual(
-          options.view_as(PipelineOptionsTest.MockOptions).mock_option,
-          case['expected']['mock_option'])
-      self.assertEqual(
-          options.view_as(PipelineOptionsTest.MockOptions).mock_multi_option,
-          case['expected']['mock_multi_option'])
-
-  def test_sublcalsses_of_pipeline_options_can_be_instantiated(self):
-    for case in PipelineOptionsTest.TEST_CASES:
-      mock_options = PipelineOptionsTest.MockOptions(flags=case['flags'])
-      self.assertEqual(mock_options.mock_flag, case['expected']['mock_flag'])
-      self.assertEqual(
-          mock_options.mock_option, case['expected']['mock_option'])
-      self.assertEqual(
-          mock_options.mock_multi_option, 
case['expected']['mock_multi_option'])
-
-  def test_views_can_be_constructed_from_pipeline_option_subclasses(self):
-    for case in PipelineOptionsTest.TEST_CASES:
-      fake_options = PipelineOptionsTest.FakeOptions(flags=case['flags'])
-      mock_options = fake_options.view_as(PipelineOptionsTest.MockOptions)
-
-      self.assertEqual(mock_options.mock_flag, case['expected']['mock_flag'])
-      self.assertEqual(
-          mock_options.mock_option, case['expected']['mock_option'])
-      self.assertEqual(
-          mock_options.mock_multi_option, 
case['expected']['mock_multi_option'])
+  @parameterized.expand(TEST_CASES)
+  def test_display_data(self, flags, _, display_data):
+    options = PipelineOptions(flags=flags)
+    dd = DisplayData.create_from(options)
+    hc.assert_that(dd.items, hc.contains_inanyorder(*display_data))
+
+  @parameterized.expand(TEST_CASES)
+  def test_get_all_options_subclass(self, flags, expected, _):
+    options = PipelineOptionsTest.MockOptions(flags=flags)
+    self.assertDictContainsSubset(expected, options.get_all_options())
+    self.assertEqual(
+        options.view_as(PipelineOptionsTest.MockOptions).mock_flag,
+        expected['mock_flag'])
+    self.assertEqual(
+        options.view_as(PipelineOptionsTest.MockOptions).mock_option,
+        expected['mock_option'])
+    self.assertEqual(
+        options.view_as(PipelineOptionsTest.MockOptions).mock_multi_option,
+        expected['mock_multi_option'])
+
+  @parameterized.expand(TEST_CASES)
+  def test_get_all_options(self, flags, expected, _):
+    options = PipelineOptions(flags=flags)
+    self.assertDictContainsSubset(expected, options.get_all_options())
+    self.assertEqual(
+        options.view_as(PipelineOptionsTest.MockOptions).mock_flag,
+        expected['mock_flag'])
+    self.assertEqual(
+        options.view_as(PipelineOptionsTest.MockOptions).mock_option,
+        expected['mock_option'])
+    self.assertEqual(
+        options.view_as(PipelineOptionsTest.MockOptions).mock_multi_option,
+        expected['mock_multi_option'])
+
+  @parameterized.expand(TEST_CASES)
+  def test_subclasses_of_pipeline_options_can_be_instantiated(
+      self, flags, expected, _):
+    mock_options = PipelineOptionsTest.MockOptions(flags=flags)
+    self.assertEqual(mock_options.mock_flag, expected['mock_flag'])
+    self.assertEqual(mock_options.mock_option, expected['mock_option'])
+    self.assertEqual(
+        mock_options.mock_multi_option, expected['mock_multi_option'])
+
+  @parameterized.expand(TEST_CASES)
+  def test_views_can_be_constructed_from_pipeline_option_subclasses(
+      self, flags, expected, _):
+    fake_options = PipelineOptionsTest.FakeOptions(flags=flags)
+    mock_options = fake_options.view_as(PipelineOptionsTest.MockOptions)
+
+    self.assertEqual(mock_options.mock_flag, expected['mock_flag'])
+    self.assertEqual(mock_options.mock_option, expected['mock_option'])
+    self.assertEqual(
+        mock_options.mock_multi_option, expected['mock_multi_option'])
 
   def test_views_do_not_expose_options_defined_by_other_views(self):
     flags = ['--mock_option=mock_value', '--fake_option=fake_value']
@@ -312,23 +267,23 @@ class PipelineOptionsTest(unittest.TestCase):
             PipelineOptionsTest.FakeOptions).view_as(
                 PipelineOptionsTest.MockOptions).fake_option)
 
-  def test_from_dictionary(self):
-    for case in PipelineOptionsTest.TEST_CASES:
-      options = PipelineOptions(flags=case['flags'])
-      all_options_dict = options.get_all_options()
-      options_from_dict = PipelineOptions.from_dictionary(all_options_dict)
-      self.assertEqual(
-          options_from_dict.view_as(PipelineOptionsTest.MockOptions).mock_flag,
-          case['expected']['mock_flag'])
-      self.assertEqual(
-          options.view_as(PipelineOptionsTest.MockOptions).mock_option,
-          case['expected']['mock_option'])
-      self.assertEqual(
-          options.view_as(PipelineOptionsTest.MockOptions).mock_multi_option,
-          case['expected']['mock_multi_option'])
-      self.assertEqual(
-          options.view_as(PipelineOptionsTest.MockOptions).mock_json_option,
-          case['expected'].get('mock_json_option', {}))
+  @parameterized.expand(TEST_CASES)
+  def test_from_dictionary(self, flags, expected, _):
+    options = PipelineOptions(flags=flags)
+    all_options_dict = options.get_all_options()
+    options_from_dict = PipelineOptions.from_dictionary(all_options_dict)
+    self.assertEqual(
+        options_from_dict.view_as(PipelineOptionsTest.MockOptions).mock_flag,
+        expected['mock_flag'])
+    self.assertEqual(
+        options.view_as(PipelineOptionsTest.MockOptions).mock_option,
+        expected['mock_option'])
+    self.assertEqual(
+        options.view_as(PipelineOptionsTest.MockOptions).mock_multi_option,
+        expected['mock_multi_option'])
+    self.assertEqual(
+        options.view_as(PipelineOptionsTest.MockOptions).mock_json_option,
+        expected.get('mock_json_option', {}))
 
   def test_none_from_dictionary(self):
     class NoneDefaultOptions(PipelineOptions):
diff --git a/sdks/python/apache_beam/options/pipeline_options_validator_test.py 
b/sdks/python/apache_beam/options/pipeline_options_validator_test.py
index 1f4c8be226d..015e3ef787f 100644
--- a/sdks/python/apache_beam/options/pipeline_options_validator_test.py
+++ b/sdks/python/apache_beam/options/pipeline_options_validator_test.py
@@ -26,6 +26,7 @@ from hamcrest import assert_that
 from hamcrest import contains_string
 from hamcrest import only_contains
 from hamcrest.core.base_matcher import BaseMatcher
+from parameterized import parameterized
 
 from apache_beam.internal import pickler
 from apache_beam.options.pipeline_options import DebugOptions
@@ -95,170 +96,85 @@ class SetupTest(unittest.TestCase):
             errors, ['project', 'staging_location', 'temp_location', 
'region']),
         [])
 
-  def test_gcs_path(self):
-    def get_validator(temp_location, staging_location):
+  @parameterized.expand([
+      (None, 'gs://foo/bar',
+       []), (None, None, ['staging_location', 'temp_location']),
+      ('gs://foo/bar', None, []), ('gs://foo/bar', 'gs://ABC/bar',
+                                   []), ('gcs:/foo/bar', 'gs://foo/bar', []),
+      ('gs:/foo/bar', 'gs://foo/bar', []), ('gs://ABC/bar', 'gs://foo/bar', 
[]),
+      ('gs://ABC/bar', 'gs://BCD/bar', ['temp_location', 'staging_location'
+                                        ]), ('gs://foo', 'gs://foo/bar', []),
+      ('gs://foo/', 'gs://foo/bar', []), ('gs://foo/bar', 'gs://foo/bar', [])
+  ])
+  def test_gcs_path(self, temp_location, staging_location, 
expected_error_args):
+    def get_validator(_temp_location, _staging_location):
       options = ['--project=example:example', '--job_name=job']
 
-      if temp_location is not None:
-        options.append('--temp_location=' + temp_location)
+      if _temp_location is not None:
+        options.append('--temp_location=' + _temp_location)
 
-      if staging_location is not None:
-        options.append('--staging_location=' + staging_location)
+      if _staging_location is not None:
+        options.append('--staging_location=' + _staging_location)
 
       pipeline_options = PipelineOptions(options)
       runner = MockRunners.DataflowRunner()
       validator = PipelineOptionsValidator(pipeline_options, runner)
       return validator
 
-    test_cases = [{
-        'temp_location': None, 'staging_location': 'gs://foo/bar', 'errors': []
-    },
-                  {
-                      'temp_location': None,
-                      'staging_location': None,
-                      'errors': ['staging_location', 'temp_location']
-                  },
-                  {
-                      'temp_location': 'gs://foo/bar',
-                      'staging_location': None,
-                      'errors': []
-                  },
-                  {
-                      'temp_location': 'gs://foo/bar',
-                      'staging_location': 'gs://ABC/bar',
-                      'errors': []
-                  },
-                  {
-                      'temp_location': 'gcs:/foo/bar',
-                      'staging_location': 'gs://foo/bar',
-                      'errors': []
-                  },
-                  {
-                      'temp_location': 'gs:/foo/bar',
-                      'staging_location': 'gs://foo/bar',
-                      'errors': []
-                  },
-                  {
-                      'temp_location': 'gs://ABC/bar',
-                      'staging_location': 'gs://foo/bar',
-                      'errors': []
-                  },
-                  {
-                      'temp_location': 'gs://ABC/bar',
-                      'staging_location': 'gs://BCD/bar',
-                      'errors': ['temp_location', 'staging_location']
-                  },
-                  {
-                      'temp_location': 'gs://foo',
-                      'staging_location': 'gs://foo/bar',
-                      'errors': []
-                  },
-                  {
-                      'temp_location': 'gs://foo/',
-                      'staging_location': 'gs://foo/bar',
-                      'errors': []
-                  },
-                  {
-                      'temp_location': 'gs://foo/bar',
-                      'staging_location': 'gs://foo/bar',
-                      'errors': []
-                  }]
-
-    for case in test_cases:
-      errors = get_validator(case['temp_location'],
-                             case['staging_location']).validate()
-      self.assertEqual(
-          self.check_errors_for_arguments(errors, case['errors']), [], case)
-
-  def test_project(self):
-    def get_validator(project):
+    errors = get_validator(temp_location, staging_location).validate()
+    self.assertEqual(
+        self.check_errors_for_arguments(errors, expected_error_args), [])
+
+  @parameterized.expand([(None, ['project']), ('12345', ['project']),
+                         ('FOO', ['project']), ('foo:BAR', ['project']),
+                         ('fo', ['project']), ('foo', []), ('foo:bar', [])])
+  def test_project(self, project, expected_error_args):
+    def get_validator(_project):
       options = [
           '--job_name=job',
           '--staging_location=gs://foo/bar',
           '--temp_location=gs://foo/bar'
       ]
 
-      if project is not None:
-        options.append('--project=' + project)
+      if _project is not None:
+        options.append('--project=' + _project)
 
       pipeline_options = PipelineOptions(options)
       runner = MockRunners.DataflowRunner()
       validator = PipelineOptionsValidator(pipeline_options, runner)
       return validator
 
-    test_cases = [
-        {
-            'project': None, 'errors': ['project']
-        },
-        {
-            'project': '12345', 'errors': ['project']
-        },
-        {
-            'project': 'FOO', 'errors': ['project']
-        },
-        {
-            'project': 'foo:BAR', 'errors': ['project']
-        },
-        {
-            'project': 'fo', 'errors': ['project']
-        },
-        {
-            'project': 'foo', 'errors': []
-        },
-        {
-            'project': 'foo:bar', 'errors': []
-        },
-    ]
-
-    for case in test_cases:
-      errors = get_validator(case['project']).validate()
-      self.assertEqual(
-          self.check_errors_for_arguments(errors, case['errors']), [])
+    errors = get_validator(project).validate()
+    self.assertEqual(
+        self.check_errors_for_arguments(errors, expected_error_args), [])
 
-  def test_job_name(self):
-    def get_validator(job_name):
+  @parameterized.expand([(None, []), ('12345', ['job_name']),
+                         ('FOO', ['job_name']), ('foo:bar', ['job_name']),
+                         ('fo', []), ('foo', [])])
+  def test_job_name(self, job_name, expected_error_args):
+    def get_validator(_job_name):
       options = [
           '--project=example:example',
           '--staging_location=gs://foo/bar',
           '--temp_location=gs://foo/bar'
       ]
 
-      if job_name is not None:
-        options.append('--job_name=' + job_name)
+      if _job_name is not None:
+        options.append('--job_name=' + _job_name)
 
       pipeline_options = PipelineOptions(options)
       runner = MockRunners.DataflowRunner()
       validator = PipelineOptionsValidator(pipeline_options, runner)
       return validator
 
-    test_cases = [
-        {
-            'job_name': None, 'errors': []
-        },
-        {
-            'job_name': '12345', 'errors': ['job_name']
-        },
-        {
-            'job_name': 'FOO', 'errors': ['job_name']
-        },
-        {
-            'job_name': 'foo:bar', 'errors': ['job_name']
-        },
-        {
-            'job_name': 'fo', 'errors': []
-        },
-        {
-            'job_name': 'foo', 'errors': []
-        },
-    ]
-
-    for case in test_cases:
-      errors = get_validator(case['job_name']).validate()
-      self.assertEqual(
-          self.check_errors_for_arguments(errors, case['errors']), [])
+    errors = get_validator(job_name).validate()
+    self.assertEqual(
+        self.check_errors_for_arguments(errors, expected_error_args), [])
 
-  def test_num_workers(self):
-    def get_validator(num_workers):
+  @parameterized.expand([(None, []), ('1', []), ('0', ['num_workers']),
+                         ('-1', ['num_workers'])])
+  def test_num_workers(self, num_workers, expected_error_args):
+    def get_validator(_num_workers):
       options = [
           '--project=example:example',
           '--job_name=job',
@@ -266,87 +182,66 @@ class SetupTest(unittest.TestCase):
           '--temp_location=gs://foo/bar'
       ]
 
-      if num_workers is not None:
-        options.append('--num_workers=' + num_workers)
+      if _num_workers is not None:
+        options.append('--num_workers=' + _num_workers)
 
       pipeline_options = PipelineOptions(options)
       runner = MockRunners.DataflowRunner()
       validator = PipelineOptionsValidator(pipeline_options, runner)
       return validator
 
-    test_cases = [
-        {
-            'num_workers': None, 'errors': []
-        },
-        {
-            'num_workers': '1', 'errors': []
-        },
-        {
-            'num_workers': '0', 'errors': ['num_workers']
-        },
-        {
-            'num_workers': '-1', 'errors': ['num_workers']
-        },
-    ]
-
-    for case in test_cases:
-      errors = get_validator(case['num_workers']).validate()
-      self.assertEqual(
-          self.check_errors_for_arguments(errors, case['errors']), [])
-
-  def test_is_service_runner(self):
-    test_cases = [
-        {
-            'runner': MockRunners.OtherRunner(),
-            'options': [],
-            'expected': False,
-        },
-        {
-            'runner': MockRunners.OtherRunner(),
-            'options': ['--dataflow_endpoint=https://dataflow.googleapis.com'],
-            'expected': False,
-        },
-        {
-            'runner': MockRunners.OtherRunner(),
-            'options': 
['--dataflow_endpoint=https://dataflow.googleapis.com/'],
-            'expected': False,
-        },
-        {
-            'runner': MockRunners.DataflowRunner(),
-            'options': [],
-            'expected': True,
-        },
-        {
-            'runner': MockRunners.DataflowRunner(),
-            'options': ['--dataflow_endpoint=https://another.service.com'],
-            'expected': True,
-        },
-        {
-            'runner': MockRunners.DataflowRunner(),
-            'options': ['--dataflow_endpoint=https://dataflow.googleapis.com'],
-            'expected': True,
-        },
-        {
-            'runner': MockRunners.DataflowRunner(),
-            'options': ['--dataflow_endpoint=http://localhost:1000'],
-            'expected': False,
-        },
-        {
-            'runner': MockRunners.DataflowRunner(),
-            'options': ['--dataflow_endpoint=foo: //dataflow. googleapis. 
com'],
-            'expected': True,
-        },
-        {
-            'runner': MockRunners.DataflowRunner(),
-            'options': [],
-            'expected': True,
-        },
-    ]
-
-    for case in test_cases:
-      validator = PipelineOptionsValidator(
-          PipelineOptions(case['options']), case['runner'])
-      self.assertEqual(validator.is_service_runner(), case['expected'], case)
+    errors = get_validator(num_workers).validate()
+    self.assertEqual(
+        self.check_errors_for_arguments(errors, expected_error_args), [])
+
+  @parameterized.expand([
+      (
+          MockRunners.OtherRunner(),
+          [],
+          False,
+      ),
+      (
+          MockRunners.OtherRunner(),
+          ['--dataflow_endpoint=https://dataflow.googleapis.com'],
+          False,
+      ),
+      (
+          MockRunners.OtherRunner(),
+          ['--dataflow_endpoint=https://dataflow.googleapis.com/'],
+          False,
+      ), (
+          MockRunners.DataflowRunner(),
+          [],
+          True,
+      ),
+      (
+          MockRunners.DataflowRunner(),
+          ['--dataflow_endpoint=https://another.service.com'],
+          True,
+      ),
+      (
+          MockRunners.DataflowRunner(),
+          ['--dataflow_endpoint=https://dataflow.googleapis.com'],
+          True,
+      ),
+      (
+          MockRunners.DataflowRunner(),
+          ['--dataflow_endpoint=http://localhost:1000'],
+          False,
+      ),
+      (
+          MockRunners.DataflowRunner(),
+          ['--dataflow_endpoint=foo: //dataflow. googleapis. com'],
+          True,
+      ), (
+          MockRunners.DataflowRunner(),
+          [],
+          True,
+      )
+  ])
+  def test_is_service_runner(self, runner, options, expected):
+    validator = PipelineOptionsValidator(PipelineOptions(options), runner)
+    self.assertEqual(validator.is_service_runner(), expected)
 
   def test_dataflow_job_file_and_template_location_mutually_exclusive(self):
     runner = MockRunners.OtherRunner()
@@ -652,7 +547,10 @@ class SetupTest(unittest.TestCase):
     errors = validator.validate()
     self.assertEqual(len(errors), 0)
 
-  def test_test_matcher(self):
+  @parameterized.expand([(None, []), (pickler.dumps(AlwaysPassMatcher()), []),
+                         (b'abc', ['on_success_matcher']),
+                         (pickler.dumps(object), ['on_success_matcher'])])
+  def test_test_matcher(self, on_success_matcher, errors):
     def get_validator(matcher):
       options = [
           '--project=example:example',
@@ -667,27 +565,8 @@ class SetupTest(unittest.TestCase):
       runner = MockRunners.TestDataflowRunner()
       return PipelineOptionsValidator(pipeline_options, runner)
 
-    test_case = [
-        {
-            'on_success_matcher': None, 'errors': []
-        },
-        {
-            'on_success_matcher': pickler.dumps(AlwaysPassMatcher()),
-            'errors': []
-        },
-        {
-            'on_success_matcher': b'abc', 'errors': ['on_success_matcher']
-        },
-        {
-            'on_success_matcher': pickler.dumps(object),
-            'errors': ['on_success_matcher']
-        },
-    ]
-
-    for case in test_case:
-      errors = get_validator(case['on_success_matcher']).validate()
-      self.assertEqual(
-          self.check_errors_for_arguments(errors, case['errors']), [])
+    errors = get_validator(on_success_matcher).validate()
+    self.assertEqual(self.check_errors_for_arguments(errors, errors), [])
 
   def test_transform_name_mapping_without_update(self):
     options = [
@@ -747,195 +626,112 @@ class SetupTest(unittest.TestCase):
     errors = validator.validate()
     self.assertTrue(errors)
 
-  def test_environment_options(self):
-    test_cases = [
-        {
-            'options': ['--environment_type=dOcKeR'], 'errors': []
-        },
-        {
-            'options': [
-                '--environment_type=dOcKeR',
-                '--environment_options=docker_container_image=foo'
-            ],
-            'errors': []
-        },
-        {
-            'options': [
-                '--environment_type=dOcKeR', '--environment_config=foo'
-            ],
-            'errors': []
-        },
-        {
-            'options': [
-                '--environment_type=dOcKeR',
-                '--environment_options=docker_container_image=foo',
-                '--environment_config=foo'
-            ],
-            'errors': ['environment_config']
-        },
-        {
-            'options': [
-                '--environment_type=dOcKeR',
-                '--environment_options=process_command=foo',
-                '--environment_options=process_variables=foo=bar',
-                '--environment_options=external_service_address=foo'
-            ],
-            'errors': [
-                'process_command',
-                'process_variables',
-                'external_service_address'
-            ]
-        },
-        {
-            'options': ['--environment_type=pRoCeSs'],
-            'errors': ['process_command']
-        },
-        {
-            'options': [
-                '--environment_type=pRoCeSs',
-                '--environment_options=process_command=foo'
-            ],
-            'errors': []
-        },
-        {
-            'options': [
-                '--environment_type=pRoCeSs', '--environment_config=foo'
-            ],
-            'errors': []
-        },
-        {
-            'options': [
-                '--environment_type=pRoCeSs',
-                '--environment_options=process_command=foo',
-                '--environment_config=foo'
-            ],
-            'errors': ['environment_config']
-        },
-        {
-            'options': [
-                '--environment_type=pRoCeSs',
-                '--environment_options=process_command=foo',
-                '--environment_options=process_variables=foo=bar',
-                '--environment_options=docker_container_image=foo',
-                '--environment_options=external_service_address=foo'
-            ],
-            'errors': ['docker_container_image', 'external_service_address']
-        },
-        {
-            'options': ['--environment_type=eXtErNaL'],
-            'errors': ['external_service_address']
-        },
-        {
-            'options': [
-                '--environment_type=eXtErNaL',
-                '--environment_options=external_service_address=foo'
-            ],
-            'errors': []
-        },
-        {
-            'options': [
-                '--environment_type=eXtErNaL', '--environment_config=foo'
-            ],
-            'errors': []
-        },
-        {
-            'options': [
-                '--environment_type=eXtErNaL',
-                '--environment_options=external_service_address=foo',
-                '--environment_config=foo'
-            ],
-            'errors': ['environment_config']
-        },
-        {
-            'options': [
-                '--environment_type=eXtErNaL',
-                '--environment_options=external_service_address=foo',
-                '--environment_options=process_command=foo',
-                '--environment_options=process_variables=foo=bar',
-                '--environment_options=docker_container_image=foo',
-            ],
-            'errors': [
-                'process_command',
-                'process_variables',
-                'docker_container_image'
-            ]
-        },
-        {
-            'options': ['--environment_type=lOoPbACk'], 'errors': []
-        },
-        {
-            'options': [
-                '--environment_type=lOoPbACk', '--environment_config=foo'
-            ],
-            'errors': ['environment_config']
-        },
-        {
-            'options': [
-                '--environment_type=lOoPbACk',
-                '--environment_options=docker_container_image=foo',
-                '--environment_options=process_command=foo',
-                '--environment_options=process_variables=foo=bar',
-                '--environment_options=external_service_address=foo',
-            ],
-            'errors': [
-                'docker_container_image',
-                'process_command',
-                'process_variables',
-                'external_service_address'
-            ]
-        },
-        {
-            'options': ['--environment_type=beam:env:foo:v1'], 'errors': []
-        },
-        {
-            'options': [
-                '--environment_type=beam:env:foo:v1',
-                '--environment_config=foo'
-            ],
-            'errors': []
-        },
-        {
-            'options': [
-                '--environment_type=beam:env:foo:v1',
-                '--environment_options=docker_container_image=foo',
-                '--environment_options=process_command=foo',
-                '--environment_options=process_variables=foo=bar',
-                '--environment_options=external_service_address=foo',
-            ],
-            'errors': [
-                'docker_container_image',
-                'process_command',
-                'process_variables',
-                'external_service_address'
-            ]
-        },
-        {
-            'options': [
-                '--environment_options=docker_container_image=foo',
-                '--environment_options=process_command=foo',
-                '--environment_options=process_variables=foo=bar',
-                '--environment_options=external_service_address=foo',
-            ],
-            'errors': [
-                'docker_container_image',
-                'process_command',
-                'process_variables',
-                'external_service_address'
-            ]
-        },
-    ]
+  @parameterized.expand([
+      (['--environment_type=dOcKeR'], []),
+      ([
+          '--environment_type=dOcKeR',
+          '--environment_options=docker_container_image=foo'
+      ], []), (['--environment_type=dOcKeR', '--environment_config=foo'], []),
+      ([
+          '--environment_type=dOcKeR',
+          '--environment_options=docker_container_image=foo',
+          '--environment_config=foo'
+      ], ['environment_config']),
+      ([
+          '--environment_type=dOcKeR',
+          '--environment_options=process_command=foo',
+          '--environment_options=process_variables=foo=bar',
+          '--environment_options=external_service_address=foo'
+      ], ['process_command', 'process_variables', 'external_service_address']),
+      (['--environment_type=pRoCeSs'], ['process_command']),
+      ([
+          '--environment_type=pRoCeSs',
+          '--environment_options=process_command=foo'
+      ], []), (['--environment_type=pRoCeSs', '--environment_config=foo'], []),
+      ([
+          '--environment_type=pRoCeSs',
+          '--environment_options=process_command=foo',
+          '--environment_config=foo'
+      ], ['environment_config']),
+      ([
+          '--environment_type=pRoCeSs',
+          '--environment_options=process_command=foo',
+          '--environment_options=process_variables=foo=bar',
+          '--environment_options=docker_container_image=foo',
+          '--environment_options=external_service_address=foo'
+      ], ['docker_container_image', 'external_service_address']),
+      (['--environment_type=eXtErNaL'], ['external_service_address']),
+      ([
+          '--environment_type=eXtErNaL',
+          '--environment_options=external_service_address=foo'
+      ], []), (['--environment_type=eXtErNaL', '--environment_config=foo'], 
[]),
+      ([
+          '--environment_type=eXtErNaL',
+          '--environment_options=external_service_address=foo',
+          '--environment_config=foo'
+      ], ['environment_config']),
+      ([
+          '--environment_type=eXtErNaL',
+          '--environment_options=external_service_address=foo',
+          '--environment_options=process_command=foo',
+          '--environment_options=process_variables=foo=bar',
+          '--environment_options=docker_container_image=foo'
+      ], ['process_command', 'process_variables',
+          'docker_container_image']), (['--environment_type=lOoPbACk'], []),
+      (['--environment_type=lOoPbACk',
+        '--environment_config=foo'], ['environment_config']),
+      ([
+          '--environment_type=lOoPbACk',
+          '--environment_options=docker_container_image=foo',
+          '--environment_options=process_command=foo',
+          '--environment_options=process_variables=foo=bar',
+          '--environment_options=external_service_address=foo'
+      ],
+       [
+           'docker_container_image',
+           'process_command',
+           'process_variables',
+           'external_service_address'
+       ]), (['--environment_type=beam:env:foo:v1'], []),
+      (['--environment_type=beam:env:foo:v1', '--environment_config=foo'], []),
+      ([
+          '--environment_type=beam:env:foo:v1',
+          '--environment_options=docker_container_image=foo',
+          '--environment_options=process_command=foo',
+          '--environment_options=process_variables=foo=bar',
+          '--environment_options=external_service_address=foo'
+      ],
+       [
+           'docker_container_image',
+           'process_command',
+           'process_variables',
+           'external_service_address'
+       ]),
+      ([
+          '--environment_options=docker_container_image=foo',
+          '--environment_options=process_command=foo',
+          '--environment_options=process_variables=foo=bar',
+          '--environment_options=external_service_address=foo'
+      ],
+       [
+           'docker_container_image',
+           'process_command',
+           'process_variables',
+           'external_service_address'
+       ])
+  ])
+  def test_environment_options(self, options, expected_error_args):
     errors = []
-    for case in test_cases:
-      validator = PipelineOptionsValidator(
-          PipelineOptions(case['options']), MockRunners.OtherRunner())
-      validation_result = validator.validate()
-      validation_errors = self.check_errors_for_arguments(
-          validation_result, case['errors'])
-      if validation_errors:
-        errors.append(
-            'Options "%s" had unexpected validation results: "%s"' %
-            (' '.join(case['options']), ' '.join(validation_errors)))
-    self.assertEqual(errors, [], errors)
+    validator = PipelineOptionsValidator(
+        PipelineOptions(options), MockRunners.OtherRunner())
+    validation_result = validator.validate()
+    validation_errors = self.check_errors_for_arguments(
+        validation_result, expected_error_args)
+    if validation_errors:
+      errors.append(
+          'Options "%s" had unexpected validation results: "%s"' %
+          (' '.join(options), ' '.join(validation_errors)))
+    self.assertEqual(errors, [], expected_error_args)
 
 
 if __name__ == '__main__':


Reply via email to