afscgap.test.test_flat_local_filter
Tests for local filtering on returned flat results.
(c) 2025 Regents of University of California / The Eric and Wendy Schmidt Center for Data Science and the Environment at UC Berkeley.
This file is part of afscgap released under the BSD 3-Clause License. See LICENSE.md.
1""" 2Tests for local filtering on returned flat results. 3 4(c) 2025 Regents of University of California / The Eric and Wendy Schmidt Center 5for Data Science and the Environment at UC Berkeley. 6 7This file is part of afscgap released under the BSD 3-Clause License. See 8LICENSE.md. 9""" 10import unittest 11import unittest.mock 12 13import afscgap.flat_local_filter 14import afscgap.param 15 16 17class EqualsLocalFilterTests(unittest.TestCase): 18 19 def setUp(self): 20 self._filter = afscgap.flat_local_filter.EqualsLocalFilter( 21 lambda x: x.get_value(), 22 1 23 ) 24 25 def test_matches_true(self): 26 self.assertTrue(self._filter.matches(self._make_target(1))) 27 28 def test_matches_false(self): 29 self.assertFalse(self._filter.matches(self._make_target(1.001))) 30 31 def test_matches_none(self): 32 self.assertFalse(self._filter.matches(self._make_target(None))) 33 34 def _make_target(self, value): 35 mock = unittest.mock.MagicMock() 36 mock.get_value = unittest.mock.MagicMock(return_value=value) 37 return mock 38 39 40class RangeLocalFilterTests(unittest.TestCase): 41 42 def setUp(self): 43 self._filter = afscgap.flat_local_filter.RangeLocalFilter( 44 lambda x: x.get_value(), 45 2, 46 4 47 ) 48 49 def test_out_lower(self): 50 self.assertFalse(self._filter.matches(self._make_target(1))) 51 52 def test_at_lower(self): 53 self.assertTrue(self._filter.matches(self._make_target(2))) 54 55 def test_mid(self): 56 self.assertTrue(self._filter.matches(self._make_target(3))) 57 58 def test_at_high(self): 59 self.assertTrue(self._filter.matches(self._make_target(4))) 60 61 def test_above_high(self): 62 self.assertFalse(self._filter.matches(self._make_target(5))) 63 64 def test_none(self): 65 self.assertFalse(self._filter.matches(self._make_target(None))) 66 67 def _make_target(self, value): 68 mock = unittest.mock.MagicMock() 69 mock.get_value = unittest.mock.MagicMock(return_value=value) 70 return mock 71 72 73class LogcalAndLocalFilterTests(unittest.TestCase): 74 75 def test_empty(self): 76 target = self._make_filter([]) 77 self.assertTrue(target.matches(1)) 78 79 def test_single_true(self): 80 target = self._make_filter([True]) 81 self.assertTrue(target.matches(1)) 82 83 def test_single_false(self): 84 target = self._make_filter([False]) 85 self.assertFalse(target.matches(1)) 86 87 def test_multiple_true(self): 88 target = self._make_filter([True, True]) 89 self.assertTrue(target.matches(1)) 90 91 def test_multiple_false(self): 92 target = self._make_filter([True, False]) 93 self.assertFalse(target.matches(1)) 94 95 def test_none(self): 96 target = self._make_filter([True, True]) 97 self.assertTrue(target.matches(None)) 98 99 def _make_filter(self, values): 100 inner_filters = map(lambda x: self._make_inner_filter(x), values) 101 return afscgap.flat_local_filter.LogicalAndLocalFilter(inner_filters) 102 103 def _make_inner_filter(self, value): 104 mock = unittest.mock.MagicMock() 105 mock.matches = unittest.mock.MagicMock(return_value=value) 106 return mock 107 108 109class BuildIndividualFilterTests(unittest.TestCase): 110 111 def test_empty(self): 112 param = afscgap.param.EmptyParam() 113 local_filter = afscgap.flat_local_filter.build_individual_filter('year', param) 114 self.assertIsNone(local_filter) 115 116 def test_equals_true(self): 117 param = afscgap.param.IntEqualsParam(2025) 118 local_filter = afscgap.flat_local_filter.build_individual_filter('year', param) 119 self.assertTrue(local_filter.matches(self._make_target(2025))) 120 121 def test_equals_false(self): 122 param = afscgap.param.IntEqualsParam(2025) 123 local_filter = afscgap.flat_local_filter.build_individual_filter('year', param) 124 self.assertFalse(local_filter.matches(self._make_target(2024))) 125 126 def test_range_true(self): 127 param = afscgap.param.IntRangeParam(2024, 2026) 128 local_filter = afscgap.flat_local_filter.build_individual_filter('year', param) 129 self.assertTrue(local_filter.matches(self._make_target(2025))) 130 131 def test_range_false(self): 132 param = afscgap.param.IntRangeParam(2024, 2026) 133 local_filter = afscgap.flat_local_filter.build_individual_filter('year', param) 134 self.assertFalse(local_filter.matches(self._make_target(2023))) 135 136 def test_unsupported_accessor(self): 137 with self.assertRaises(RuntimeError): 138 param = afscgap.param.EmptyParam() 139 afscgap.flat_local_filter.build_individual_filter('unknown', param) 140 141 def test_unsupported_filter(self): 142 with self.assertRaises(RuntimeError): 143 param = unittest.mock.MagicMock() 144 param.get_filter_type = unittest.mock.MagicMock(return_value='unknown') 145 afscgap.flat_local_filter.build_individual_filter('year', param) 146 147 def _make_target(self, target_value): 148 mock_target = unittest.mock.MagicMock() 149 mock_target.get_year = unittest.mock.MagicMock(return_value=target_value) 150 return mock_target 151 152 153class BuildFilterTests(unittest.TestCase): 154 155 def setUp(self): 156 params = { 157 'year': afscgap.param.IntRangeParam(2024, 2026), 158 'srvy': afscgap.param.StrEqualsParam('GOA'), 159 'count': afscgap.param.EmptyParam() 160 } 161 self._local_filter = afscgap.flat_local_filter.build_filter(params) 162 163 def test_true(self): 164 example = self._build_example(2025, 'GOA', 123) 165 self.assertTrue(self._local_filter.matches(example)) 166 167 def test_false_int(self): 168 example = self._build_example(2023, 'GOA', 123) 169 self.assertFalse(self._local_filter.matches(example)) 170 171 def test_false_str(self): 172 example = self._build_example(2025, 'Other', 123) 173 self.assertFalse(self._local_filter.matches(example)) 174 175 def test_ignorable(self): 176 example = self._build_example(2025, 'GOA', None) 177 self.assertTrue(self._local_filter.matches(example)) 178 179 def _build_example(self, year, survey, count): 180 mock = unittest.mock.MagicMock() 181 mock.get_year = unittest.mock.MagicMock(return_value=year) 182 mock.get_srvy = unittest.mock.MagicMock(return_value=survey) 183 mock.get_count = unittest.mock.MagicMock(return_value=count) 184 return mock
18class EqualsLocalFilterTests(unittest.TestCase): 19 20 def setUp(self): 21 self._filter = afscgap.flat_local_filter.EqualsLocalFilter( 22 lambda x: x.get_value(), 23 1 24 ) 25 26 def test_matches_true(self): 27 self.assertTrue(self._filter.matches(self._make_target(1))) 28 29 def test_matches_false(self): 30 self.assertFalse(self._filter.matches(self._make_target(1.001))) 31 32 def test_matches_none(self): 33 self.assertFalse(self._filter.matches(self._make_target(None))) 34 35 def _make_target(self, value): 36 mock = unittest.mock.MagicMock() 37 mock.get_value = unittest.mock.MagicMock(return_value=value) 38 return mock
A class whose instances are single test cases.
By default, the test code itself should be placed in a method named 'runTest'.
If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute.
Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively.
If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run.
When subclassing TestCase, you can set these attributes:
- failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'.
- longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed.
- maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required.
20 def setUp(self): 21 self._filter = afscgap.flat_local_filter.EqualsLocalFilter( 22 lambda x: x.get_value(), 23 1 24 )
Hook method for setting up the test fixture before exercising it.
41class RangeLocalFilterTests(unittest.TestCase): 42 43 def setUp(self): 44 self._filter = afscgap.flat_local_filter.RangeLocalFilter( 45 lambda x: x.get_value(), 46 2, 47 4 48 ) 49 50 def test_out_lower(self): 51 self.assertFalse(self._filter.matches(self._make_target(1))) 52 53 def test_at_lower(self): 54 self.assertTrue(self._filter.matches(self._make_target(2))) 55 56 def test_mid(self): 57 self.assertTrue(self._filter.matches(self._make_target(3))) 58 59 def test_at_high(self): 60 self.assertTrue(self._filter.matches(self._make_target(4))) 61 62 def test_above_high(self): 63 self.assertFalse(self._filter.matches(self._make_target(5))) 64 65 def test_none(self): 66 self.assertFalse(self._filter.matches(self._make_target(None))) 67 68 def _make_target(self, value): 69 mock = unittest.mock.MagicMock() 70 mock.get_value = unittest.mock.MagicMock(return_value=value) 71 return mock
A class whose instances are single test cases.
By default, the test code itself should be placed in a method named 'runTest'.
If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute.
Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively.
If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run.
When subclassing TestCase, you can set these attributes:
- failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'.
- longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed.
- maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required.
43 def setUp(self): 44 self._filter = afscgap.flat_local_filter.RangeLocalFilter( 45 lambda x: x.get_value(), 46 2, 47 4 48 )
Hook method for setting up the test fixture before exercising it.
74class LogcalAndLocalFilterTests(unittest.TestCase): 75 76 def test_empty(self): 77 target = self._make_filter([]) 78 self.assertTrue(target.matches(1)) 79 80 def test_single_true(self): 81 target = self._make_filter([True]) 82 self.assertTrue(target.matches(1)) 83 84 def test_single_false(self): 85 target = self._make_filter([False]) 86 self.assertFalse(target.matches(1)) 87 88 def test_multiple_true(self): 89 target = self._make_filter([True, True]) 90 self.assertTrue(target.matches(1)) 91 92 def test_multiple_false(self): 93 target = self._make_filter([True, False]) 94 self.assertFalse(target.matches(1)) 95 96 def test_none(self): 97 target = self._make_filter([True, True]) 98 self.assertTrue(target.matches(None)) 99 100 def _make_filter(self, values): 101 inner_filters = map(lambda x: self._make_inner_filter(x), values) 102 return afscgap.flat_local_filter.LogicalAndLocalFilter(inner_filters) 103 104 def _make_inner_filter(self, value): 105 mock = unittest.mock.MagicMock() 106 mock.matches = unittest.mock.MagicMock(return_value=value) 107 return mock
A class whose instances are single test cases.
By default, the test code itself should be placed in a method named 'runTest'.
If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute.
Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively.
If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run.
When subclassing TestCase, you can set these attributes:
- failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'.
- longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed.
- maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required.
110class BuildIndividualFilterTests(unittest.TestCase): 111 112 def test_empty(self): 113 param = afscgap.param.EmptyParam() 114 local_filter = afscgap.flat_local_filter.build_individual_filter('year', param) 115 self.assertIsNone(local_filter) 116 117 def test_equals_true(self): 118 param = afscgap.param.IntEqualsParam(2025) 119 local_filter = afscgap.flat_local_filter.build_individual_filter('year', param) 120 self.assertTrue(local_filter.matches(self._make_target(2025))) 121 122 def test_equals_false(self): 123 param = afscgap.param.IntEqualsParam(2025) 124 local_filter = afscgap.flat_local_filter.build_individual_filter('year', param) 125 self.assertFalse(local_filter.matches(self._make_target(2024))) 126 127 def test_range_true(self): 128 param = afscgap.param.IntRangeParam(2024, 2026) 129 local_filter = afscgap.flat_local_filter.build_individual_filter('year', param) 130 self.assertTrue(local_filter.matches(self._make_target(2025))) 131 132 def test_range_false(self): 133 param = afscgap.param.IntRangeParam(2024, 2026) 134 local_filter = afscgap.flat_local_filter.build_individual_filter('year', param) 135 self.assertFalse(local_filter.matches(self._make_target(2023))) 136 137 def test_unsupported_accessor(self): 138 with self.assertRaises(RuntimeError): 139 param = afscgap.param.EmptyParam() 140 afscgap.flat_local_filter.build_individual_filter('unknown', param) 141 142 def test_unsupported_filter(self): 143 with self.assertRaises(RuntimeError): 144 param = unittest.mock.MagicMock() 145 param.get_filter_type = unittest.mock.MagicMock(return_value='unknown') 146 afscgap.flat_local_filter.build_individual_filter('year', param) 147 148 def _make_target(self, target_value): 149 mock_target = unittest.mock.MagicMock() 150 mock_target.get_year = unittest.mock.MagicMock(return_value=target_value) 151 return mock_target
A class whose instances are single test cases.
By default, the test code itself should be placed in a method named 'runTest'.
If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute.
Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively.
If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run.
When subclassing TestCase, you can set these attributes:
- failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'.
- longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed.
- maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required.
154class BuildFilterTests(unittest.TestCase): 155 156 def setUp(self): 157 params = { 158 'year': afscgap.param.IntRangeParam(2024, 2026), 159 'srvy': afscgap.param.StrEqualsParam('GOA'), 160 'count': afscgap.param.EmptyParam() 161 } 162 self._local_filter = afscgap.flat_local_filter.build_filter(params) 163 164 def test_true(self): 165 example = self._build_example(2025, 'GOA', 123) 166 self.assertTrue(self._local_filter.matches(example)) 167 168 def test_false_int(self): 169 example = self._build_example(2023, 'GOA', 123) 170 self.assertFalse(self._local_filter.matches(example)) 171 172 def test_false_str(self): 173 example = self._build_example(2025, 'Other', 123) 174 self.assertFalse(self._local_filter.matches(example)) 175 176 def test_ignorable(self): 177 example = self._build_example(2025, 'GOA', None) 178 self.assertTrue(self._local_filter.matches(example)) 179 180 def _build_example(self, year, survey, count): 181 mock = unittest.mock.MagicMock() 182 mock.get_year = unittest.mock.MagicMock(return_value=year) 183 mock.get_srvy = unittest.mock.MagicMock(return_value=survey) 184 mock.get_count = unittest.mock.MagicMock(return_value=count) 185 return mock
A class whose instances are single test cases.
By default, the test code itself should be placed in a method named 'runTest'.
If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute.
Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively.
If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run.
When subclassing TestCase, you can set these attributes:
- failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'.
- longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed.
- maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required.
156 def setUp(self): 157 params = { 158 'year': afscgap.param.IntRangeParam(2024, 2026), 159 'srvy': afscgap.param.StrEqualsParam('GOA'), 160 'count': afscgap.param.EmptyParam() 161 } 162 self._local_filter = afscgap.flat_local_filter.build_filter(params)
Hook method for setting up the test fixture before exercising it.