Skip to content

Commit

Permalink
Alloz variable neutralization in YAML test files
Browse files Browse the repository at this point in the history
Fix text for comparison with country-template parameter

Bump

Update CHANGELOG.md

Co-authored-by: sandcha <[email protected]>

Test neutralized_variables new attribute for YAML tests

Update CHANGELOG.md

Co-authored-by: sandcha <[email protected]>

Add tbs with neutralized variables to yaml tbs cache

fixup! Add tbs with neutralized variables to yaml tbs cache

Add test on yaml runner on tbs cache with neutralized variable

fixup! Add test on yaml runner on tbs cache with neutralized variable
  • Loading branch information
benjello committed Aug 31, 2021
1 parent 6b3e1d3 commit 201db36
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 18 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 35.5.0 [#1021](https://github.com/openfisca/openfisca-core/pull/1021)

#### New features

- Introduce `neutralize_variables` option in YAML test files
- A neutralized variable in a YAML test will return its default value when computed.

### 35.4.2 [#1026](https://github.com/openfisca/openfisca-core/pull/1026)

#### Bug fix
Expand Down Expand Up @@ -38,7 +45,7 @@
- When libraries do not implement their own types, MyPy provides stubs, or type sheds
- Thanks to `__future__.annotations`, those stubs or type sheds are casted to `typing.Any`
- Since 1.20.x, NumPy now provides their own type definitions
- The introduction of NumPy 1.20.x in #990 caused one major problem:
- The introduction of NumPy 1.20.x in #990 caused one major problem:
- It is general practice to do not import at runtime modules only used for typing purposes, thanks to the `typing.TYPE_CHEKING` variable
- The new `numpy.typing` module was being imported at runtime, rendering OpenFisca unusable to all users depending on previous versions of NumPy (1.20.x-)
- These changes revert #990 and solve #1009 and #1012
Expand Down
33 changes: 29 additions & 4 deletions openfisca_core/tools/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,22 @@ def import_yaml():
return yaml, Loader


TEST_KEYWORDS = {'absolute_error_margin', 'description', 'extensions', 'ignore_variables', 'input', 'keywords', 'max_spiral_loops', 'name', 'only_variables', 'output', 'period', 'reforms', 'relative_error_margin'}
TEST_KEYWORDS = {
'absolute_error_margin',
'description',
'extensions',
'ignore_variables',
'input',
'keywords',
'max_spiral_loops',
'name',
'neutralized_variables',
'only_variables',
'output',
'period',
'reforms',
'relative_error_margin'
}

yaml, Loader = import_yaml()

Expand Down Expand Up @@ -137,7 +152,12 @@ def runtest(self):
unexpected_keys = set(self.test.keys()).difference(TEST_KEYWORDS)
raise ValueError("Unexpected keys {} in test '{}' in file '{}'".format(unexpected_keys, self.name, self.fspath))

self.tax_benefit_system = _get_tax_benefit_system(self.baseline_tax_benefit_system, self.test.get('reforms', []), self.test.get('extensions', []))
self.tax_benefit_system = _get_tax_benefit_system(
self.baseline_tax_benefit_system,
self.test.get('reforms', []),
self.test.get('extensions', []),
self.test.get('neutralized_variables', [])
)

builder = SimulationBuilder()
input = self.test.get('input', {})
Expand Down Expand Up @@ -262,14 +282,16 @@ def pytest_collect_file(self, parent, path):
options = self.options)


def _get_tax_benefit_system(baseline, reforms, extensions):
def _get_tax_benefit_system(baseline, reforms, extensions, neutralized_variables):
if not isinstance(reforms, list):
reforms = [reforms]
if not isinstance(extensions, list):
extensions = [extensions]
if not isinstance(neutralized_variables, list):
neutralized_variables = [neutralized_variables]

# keep reforms order in cache, ignore extensions order
key = hash((id(baseline), ':'.join(reforms), frozenset(extensions)))
key = hash((id(baseline), ':'.join(reforms), frozenset(extensions), ':'.join(neutralized_variables)))
if _tax_benefit_system_cache.get(key):
return _tax_benefit_system_cache.get(key)

Expand All @@ -282,6 +304,9 @@ def _get_tax_benefit_system(baseline, reforms, extensions):
current_tax_benefit_system = current_tax_benefit_system.clone()
current_tax_benefit_system.load_extension(extension)

for neutralized_variable in neutralized_variables:
current_tax_benefit_system.neutralize_variable(neutralized_variable)

_tax_benefit_system_cache[key] = current_tax_benefit_system

return current_tax_benefit_system
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

setup(
name = 'OpenFisca-Core',
version = '35.4.2',
version = '35.5.0',
author = 'OpenFisca Team',
author_email = '[email protected]',
classifiers = [
Expand Down
4 changes: 4 additions & 0 deletions tests/core/test_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ def test_with_anchors(tax_benefit_system):
assert run_yaml_test(tax_benefit_system, 'test_with_anchors.yaml') == EXIT_OK


def test_with_neutralized_variables(tax_benefit_system):
assert run_yaml_test(tax_benefit_system, 'test_with_neutralized_variables.yaml') == EXIT_OK


def test_run_tests_from_directory_fail(tax_benefit_system):
assert run_yaml_test(tax_benefit_system, yaml_tests_dir) == EXIT_TESTSFAILED

Expand Down
38 changes: 26 additions & 12 deletions tests/core/tools/test_runner/test_yaml_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ def apply_reform(self, path):
def load_extension(self, extension):
pass

def neutralize_variable(self, variable_name):
pass

def entities_by_singular(self):
return {}

Expand Down Expand Up @@ -95,51 +98,62 @@ def test_variable_not_found():
def test_tax_benefit_systems_with_reform_cache():
baseline = TaxBenefitSystem()

ab_tax_benefit_system = _get_tax_benefit_system(baseline, 'ab', [])
ba_tax_benefit_system = _get_tax_benefit_system(baseline, 'ba', [])
ab_tax_benefit_system = _get_tax_benefit_system(baseline, 'ab', [], [])
ba_tax_benefit_system = _get_tax_benefit_system(baseline, 'ba', [], [])
assert ab_tax_benefit_system != ba_tax_benefit_system


def test_reforms_formats():
baseline = TaxBenefitSystem()

lonely_reform_tbs = _get_tax_benefit_system(baseline, 'lonely_reform', [])
list_lonely_reform_tbs = _get_tax_benefit_system(baseline, ['lonely_reform'], [])
lonely_reform_tbs = _get_tax_benefit_system(baseline, 'lonely_reform', [], [])
list_lonely_reform_tbs = _get_tax_benefit_system(baseline, ['lonely_reform'], [], [])
assert lonely_reform_tbs == list_lonely_reform_tbs


def test_reforms_order():
baseline = TaxBenefitSystem()

abba_tax_benefit_system = _get_tax_benefit_system(baseline, ['ab', 'ba'], [])
baab_tax_benefit_system = _get_tax_benefit_system(baseline, ['ba', 'ab'], [])
abba_tax_benefit_system = _get_tax_benefit_system(baseline, ['ab', 'ba'], [], [])
baab_tax_benefit_system = _get_tax_benefit_system(baseline, ['ba', 'ab'], [], [])
assert abba_tax_benefit_system != baab_tax_benefit_system # keep reforms order in cache


def test_tax_benefit_systems_with_extensions_cache():
baseline = TaxBenefitSystem()

xy_tax_benefit_system = _get_tax_benefit_system(baseline, [], 'xy')
yx_tax_benefit_system = _get_tax_benefit_system(baseline, [], 'yx')
xy_tax_benefit_system = _get_tax_benefit_system(baseline, [], 'xy', [])
yx_tax_benefit_system = _get_tax_benefit_system(baseline, [], 'yx', [])
assert xy_tax_benefit_system != yx_tax_benefit_system


def test_extensions_formats():
baseline = TaxBenefitSystem()

lonely_extension_tbs = _get_tax_benefit_system(baseline, [], 'lonely_extension')
list_lonely_extension_tbs = _get_tax_benefit_system(baseline, [], ['lonely_extension'])
lonely_extension_tbs = _get_tax_benefit_system(baseline, [], 'lonely_extension', [])
list_lonely_extension_tbs = _get_tax_benefit_system(baseline, [], ['lonely_extension'], [])
assert lonely_extension_tbs == list_lonely_extension_tbs


def test_extensions_order():
baseline = TaxBenefitSystem()

xy_tax_benefit_system = _get_tax_benefit_system(baseline, [], ['x', 'y'])
yx_tax_benefit_system = _get_tax_benefit_system(baseline, [], ['y', 'x'])
xy_tax_benefit_system = _get_tax_benefit_system(baseline, [], ['x', 'y'], [])
yx_tax_benefit_system = _get_tax_benefit_system(baseline, [], ['y', 'x'], [])
assert xy_tax_benefit_system == yx_tax_benefit_system # extensions order is ignored in cache


def test_tax_benefit_systems_with_neutralized_variables():
baseline = TaxBenefitSystem()

re_tax_benefit_system = _get_tax_benefit_system(baseline, 'r', ['e'], [])
ren_tax_benefit_system = _get_tax_benefit_system(baseline, 'r', ['e'], ['n'])
n_tax_benefit_system = _get_tax_benefit_system(baseline, [], [], ['n'])

assert re_tax_benefit_system != ren_tax_benefit_system
assert ren_tax_benefit_system != n_tax_benefit_system


def test_performance_graph_option_output():
test = {'input': {'salary': {'2017-01': 2000}}, 'output': {'salary': {'2017-01': 2000}}}
test_item = TestItem(test)
Expand Down
17 changes: 17 additions & 0 deletions tests/core/yaml_tests/test_with_neutralized_variables.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
- name: "Result outside neutralized variables"
period: 2021-01
neutralized_variables:
- housing_allowance
input:
age: 30
output:
basic_income: 600

- name: "Result within neutralized variables"
period: 2021-01
neutralized_variables:
- basic_income
input:
age: 30
output:
basic_income: 0

0 comments on commit 201db36

Please sign in to comment.