diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fbf6cacac..897aef89a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +### 35.3.5 [#997](https://github.com/openfisca/openfisca-core/pull/997) + +#### Technical changes + +- In tests, extract `CountryTaxBenefitSystem` to a fixture reusable by all the tests in the test suite. + - It allows for a better reusability of test scenarios available to new contributors. + - To mitigate possible performance issues, by default the fixture is initialised once per test module. + ### 35.3.4 [#999](https://github.com/openfisca/openfisca-core/pull/999) #### Technical improvements diff --git a/README.md b/README.md index d1f5767689..bbb2be461e 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ pytest tests/core/test_parameters.py -k test_parameter_for_period ## Style -This repository adheres to a certain coding style, and we invite you to follow it for your contributions to be integrated promptly. +This repository adheres to a [certain coding style](STYLEGUIDE.md), and we invite you to follow it for your contributions to be integrated promptly. Style checking is already run with `make test`. To run the style checker alone: diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md new file mode 100644 index 0000000000..db5ea925e2 --- /dev/null +++ b/STYLEGUIDE.md @@ -0,0 +1,84 @@ +# OpenFisca's Python Style Guide + +Arguments over code style and formatting are the bread and butter of most open-source projets out there, including OpenFisca. + +To avoid this, we have a style guide, that is a set or arbitrary but consistent conventions about how code should be written, for contributors and maintainers alike. + +## Notice + +### About this style guide + +The present style guide is a work in progress. + +It largely follows [Python Foundation's](https://www.python.org/dev/peps/pep-0008/), [NumPy's](https://numpydoc.readthedocs.io/en/latest/format.html) and [Google's](https://google.github.io/styleguide/pyguide.html), but it has a lot of her own as well. + +### Contributing + +Please refer whenever possible to this style guide both for your contributions and your reviews. + +If the style in question is not present and contentious, do not hesitate to include an addition to this guide within your proposal or review. + +## Imports + +1. In general, use import statements for entire namespaces and modules, rather than for classes and functions. Are exempt of this rule the `typing` module, NumPy's `typing` module, and `openfisca_core` module and submodules (but only in the case of class imports). + +2. In general, use absolute import statements rather that relative ones. Are exempt of this rule the modules relative to a submodule of OpenFisca, in order to improve the delimitation of internal and external interfaces. + +3. Always follow this order for your imports: system modules, third party modules, third party OpenFisca modules, external OpenFisca Core modules, internal OpenFisca Core modules. + +For example given: + +``` +/openfisca_core/axes/__init__.py +/openfisca_core/axes/nothing.py +/openfisca_core/axes/something.py +``` + +Whenever possible we should expect: + +```python +# /openfisca_core/axes/nothing.py +# +# Yes + +import copy +from typing import List + +import numpy +from numpy.typing import ArrayLike + +from openfisca_country_template import entities + +from openfisca_core import tools +from openfisca_core.variables import Variable + +from . import Something + +def do(this: List) -> ArrayLike: + that = copy.deepcopy(this) + array = numpy.ndarray(that) + return Something(entities.Person, Variable) +``` + +And avoid: + +```python +# /openfisca_core/axes/nothing.py +# +# No + +from openfisca_country_template.entities import Person +from openfisca_core import variables +from openfisca_core.tools import assert_near +from openfisca_core import axes + +from numpy import ndarray +from copy import deepcopy +import typing +import numpy.typing + +def do(this: typing.List) -> numpy.typing.ArrayLike: + that = deepcopy(this) + array = ndarray(that) + return axes.Something(Person, variables.Variable) +``` diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000000..ae14b71c8a --- /dev/null +++ b/conftest.py @@ -0,0 +1,5 @@ +pytest_plugins = [ + "tests.fixtures.entities", + "tests.fixtures.simulations", + "tests.fixtures.taxbenefitsystems", + ] diff --git a/setup.py b/setup.py index fb8ccf5622..601c0e7493 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,4 @@ #! /usr/bin/env python -# -*- coding: utf-8 -*- - from setuptools import setup, find_packages @@ -37,7 +35,7 @@ setup( name = 'OpenFisca-Core', - version = '35.3.4', + version = '35.3.5', author = 'OpenFisca Team', author_email = 'contact@openfisca.org', classifiers = [ diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/core/parameter_validation/test_parameter_clone.py b/tests/core/parameter_validation/test_parameter_clone.py index 7b839caa15..a14630e9a0 100644 --- a/tests/core/parameter_validation/test_parameter_clone.py +++ b/tests/core/parameter_validation/test_parameter_clone.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- -from ..test_countries import tax_benefit_system - import os + from openfisca_core.parameters import ParameterNode + BASE_DIR = os.path.dirname(os.path.abspath(__file__)) year = 2016 @@ -20,7 +19,7 @@ def test_clone(): assert id(clone.node1.param) != id(parameters.node1.param) -def test_clone_parameter(): +def test_clone_parameter(tax_benefit_system): param = tax_benefit_system.parameters.taxes.income_tax_rate clone = param.clone() @@ -32,7 +31,7 @@ def test_clone_parameter(): assert clone.values_list == param.values_list -def test_clone_parameter_node(): +def test_clone_parameter_node(tax_benefit_system): node = tax_benefit_system.parameters.taxes clone = node.clone() @@ -41,7 +40,7 @@ def test_clone_parameter_node(): assert clone.children['income_tax_rate'] is not node.children['income_tax_rate'] -def test_clone_scale(): +def test_clone_scale(tax_benefit_system): scale = tax_benefit_system.parameters.taxes.social_security_contribution clone = scale.clone() @@ -49,7 +48,7 @@ def test_clone_scale(): assert clone.brackets[0].rate is not scale.brackets[0].rate -def test_deep_edit(): +def test_deep_edit(tax_benefit_system): parameters = tax_benefit_system.parameters clone = parameters.clone() diff --git a/tests/core/test_axes.py b/tests/core/test_axes.py index 686c9b27e7..f106a82a5b 100644 --- a/tests/core/test_axes.py +++ b/tests/core/test_axes.py @@ -1,31 +1,27 @@ import pytest -from pytest import fixture, approx -from openfisca_core.simulation_builder import SimulationBuilder -from .test_simulation_builder import * # noqa: F401 - - -@fixture -def simulation_builder(): - return SimulationBuilder() +from openfisca_core.simulations import SimulationBuilder +from openfisca_core.tools import test_runner # With periods -def test_add_axis_without_period(simulation_builder, persons): +def test_add_axis_without_period(persons): + simulation_builder = SimulationBuilder() simulation_builder.set_default_period('2018-11') simulation_builder.add_person_entity(persons, {'Alicia': {}}) simulation_builder.register_variable('salary', persons) simulation_builder.add_parallel_axis({'count': 3, 'name': 'salary', 'min': 0, 'max': 3000}) simulation_builder.expand_axes() - assert simulation_builder.get_input('salary', '2018-11') == approx([0, 1500, 3000]) + assert simulation_builder.get_input('salary', '2018-11') == pytest.approx([0, 1500, 3000]) # With variables -def test_add_axis_on_a_non_existing_variable(simulation_builder, persons): +def test_add_axis_on_a_non_existing_variable(persons): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}}) simulation_builder.add_parallel_axis({'count': 3, 'name': 'ubi', 'min': 0, 'max': 3000, 'period': '2018-11'}) @@ -33,12 +29,13 @@ def test_add_axis_on_a_non_existing_variable(simulation_builder, persons): simulation_builder.expand_axes() -def test_add_axis_on_an_existing_variable_with_input(simulation_builder, persons): +def test_add_axis_on_an_existing_variable_with_input(persons): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {'salary': {'2018-11': 1000}}}) simulation_builder.register_variable('salary', persons) simulation_builder.add_parallel_axis({'count': 3, 'name': 'salary', 'min': 0, 'max': 3000, 'period': '2018-11'}) simulation_builder.expand_axes() - assert simulation_builder.get_input('salary', '2018-11') == approx([0, 1500, 3000]) + assert simulation_builder.get_input('salary', '2018-11') == pytest.approx([0, 1500, 3000]) assert simulation_builder.get_count('persons') == 3 assert simulation_builder.get_ids('persons') == ['Alicia0', 'Alicia1', 'Alicia2'] @@ -46,27 +43,30 @@ def test_add_axis_on_an_existing_variable_with_input(simulation_builder, persons # With entities -def test_add_axis_on_persons(simulation_builder, persons): +def test_add_axis_on_persons(persons): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}}) simulation_builder.register_variable('salary', persons) simulation_builder.add_parallel_axis({'count': 3, 'name': 'salary', 'min': 0, 'max': 3000, 'period': '2018-11'}) simulation_builder.expand_axes() - assert simulation_builder.get_input('salary', '2018-11') == approx([0, 1500, 3000]) + assert simulation_builder.get_input('salary', '2018-11') == pytest.approx([0, 1500, 3000]) assert simulation_builder.get_count('persons') == 3 assert simulation_builder.get_ids('persons') == ['Alicia0', 'Alicia1', 'Alicia2'] -def test_add_two_axes(simulation_builder, persons): +def test_add_two_axes(persons): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}}) simulation_builder.register_variable('salary', persons) simulation_builder.add_parallel_axis({'count': 3, 'name': 'salary', 'min': 0, 'max': 3000, 'period': '2018-11'}) simulation_builder.add_parallel_axis({'count': 3, 'name': 'pension', 'min': 0, 'max': 2000, 'period': '2018-11'}) simulation_builder.expand_axes() - assert simulation_builder.get_input('salary', '2018-11') == approx([0, 1500, 3000]) - assert simulation_builder.get_input('pension', '2018-11') == approx([0, 1000, 2000]) + assert simulation_builder.get_input('salary', '2018-11') == pytest.approx([0, 1500, 3000]) + assert simulation_builder.get_input('pension', '2018-11') == pytest.approx([0, 1000, 2000]) -def test_add_axis_with_group(simulation_builder, persons): +def test_add_axis_with_group(persons): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}, 'Javier': {}}) simulation_builder.register_variable('salary', persons) simulation_builder.add_parallel_axis({'count': 2, 'name': 'salary', 'min': 0, 'max': 3000, 'period': '2018-11'}) @@ -74,59 +74,64 @@ def test_add_axis_with_group(simulation_builder, persons): simulation_builder.expand_axes() assert simulation_builder.get_count('persons') == 4 assert simulation_builder.get_ids('persons') == ['Alicia0', 'Javier1', 'Alicia2', 'Javier3'] - assert simulation_builder.get_input('salary', '2018-11') == approx([0, 0, 3000, 3000]) + assert simulation_builder.get_input('salary', '2018-11') == pytest.approx([0, 0, 3000, 3000]) -def test_add_axis_with_group_int_period(simulation_builder, persons): +def test_add_axis_with_group_int_period(persons): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}, 'Javier': {}}) simulation_builder.register_variable('salary', persons) simulation_builder.add_parallel_axis({'count': 2, 'name': 'salary', 'min': 0, 'max': 3000, 'period': 2018}) simulation_builder.add_parallel_axis({'count': 2, 'name': 'salary', 'min': 0, 'max': 3000, 'period': 2018, 'index': 1}) simulation_builder.expand_axes() - assert simulation_builder.get_input('salary', '2018') == approx([0, 0, 3000, 3000]) + assert simulation_builder.get_input('salary', '2018') == pytest.approx([0, 0, 3000, 3000]) -def test_add_axis_on_group_entity(simulation_builder, persons, group_entity): +def test_add_axis_on_households(persons, households): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}, 'Javier': {}, 'Tom': {}}) - simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Tom'], group_entity, { + simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Tom'], households, { 'housea': {'parents': ['Alicia', 'Javier']}, 'houseb': {'parents': ['Tom']}, }) - simulation_builder.register_variable('rent', group_entity) + simulation_builder.register_variable('rent', households) simulation_builder.add_parallel_axis({'count': 2, 'name': 'rent', 'min': 0, 'max': 3000, 'period': '2018-11'}) simulation_builder.expand_axes() assert simulation_builder.get_count('households') == 4 assert simulation_builder.get_ids('households') == ['housea0', 'houseb1', 'housea2', 'houseb3'] - assert simulation_builder.get_input('rent', '2018-11') == approx([0, 0, 3000, 0]) + assert simulation_builder.get_input('rent', '2018-11') == pytest.approx([0, 0, 3000, 0]) -def test_axis_on_group_expands_persons(simulation_builder, persons, group_entity): +def test_axis_on_group_expands_persons(persons, households): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}, 'Javier': {}, 'Tom': {}}) - simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Tom'], group_entity, { + simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Tom'], households, { 'housea': {'parents': ['Alicia', 'Javier']}, 'houseb': {'parents': ['Tom']}, }) - simulation_builder.register_variable('rent', group_entity) + simulation_builder.register_variable('rent', households) simulation_builder.add_parallel_axis({'count': 2, 'name': 'rent', 'min': 0, 'max': 3000, 'period': '2018-11'}) simulation_builder.expand_axes() assert simulation_builder.get_count('persons') == 6 -def test_add_axis_distributes_roles(simulation_builder, persons, group_entity): +def test_add_axis_distributes_roles(persons, households): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}, 'Javier': {}, 'Tom': {}}) - simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Tom'], group_entity, { + simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Tom'], households, { 'housea': {'parents': ['Alicia']}, 'houseb': {'parents': ['Tom'], 'children': ['Javier']}, }) - simulation_builder.register_variable('rent', group_entity) + simulation_builder.register_variable('rent', households) simulation_builder.add_parallel_axis({'count': 2, 'name': 'rent', 'min': 0, 'max': 3000, 'period': '2018-11'}) simulation_builder.expand_axes() assert [role.key for role in simulation_builder.get_roles('households')] == ['parent', 'child', 'parent', 'parent', 'child', 'parent'] -def test_add_axis_on_persons_distributes_roles(simulation_builder, persons, group_entity): +def test_add_axis_on_persons_distributes_roles(persons, households): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}, 'Javier': {}, 'Tom': {}}) - simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Tom'], group_entity, { + simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Tom'], households, { 'housea': {'parents': ['Alicia']}, 'houseb': {'parents': ['Tom'], 'children': ['Javier']}, }) @@ -136,30 +141,33 @@ def test_add_axis_on_persons_distributes_roles(simulation_builder, persons, grou assert [role.key for role in simulation_builder.get_roles('households')] == ['parent', 'child', 'parent', 'parent', 'child', 'parent'] -def test_add_axis_distributes_memberships(simulation_builder, persons, group_entity): +def test_add_axis_distributes_memberships(persons, households): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}, 'Javier': {}, 'Tom': {}}) - simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Tom'], group_entity, { + simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Tom'], households, { 'housea': {'parents': ['Alicia']}, 'houseb': {'parents': ['Tom'], 'children': ['Javier']}, }) - simulation_builder.register_variable('rent', group_entity) + simulation_builder.register_variable('rent', households) simulation_builder.add_parallel_axis({'count': 2, 'name': 'rent', 'min': 0, 'max': 3000, 'period': '2018-11'}) simulation_builder.expand_axes() assert simulation_builder.get_memberships('households') == [0, 1, 1, 2, 3, 3] -def test_add_perpendicular_axes(simulation_builder, persons): +def test_add_perpendicular_axes(persons): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, {'Alicia': {}}) simulation_builder.register_variable('salary', persons) simulation_builder.register_variable('pension', persons) simulation_builder.add_parallel_axis({'count': 3, 'name': 'salary', 'min': 0, 'max': 3000, 'period': '2018-11'}) simulation_builder.add_perpendicular_axis({'count': 2, 'name': 'pension', 'min': 0, 'max': 2000, 'period': '2018-11'}) simulation_builder.expand_axes() - assert simulation_builder.get_input('salary', '2018-11') == approx([0, 1500, 3000, 0, 1500, 3000]) - assert simulation_builder.get_input('pension', '2018-11') == approx([0, 0, 0, 2000, 2000, 2000]) + assert simulation_builder.get_input('salary', '2018-11') == pytest.approx([0, 1500, 3000, 0, 1500, 3000]) + assert simulation_builder.get_input('pension', '2018-11') == pytest.approx([0, 0, 0, 2000, 2000, 2000]) -def test_add_perpendicular_axis_on_an_existing_variable_with_input(simulation_builder, persons): +def test_add_perpendicular_axis_on_an_existing_variable_with_input(persons): + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, { 'Alicia': { 'salary': {'2018-11': 1000}, @@ -171,14 +179,14 @@ def test_add_perpendicular_axis_on_an_existing_variable_with_input(simulation_bu simulation_builder.add_parallel_axis({'count': 3, 'name': 'salary', 'min': 0, 'max': 3000, 'period': '2018-11'}) simulation_builder.add_perpendicular_axis({'count': 2, 'name': 'pension', 'min': 0, 'max': 2000, 'period': '2018-11'}) simulation_builder.expand_axes() - assert simulation_builder.get_input('salary', '2018-11') == approx([0, 1500, 3000, 0, 1500, 3000]) - assert simulation_builder.get_input('pension', '2018-11') == approx([0, 0, 0, 2000, 2000, 2000]) + assert simulation_builder.get_input('salary', '2018-11') == pytest.approx([0, 1500, 3000, 0, 1500, 3000]) + assert simulation_builder.get_input('pension', '2018-11') == pytest.approx([0, 0, 0, 2000, 2000, 2000]) + # Integration test -def test_simulation_with_axes(simulation_builder): - from .test_countries import tax_benefit_system +def test_simulation_with_axes(tax_benefit_system): input_yaml = """ persons: Alicia: {salary: {2018-11: 0}} @@ -197,7 +205,7 @@ def test_simulation_with_axes(simulation_builder): max: 3000 period: 2018-11 """ - data = yaml.safe_load(input_yaml) - simulation = simulation_builder.build_from_dict(tax_benefit_system, data) - assert simulation.get_array('salary', '2018-11') == approx([0, 0, 0, 0, 0, 0]) - assert simulation.get_array('rent', '2018-11') == approx([0, 0, 3000, 0]) + data = test_runner.yaml.safe_load(input_yaml) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, data) + assert simulation.get_array('salary', '2018-11') == pytest.approx([0, 0, 0, 0, 0, 0]) + assert simulation.get_array('rent', '2018-11') == pytest.approx([0, 0, 3000, 0]) diff --git a/tests/core/test_calculate_output.py b/tests/core/test_calculate_output.py index 63959155d2..6a11a27d84 100644 --- a/tests/core/test_calculate_output.py +++ b/tests/core/test_calculate_output.py @@ -1,49 +1,48 @@ -from openfisca_core.model_api import * # noqa analysis:ignore -from openfisca_core.simulation_builder import SimulationBuilder -from openfisca_core.tools import assert_near +import pytest -from openfisca_country_template import CountryTaxBenefitSystem -from openfisca_country_template.entities import * # noqa analysis:ignore -from openfisca_country_template.situation_examples import single +from openfisca_country_template import entities, situation_examples -from pytest import fixture, raises - - -@fixture -def simulation(): - return SimulationBuilder().build_from_entities(tax_benefit_system, single) +from openfisca_core import periods, simulations, tools +from openfisca_core.simulations import SimulationBuilder +from openfisca_core.variables import Variable class simple_variable(Variable): - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH value_type = int class variable_with_calculate_output_add(Variable): - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH value_type = int - calculate_output = calculate_output_add + calculate_output = simulations.calculate_output_add class variable_with_calculate_output_divide(Variable): - entity = Person - definition_period = YEAR + entity = entities.Person + definition_period = periods.YEAR value_type = int - calculate_output = calculate_output_divide + calculate_output = simulations.calculate_output_divide + + +@pytest.fixture(scope = "module", autouse = True) +def add_variables_to_tax_benefit_system(tax_benefit_system): + tax_benefit_system.add_variables( + simple_variable, + variable_with_calculate_output_add, + variable_with_calculate_output_divide + ) -tax_benefit_system = CountryTaxBenefitSystem() -tax_benefit_system.add_variables( - simple_variable, - variable_with_calculate_output_add, - variable_with_calculate_output_divide - ) +@pytest.fixture +def simulation(tax_benefit_system): + return SimulationBuilder().build_from_entities(tax_benefit_system, situation_examples.single) def test_calculate_output_default(simulation): - with raises(ValueError): + with pytest.raises(ValueError): simulation.calculate_output('simple_variable', 2017) @@ -51,9 +50,9 @@ def test_calculate_output_add(simulation): simulation.set_input('variable_with_calculate_output_add', '2017-01', [10]) simulation.set_input('variable_with_calculate_output_add', '2017-05', [20]) simulation.set_input('variable_with_calculate_output_add', '2017-12', [70]) - assert_near(simulation.calculate_output('variable_with_calculate_output_add', 2017), 100) + tools.assert_near(simulation.calculate_output('variable_with_calculate_output_add', 2017), 100) def test_calculate_output_divide(simulation): simulation.set_input('variable_with_calculate_output_divide', 2017, [12000]) - assert_near(simulation.calculate_output('variable_with_calculate_output_divide', '2017-06'), 1000) + tools.assert_near(simulation.calculate_output('variable_with_calculate_output_divide', '2017-06'), 1000) diff --git a/tests/core/test_countries.py b/tests/core/test_countries.py index e7e8ec0ee1..aeb4d762c7 100644 --- a/tests/core/test_countries.py +++ b/tests/core/test_countries.py @@ -1,137 +1,128 @@ -# -*- coding: utf-8 -*- - -from pytest import fixture, raises +import pytest +from openfisca_core import periods, populations, tools +from openfisca_core.errors import VariableNameConflictError, VariableNotFoundError +from openfisca_core.simulations import SimulationBuilder from openfisca_core.variables import Variable -from openfisca_core.periods import MONTH -from openfisca_core.simulation_builder import SimulationBuilder -from openfisca_core.taxbenefitsystems import VariableNameConflict, VariableNotFound -from openfisca_core import periods -from openfisca_core.populations import DIVIDE -from openfisca_country_template import CountryTaxBenefitSystem -from openfisca_core.tools import assert_near +PERIOD = periods.period("2016-01") -tax_benefit_system = CountryTaxBenefitSystem() +@pytest.mark.parametrize("simulation", [({"salary": 2000}, PERIOD)], indirect = True) +def test_input_variable(simulation): + result = simulation.calculate("salary", PERIOD) + tools.assert_near(result, [2000], absolute_error_margin = 0.01) -@fixture -def period(): - return "2016-01" +@pytest.mark.parametrize("simulation", [({"salary": 2000}, PERIOD)], indirect = True) +def test_basic_calculation(simulation): + result = simulation.calculate("income_tax", PERIOD) + tools.assert_near(result, [300], absolute_error_margin = 0.01) -@fixture -def make_simulation(period): - def _make_simulation(data): - builder = SimulationBuilder() - builder.default_period = period - return builder.build_from_variables(tax_benefit_system, data) - return _make_simulation +@pytest.mark.parametrize("simulation", [({"salary": 24000}, PERIOD)], indirect = True) +def test_calculate_add(simulation): + result = simulation.calculate_add("income_tax", PERIOD) + tools.assert_near(result, [3600], absolute_error_margin = 0.01) -@fixture -def make_isolated_simulation(period): - def _make_simulation(tbs, data): - builder = SimulationBuilder() - builder.default_period = period - return builder.build_from_variables(tbs, data) - return _make_simulation +@pytest.mark.parametrize( + "simulation", + [({"accommodation_size": 100, "housing_occupancy_status": "tenant"}, PERIOD)], + indirect = True, + ) +def test_calculate_divide(simulation): + result = simulation.calculate_divide("housing_tax", PERIOD) + tools.assert_near(result, [1000 / 12.], absolute_error_margin = 0.01) -def test_input_variable(make_simulation, period): - simulation = make_simulation({'salary': 2000}) - assert_near(simulation.calculate('salary', period), [2000], absolute_error_margin = 0.01) +@pytest.mark.parametrize("simulation", [({"salary": 20000}, PERIOD)], indirect = True) +def test_bareme(simulation): + result = simulation.calculate("social_security_contribution", PERIOD) + expected = [0.02 * 6000 + 0.06 * 6400 + 0.12 * 7600] + tools.assert_near(result, expected, absolute_error_margin = 0.01) -def test_basic_calculation(make_simulation, period): - simulation = make_simulation({'salary': 2000}) - assert_near(simulation.calculate('income_tax', period), [300], absolute_error_margin = 0.01) +@pytest.mark.parametrize("simulation", [({}, PERIOD)], indirect = True) +def test_non_existing_variable(simulation): + with pytest.raises(VariableNotFoundError): + simulation.calculate("non_existent_variable", PERIOD) -def test_calculate_add(make_simulation, period): - simulation = make_simulation({'salary': 24000}) - assert_near(simulation.calculate_add('income_tax', period), [3600], absolute_error_margin = 0.01) +@pytest.mark.parametrize("simulation", [({}, PERIOD)], indirect = True) +def test_calculate_variable_with_wrong_definition_period(simulation): + year = str(PERIOD.this_year) -def test_calculate_divide(make_simulation, period): - simulation = make_simulation({ - 'accommodation_size': 100, - 'housing_occupancy_status': 'tenant', - }) - assert_near(simulation.calculate_divide('housing_tax', period), [1000 / 12.], absolute_error_margin = 0.01) + with pytest.raises(ValueError) as error: + simulation.calculate("basic_income", year) + error_message = str(error.value) + expected_words = ["period", year, "month", "basic_income", "ADD"] -def test_bareme(make_simulation, period): - simulation = make_simulation({'salary': 20000}) - expected_result = 0.02 * 6000 + 0.06 * 6400 + 0.12 * 7600 - assert_near(simulation.calculate('social_security_contribution', period), [expected_result], absolute_error_margin = 0.01) + for word in expected_words: + assert word in error_message, f"Expected '{word}' in error message '{error_message}'" -def test_non_existing_variable(make_simulation): - simulation = make_simulation({}) - with raises(VariableNotFound): - simulation.calculate('non_existent_variable', 2013) +@pytest.mark.parametrize("simulation", [({}, PERIOD)], indirect = True) +def test_divide_option_on_month_defined_variable(simulation): + with pytest.raises(ValueError): + simulation.person("disposable_income", PERIOD, options = [populations.DIVIDE]) -def test_calculate_variable_with_wrong_definition_period(make_simulation): - simulation = make_simulation({}) +@pytest.mark.parametrize("simulation", [({}, PERIOD)], indirect = True) +def test_divide_option_with_complex_period(simulation): + quarter = PERIOD.last_3_months - with raises(ValueError) as error: - simulation.calculate('basic_income', 2016) + with pytest.raises(ValueError) as error: + simulation.household("housing_tax", quarter, options = [populations.DIVIDE]) error_message = str(error.value) - expected_words = ['period', '2016', 'month', 'basic_income', 'ADD'] + expected_words = ["DIVIDE", "one-year", "one-month", "period"] for word in expected_words: - assert word in error_message, 'Expected "{}" in error message "{}"'.format(word, error_message) - + assert word in error_message, f"Expected '{word}' in error message '{error_message}'" -def test_divide_option_on_month_defined_variable(make_simulation): - simulation = make_simulation({}) - with raises(ValueError): - simulation.person('disposable_income', "2016-01", options = [DIVIDE]) +def test_input_with_wrong_period(tax_benefit_system): + year = str(PERIOD.this_year) + variables = {"basic_income": {year: 12000}} + simulation_builder = SimulationBuilder() + simulation_builder.set_default_period(PERIOD) -def test_divide_option_with_complex_period(make_simulation): - simulation = make_simulation({}) - quarter = periods.period('2013-12').last_3_months - with raises(ValueError): - simulation.household('housing_tax', quarter, options = [DIVIDE]) + with pytest.raises(ValueError): + simulation_builder.build_from_variables(tax_benefit_system, variables) -def test_input_with_wrong_period(make_simulation): - with raises(ValueError): - make_simulation({'basic_income': {2015: 12000}}) +def test_variable_with_reference(make_simulation, isolated_tax_benefit_system): + variables = {"salary": 4000} + simulation = make_simulation(isolated_tax_benefit_system, variables, PERIOD) + result = simulation.calculate("disposable_income", PERIOD) -def test_variable_with_reference(make_isolated_simulation): - tax_benefit_system = CountryTaxBenefitSystem() # Work in isolation - - simulation_base = make_isolated_simulation(tax_benefit_system, {'salary': 4000}) - - revenu_disponible_avant_reforme = simulation_base.calculate('disposable_income', "2016-01") - assert(revenu_disponible_avant_reforme > 0) + assert result > 0 class disposable_income(Variable): - definition_period = MONTH + definition_period = periods.MONTH def formula(household, period): return household.empty_array() - tax_benefit_system.update_variable(disposable_income) + isolated_tax_benefit_system.update_variable(disposable_income) + simulation = make_simulation(isolated_tax_benefit_system, variables, PERIOD) - simulation_reform = make_isolated_simulation(tax_benefit_system, {'salary': 4000}) - revenu_disponible_apres_reforme = simulation_reform.calculate('disposable_income', "2016-01") + result = simulation.calculate("disposable_income", PERIOD) - assert(revenu_disponible_apres_reforme == 0) + assert result == 0 -def test_variable_name_conflict(): +def test_variable_name_conflict(tax_benefit_system): + class disposable_income(Variable): - reference = 'disposable_income' - definition_period = MONTH + reference = "disposable_income" + definition_period = periods.MONTH def formula(household, period): return household.empty_array() - with raises(VariableNameConflict): + + with pytest.raises(VariableNameConflictError): tax_benefit_system.add_variable(disposable_income) diff --git a/tests/core/test_cycles.py b/tests/core/test_cycles.py index 949df40336..1c4361ded2 100644 --- a/tests/core/test_cycles.py +++ b/tests/core/test_cycles.py @@ -1,33 +1,28 @@ -# -*- coding: utf-8 -*- +import pytest -from openfisca_core import periods -from openfisca_core.periods import MONTH -from openfisca_core.simulation_builder import SimulationBuilder -from openfisca_core.simulations import CycleError -from openfisca_core.variables import Variable - -from openfisca_country_template import CountryTaxBenefitSystem -from openfisca_country_template.entities import Person -from openfisca_core.tools import assert_near +from openfisca_country_template import entities -from pytest import fixture, raises +from openfisca_core import periods, tools +from openfisca_core.errors import CycleError +from openfisca_core.simulations import SimulationBuilder +from openfisca_core.variables import Variable -@fixture +@pytest.fixture def reference_period(): return periods.period('2013-01') -@fixture -def simulation(reference_period): +@pytest.fixture +def simulation(tax_benefit_system): return SimulationBuilder().build_default_simulation(tax_benefit_system) # 1 <--> 2 with same period class variable1(Variable): value_type = int - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH def formula(person, period): return person('variable2', period) @@ -35,8 +30,8 @@ def formula(person, period): class variable2(Variable): value_type = int - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH def formula(person, period): return person('variable1', period) @@ -45,8 +40,8 @@ def formula(person, period): # 3 <--> 4 with a period offset class variable3(Variable): value_type = int - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH def formula(person, period): return person('variable4', period.last_month) @@ -54,8 +49,8 @@ def formula(person, period): class variable4(Variable): value_type = int - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH def formula(person, period): return person('variable3', period) @@ -65,8 +60,8 @@ def formula(person, period): # <--- class variable5(Variable): value_type = int - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH def formula(person, period): variable6 = person('variable6', period.last_month) @@ -75,8 +70,8 @@ def formula(person, period): class variable6(Variable): value_type = int - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH def formula(person, period): variable5 = person('variable5', period) @@ -85,8 +80,8 @@ def formula(person, period): class variable7(Variable): value_type = int - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH def formula(person, period): variable5 = person('variable5', period) @@ -96,8 +91,8 @@ def formula(person, period): # december cotisation depending on november value class cotisation(Variable): value_type = int - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH def formula(person, period): if period.start.month == 12: @@ -106,29 +101,37 @@ def formula(person, period): return person.empty_array() + 1 -# TaxBenefitSystem instance declared after formulas -tax_benefit_system = CountryTaxBenefitSystem() -tax_benefit_system.add_variables(variable1, variable2, variable3, variable4, - variable5, variable6, variable7, cotisation) +@pytest.fixture(scope = "module", autouse = True) +def add_variables_to_tax_benefit_system(tax_benefit_system): + tax_benefit_system.add_variables( + variable1, + variable2, + variable3, + variable4, + variable5, + variable6, + variable7, + cotisation, + ) def test_pure_cycle(simulation, reference_period): - with raises(CycleError): + with pytest.raises(CycleError): simulation.calculate('variable1', period = reference_period) def test_spirals_result_in_default_value(simulation, reference_period): variable3 = simulation.calculate('variable3', period = reference_period) - assert_near(variable3, [0]) + tools.assert_near(variable3, [0]) def test_spiral_heuristic(simulation, reference_period): variable5 = simulation.calculate('variable5', period = reference_period) variable6 = simulation.calculate('variable6', period = reference_period) variable6_last_month = simulation.calculate('variable6', reference_period.last_month) - assert_near(variable5, [11]) - assert_near(variable6, [11]) - assert_near(variable6_last_month, [11]) + tools.assert_near(variable5, [11]) + tools.assert_near(variable6, [11]) + tools.assert_near(variable6_last_month, [11]) def test_spiral_cache(simulation, reference_period): @@ -140,4 +143,4 @@ def test_spiral_cache(simulation, reference_period): def test_cotisation_1_level(simulation, reference_period): month = reference_period.last_month cotisation = simulation.calculate('cotisation', period = month) - assert_near(cotisation, [0]) + tools.assert_near(cotisation, [0]) diff --git a/tests/core/test_dump_restore.py b/tests/core/test_dump_restore.py index fcc53f516f..5d377913c9 100644 --- a/tests/core/test_dump_restore.py +++ b/tests/core/test_dump_restore.py @@ -1,41 +1,37 @@ -# -*- coding: utf-8 -*- - - import shutil import tempfile -from numpy.testing import assert_array_equal +from numpy import testing -from openfisca_core.simulation_builder import SimulationBuilder -from openfisca_country_template.situation_examples import couple -from openfisca_core.tools.simulation_dumper import dump_simulation, restore_simulation +from openfisca_country_template import situation_examples -from .test_countries import tax_benefit_system +from openfisca_core.simulations import SimulationBuilder +from openfisca_core.tools import simulation_dumper -def test_dump(): +def test_dump(tax_benefit_system): directory = tempfile.mkdtemp(prefix = "openfisca_") - simulation = SimulationBuilder().build_from_entities(tax_benefit_system, couple) + simulation = SimulationBuilder().build_from_entities(tax_benefit_system, situation_examples.couple) calculated_value = simulation.calculate('disposable_income', '2018-01') - dump_simulation(simulation, directory) + simulation_dumper.dump_simulation(simulation, directory) - simulation_2 = restore_simulation(directory, tax_benefit_system) + simulation_2 = simulation_dumper.restore_simulation(directory, tax_benefit_system) # Check entities structure have been restored - assert_array_equal(simulation.person.ids, simulation_2.person.ids) - assert_array_equal(simulation.person.count, simulation_2.person.count) - assert_array_equal(simulation.household.ids, simulation_2.household.ids) - assert_array_equal(simulation.household.count, simulation_2.household.count) - assert_array_equal(simulation.household.members_position, simulation_2.household.members_position) - assert_array_equal(simulation.household.members_entity_id, simulation_2.household.members_entity_id) - assert_array_equal(simulation.household.members_role, simulation_2.household.members_role) + testing.assert_array_equal(simulation.person.ids, simulation_2.person.ids) + testing.assert_array_equal(simulation.person.count, simulation_2.person.count) + testing.assert_array_equal(simulation.household.ids, simulation_2.household.ids) + testing.assert_array_equal(simulation.household.count, simulation_2.household.count) + testing.assert_array_equal(simulation.household.members_position, simulation_2.household.members_position) + testing.assert_array_equal(simulation.household.members_entity_id, simulation_2.household.members_entity_id) + testing.assert_array_equal(simulation.household.members_role, simulation_2.household.members_role) # Check calculated values are in cache disposable_income_holder = simulation_2.person.get_holder('disposable_income') cached_value = disposable_income_holder.get_array('2018-01') assert cached_value is not None - assert_array_equal(cached_value, calculated_value) + testing.assert_array_equal(cached_value, calculated_value) shutil.rmtree(directory) diff --git a/tests/core/test_entities.py b/tests/core/test_entities.py index 0702ceaf3b..b15653b055 100644 --- a/tests/core/test_entities.py +++ b/tests/core/test_entities.py @@ -1,14 +1,10 @@ -# -*- coding: utf-8 -*- - from copy import deepcopy -from openfisca_core.simulation_builder import SimulationBuilder -from openfisca_core.tools import assert_near -from openfisca_core.tools.test_runner import yaml -from openfisca_country_template.entities import Household -from openfisca_country_template.situation_examples import single, couple +from openfisca_country_template import entities, situation_examples -from .test_countries import tax_benefit_system +from openfisca_core import tools +from openfisca_core.simulations import SimulationBuilder +from openfisca_core.tools import test_runner TEST_CASE = { 'persons': {'ind0': {}, 'ind1': {}, 'ind2': {}, 'ind3': {}, 'ind4': {}, 'ind5': {}}, @@ -23,31 +19,31 @@ for (individu, age) in zip(TEST_CASE_AGES['persons'].values(), AGES): individu['age'] = age -FIRST_PARENT = Household.FIRST_PARENT -SECOND_PARENT = Household.SECOND_PARENT -PARENT = Household.PARENT -CHILD = Household.CHILD +FIRST_PARENT = entities.Household.FIRST_PARENT +SECOND_PARENT = entities.Household.SECOND_PARENT +PARENT = entities.Household.PARENT +CHILD = entities.Household.CHILD YEAR = 2016 MONTH = "2016-01" -def new_simulation(test_case, period = MONTH): - builder = SimulationBuilder() - builder.set_default_period(period) - return builder.build_from_entities(tax_benefit_system, test_case) +def new_simulation(tax_benefit_system, test_case, period = MONTH): + simulation_builder = SimulationBuilder() + simulation_builder.set_default_period(period) + return simulation_builder.build_from_entities(tax_benefit_system, test_case) -def test_role_index_and_positions(): - simulation = new_simulation(TEST_CASE) - assert_near(simulation.household.members_entity_id, [0, 0, 0, 0, 1, 1]) +def test_role_index_and_positions(tax_benefit_system): + simulation = new_simulation(tax_benefit_system, TEST_CASE) + tools.assert_near(simulation.household.members_entity_id, [0, 0, 0, 0, 1, 1]) assert((simulation.household.members_role == [FIRST_PARENT, SECOND_PARENT, CHILD, CHILD, FIRST_PARENT, CHILD]).all()) - assert_near(simulation.household.members_position, [0, 1, 2, 3, 0, 1]) + tools.assert_near(simulation.household.members_position, [0, 1, 2, 3, 0, 1]) assert(simulation.person.ids == ["ind0", "ind1", "ind2", "ind3", "ind4", "ind5"]) assert(simulation.household.ids == ['h1', 'h2']) -def test_entity_structure_with_constructor(): +def test_entity_structure_with_constructor(tax_benefit_system): simulation_yaml = """ persons: bill: {} @@ -68,16 +64,16 @@ def test_entity_structure_with_constructor(): - claudia """ - simulation = SimulationBuilder().build_from_dict(tax_benefit_system, yaml.safe_load(simulation_yaml)) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, test_runner.yaml.safe_load(simulation_yaml)) household = simulation.household - assert_near(household.members_entity_id, [0, 0, 1, 0, 0]) + tools.assert_near(household.members_entity_id, [0, 0, 1, 0, 0]) assert((household.members_role == [FIRST_PARENT, SECOND_PARENT, FIRST_PARENT, CHILD, CHILD]).all()) - assert_near(household.members_position, [0, 1, 0, 2, 3]) + tools.assert_near(household.members_position, [0, 1, 0, 2, 3]) -def test_entity_variables_with_constructor(): +def test_entity_variables_with_constructor(tax_benefit_system): simulation_yaml = """ persons: bill: {} @@ -102,12 +98,12 @@ def test_entity_variables_with_constructor(): 2017-06: 600 """ - simulation = SimulationBuilder().build_from_dict(tax_benefit_system, yaml.safe_load(simulation_yaml)) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, test_runner.yaml.safe_load(simulation_yaml)) household = simulation.household - assert_near(household('rent', "2017-06"), [800, 600]) + tools.assert_near(household('rent', "2017-06"), [800, 600]) -def test_person_variable_with_constructor(): +def test_person_variable_with_constructor(tax_benefit_system): simulation_yaml = """ persons: bill: @@ -135,13 +131,13 @@ def test_person_variable_with_constructor(): - claudia """ - simulation = SimulationBuilder().build_from_dict(tax_benefit_system, yaml.safe_load(simulation_yaml)) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, test_runner.yaml.safe_load(simulation_yaml)) person = simulation.person - assert_near(person('salary', "2017-11"), [1500, 0, 3000, 0, 0]) - assert_near(person('salary', "2017-12"), [2000, 0, 4000, 0, 0]) + tools.assert_near(person('salary', "2017-11"), [1500, 0, 3000, 0, 0]) + tools.assert_near(person('salary', "2017-12"), [2000, 0, 4000, 0, 0]) -def test_set_input_with_constructor(): +def test_set_input_with_constructor(tax_benefit_system): simulation_yaml = """ persons: bill: @@ -174,202 +170,202 @@ def test_set_input_with_constructor(): - claudia """ - simulation = SimulationBuilder().build_from_dict(tax_benefit_system, yaml.safe_load(simulation_yaml)) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, test_runner.yaml.safe_load(simulation_yaml)) person = simulation.person - assert_near(person('salary', "2017-12"), [2000, 0, 4000, 0, 0]) - assert_near(person('salary', "2017-10"), [2000, 3000, 1600, 0, 0]) + tools.assert_near(person('salary', "2017-12"), [2000, 0, 4000, 0, 0]) + tools.assert_near(person('salary', "2017-10"), [2000, 3000, 1600, 0, 0]) -def test_has_role(): - simulation = new_simulation(TEST_CASE) +def test_has_role(tax_benefit_system): + simulation = new_simulation(tax_benefit_system, TEST_CASE) individu = simulation.persons - assert_near(individu.has_role(CHILD), [False, False, True, True, False, True]) + tools.assert_near(individu.has_role(CHILD), [False, False, True, True, False, True]) -def test_has_role_with_subrole(): - simulation = new_simulation(TEST_CASE) +def test_has_role_with_subrole(tax_benefit_system): + simulation = new_simulation(tax_benefit_system, TEST_CASE) individu = simulation.persons - assert_near(individu.has_role(PARENT), [True, True, False, False, True, False]) - assert_near(individu.has_role(FIRST_PARENT), [True, False, False, False, True, False]) - assert_near(individu.has_role(SECOND_PARENT), [False, True, False, False, False, False]) + tools.assert_near(individu.has_role(PARENT), [True, True, False, False, True, False]) + tools.assert_near(individu.has_role(FIRST_PARENT), [True, False, False, False, True, False]) + tools.assert_near(individu.has_role(SECOND_PARENT), [False, True, False, False, False, False]) -def test_project(): +def test_project(tax_benefit_system): test_case = deepcopy(TEST_CASE) test_case['households']['h1']['housing_tax'] = 20000 - simulation = new_simulation(test_case, YEAR) + simulation = new_simulation(tax_benefit_system, test_case, YEAR) household = simulation.household housing_tax = household('housing_tax', YEAR) projected_housing_tax = household.project(housing_tax) - assert_near(projected_housing_tax, [20000, 20000, 20000, 20000, 0, 0]) + tools.assert_near(projected_housing_tax, [20000, 20000, 20000, 20000, 0, 0]) housing_tax_projected_on_parents = household.project(housing_tax, role = PARENT) - assert_near(housing_tax_projected_on_parents, [20000, 20000, 0, 0, 0, 0]) + tools.assert_near(housing_tax_projected_on_parents, [20000, 20000, 0, 0, 0, 0]) -def test_implicit_projection(): +def test_implicit_projection(tax_benefit_system): test_case = deepcopy(TEST_CASE) test_case['households']['h1']['housing_tax'] = 20000 - simulation = new_simulation(test_case, YEAR) + simulation = new_simulation(tax_benefit_system, test_case, YEAR) individu = simulation.person housing_tax = individu.household('housing_tax', YEAR) - assert_near(housing_tax, [20000, 20000, 20000, 20000, 0, 0]) + tools.assert_near(housing_tax, [20000, 20000, 20000, 20000, 0, 0]) -def test_sum(): +def test_sum(tax_benefit_system): test_case = deepcopy(TEST_CASE) test_case['persons']['ind0']['salary'] = 1000 test_case['persons']['ind1']['salary'] = 1500 test_case['persons']['ind4']['salary'] = 3000 test_case['persons']['ind5']['salary'] = 500 - simulation = new_simulation(test_case, MONTH) + simulation = new_simulation(tax_benefit_system, test_case, MONTH) household = simulation.household salary = household.members('salary', "2016-01") total_salary_by_household = household.sum(salary) - assert_near(total_salary_by_household, [2500, 3500]) + tools.assert_near(total_salary_by_household, [2500, 3500]) total_salary_parents_by_household = household.sum(salary, role = PARENT) - assert_near(total_salary_parents_by_household, [2500, 3000]) + tools.assert_near(total_salary_parents_by_household, [2500, 3000]) -def test_any(): +def test_any(tax_benefit_system): test_case = deepcopy(TEST_CASE_AGES) - simulation = new_simulation(test_case) + simulation = new_simulation(tax_benefit_system, test_case) household = simulation.household age = household.members('age', period = MONTH) condition_age = (age <= 18) has_household_member_with_age_inf_18 = household.any(condition_age) - assert_near(has_household_member_with_age_inf_18, [True, False]) + tools.assert_near(has_household_member_with_age_inf_18, [True, False]) condition_age_2 = (age > 18) has_household_CHILD_with_age_sup_18 = household.any(condition_age_2, role = CHILD) - assert_near(has_household_CHILD_with_age_sup_18, [False, True]) + tools.assert_near(has_household_CHILD_with_age_sup_18, [False, True]) -def test_all(): +def test_all(tax_benefit_system): test_case = deepcopy(TEST_CASE_AGES) - simulation = new_simulation(test_case) + simulation = new_simulation(tax_benefit_system, test_case) household = simulation.household age = household.members('age', period = MONTH) condition_age = (age >= 18) all_persons_age_sup_18 = household.all(condition_age) - assert_near(all_persons_age_sup_18, [False, True]) + tools.assert_near(all_persons_age_sup_18, [False, True]) all_parents_age_sup_18 = household.all(condition_age, role = PARENT) - assert_near(all_parents_age_sup_18, [True, True]) + tools.assert_near(all_parents_age_sup_18, [True, True]) -def test_max(): +def test_max(tax_benefit_system): test_case = deepcopy(TEST_CASE_AGES) - simulation = new_simulation(test_case) + simulation = new_simulation(tax_benefit_system, test_case) household = simulation.household age = household.members('age', period = MONTH) age_max = household.max(age) - assert_near(age_max, [40, 54]) + tools.assert_near(age_max, [40, 54]) age_max_child = household.max(age, role = CHILD) - assert_near(age_max_child, [9, 20]) + tools.assert_near(age_max_child, [9, 20]) -def test_min(): +def test_min(tax_benefit_system): test_case = deepcopy(TEST_CASE_AGES) - simulation = new_simulation(test_case) + simulation = new_simulation(tax_benefit_system, test_case) household = simulation.household age = household.members('age', period = MONTH) age_min = household.min(age) - assert_near(age_min, [7, 20]) + tools.assert_near(age_min, [7, 20]) age_min_parents = household.min(age, role = PARENT) - assert_near(age_min_parents, [37, 54]) + tools.assert_near(age_min_parents, [37, 54]) -def test_value_nth_person(): +def test_value_nth_person(tax_benefit_system): test_case = deepcopy(TEST_CASE_AGES) - simulation = new_simulation(test_case) + simulation = new_simulation(tax_benefit_system, test_case) household = simulation.household array = household.members('age', MONTH) result0 = household.value_nth_person(0, array, default=-1) - assert_near(result0, [40, 54]) + tools.assert_near(result0, [40, 54]) result1 = household.value_nth_person(1, array, default=-1) - assert_near(result1, [37, 20]) + tools.assert_near(result1, [37, 20]) result2 = household.value_nth_person(2, array, default=-1) - assert_near(result2, [7, -1]) + tools.assert_near(result2, [7, -1]) result3 = household.value_nth_person(3, array, default=-1) - assert_near(result3, [9, -1]) + tools.assert_near(result3, [9, -1]) -def test_rank(): +def test_rank(tax_benefit_system): test_case = deepcopy(TEST_CASE_AGES) - simulation = new_simulation(test_case) + simulation = new_simulation(tax_benefit_system, test_case) person = simulation.person age = person('age', MONTH) # [40, 37, 7, 9, 54, 20] rank = person.get_rank(person.household, age) - assert_near(rank, [3, 2, 0, 1, 1, 0]) + tools.assert_near(rank, [3, 2, 0, 1, 1, 0]) - rank_in_siblings = person.get_rank(person.household, - age, condition = person.has_role(Household.CHILD)) - assert_near(rank_in_siblings, [-1, -1, 1, 0, -1, 0]) + rank_in_siblings = person.get_rank(person.household, - age, condition = person.has_role(entities.Household.CHILD)) + tools.assert_near(rank_in_siblings, [-1, -1, 1, 0, -1, 0]) -def test_partner(): +def test_partner(tax_benefit_system): test_case = deepcopy(TEST_CASE) test_case['persons']['ind0']['salary'] = 1000 test_case['persons']['ind1']['salary'] = 1500 test_case['persons']['ind4']['salary'] = 3000 test_case['persons']['ind5']['salary'] = 500 - simulation = new_simulation(test_case) + simulation = new_simulation(tax_benefit_system, test_case) persons = simulation.persons salary = persons('salary', period = MONTH) salary_second_parent = persons.value_from_partner(salary, persons.household, PARENT) - assert_near(salary_second_parent, [1500, 1000, 0, 0, 0, 0]) + tools.assert_near(salary_second_parent, [1500, 1000, 0, 0, 0, 0]) -def test_value_from_first_person(): +def test_value_from_first_person(tax_benefit_system): test_case = deepcopy(TEST_CASE) test_case['persons']['ind0']['salary'] = 1000 test_case['persons']['ind1']['salary'] = 1500 test_case['persons']['ind4']['salary'] = 3000 test_case['persons']['ind5']['salary'] = 500 - simulation = new_simulation(test_case) + simulation = new_simulation(tax_benefit_system, test_case) household = simulation.household salaries = household.members('salary', period = MONTH) salary_first_person = household.value_from_first_person(salaries) - assert_near(salary_first_person, [1000, 3000]) + tools.assert_near(salary_first_person, [1000, 3000]) -def test_projectors_methods(): - simulation = SimulationBuilder().build_from_dict(tax_benefit_system, couple) +def test_projectors_methods(tax_benefit_system): + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, situation_examples.couple) household = simulation.household person = simulation.person - projected_vector = household.first_parent.has_role(Household.FIRST_PARENT) + projected_vector = household.first_parent.has_role(entities.Household.FIRST_PARENT) assert(len(projected_vector) == 1) # Must be of a household dimension salary_i = person.household.members('salary', '2017-01') @@ -381,7 +377,7 @@ def test_projectors_methods(): assert(len(household.first_parent.get_rank(household, salary_i)) == 1) # Must be of a person dimension -def test_sum_following_bug_ipp_1(): +def test_sum_following_bug_ipp_1(tax_benefit_system): test_case = { 'persons': {'ind0': {}, 'ind1': {}, 'ind2': {}, 'ind3': {}}, 'households': { @@ -394,16 +390,16 @@ def test_sum_following_bug_ipp_1(): test_case['persons']['ind2']['salary'] = 1000 test_case['persons']['ind3']['salary'] = 1000 - simulation = new_simulation(test_case) + simulation = new_simulation(tax_benefit_system, test_case) household = simulation.household eligible_i = household.members('salary', period = MONTH) < 1500 nb_eligibles_by_household = household.sum(eligible_i, role = CHILD) - assert_near(nb_eligibles_by_household, [0, 2]) + tools.assert_near(nb_eligibles_by_household, [0, 2]) -def test_sum_following_bug_ipp_2(): +def test_sum_following_bug_ipp_2(tax_benefit_system): test_case = { 'persons': {'ind0': {}, 'ind1': {}, 'ind2': {}, 'ind3': {}}, 'households': { @@ -416,17 +412,17 @@ def test_sum_following_bug_ipp_2(): test_case['persons']['ind2']['salary'] = 1000 test_case['persons']['ind3']['salary'] = 1000 - simulation = new_simulation(test_case) + simulation = new_simulation(tax_benefit_system, test_case) household = simulation.household eligible_i = household.members('salary', period = MONTH) < 1500 nb_eligibles_by_household = household.sum(eligible_i, role = CHILD) - assert_near(nb_eligibles_by_household, [2, 0]) + tools.assert_near(nb_eligibles_by_household, [2, 0]) -def test_get_memory_usage(): - test_case = deepcopy(single) +def test_get_memory_usage(tax_benefit_system): + test_case = deepcopy(situation_examples.single) test_case["persons"]["Alicia"]["salary"] = {"2017-01": 0} simulation = SimulationBuilder().build_from_dict(tax_benefit_system, test_case) simulation.calculate('disposable_income', '2017-01') @@ -435,7 +431,7 @@ def test_get_memory_usage(): assert(len(memory_usage['by_variable']) == 1) -def test_unordered_persons(): +def test_unordered_persons(tax_benefit_system): test_case = { 'persons': {'ind4': {}, 'ind3': {}, 'ind1': {}, 'ind2': {}, 'ind5': {}, 'ind0': {}}, 'households': { @@ -456,7 +452,7 @@ def test_unordered_persons(): # household.members_entity_id == [1, 0, 0, 0, 1, 0] - simulation = new_simulation(test_case, MONTH) + simulation = new_simulation(tax_benefit_system, test_case, MONTH) household = simulation.household person = simulation.person @@ -465,35 +461,35 @@ def test_unordered_persons(): # Aggregation/Projection persons -> entity - assert_near(household.sum(salary), [2520, 3500]) - assert_near(household.max(salary), [1500, 3000]) - assert_near(household.min(salary), [0, 500]) - assert_near(household.all(salary > 0), [False, True]) - assert_near(household.any(salary > 2000), [False, True]) - assert_near(household.first_person('salary', "2016-01"), [0, 3000]) - assert_near(household.first_parent('salary', "2016-01"), [1000, 3000]) - assert_near(household.second_parent('salary', "2016-01"), [1500, 0]) - assert_near(person.value_from_partner(salary, person.household, PARENT), [0, 0, 1000, 0, 0, 1500]) - - assert_near(household.sum(salary, role = PARENT), [2500, 3000]) - assert_near(household.sum(salary, role = CHILD), [20, 500]) - assert_near(household.max(salary, role = PARENT), [1500, 3000]) - assert_near(household.max(salary, role = CHILD), [20, 500]) - assert_near(household.min(salary, role = PARENT), [1000, 3000]) - assert_near(household.min(salary, role = CHILD), [0, 500]) - assert_near(household.all(salary > 0, role = PARENT), [True, True]) - assert_near(household.all(salary > 0, role = CHILD), [False, True]) - assert_near(household.any(salary < 1500, role = PARENT), [True, False]) - assert_near(household.any(salary > 200, role = CHILD), [False, True]) + tools.assert_near(household.sum(salary), [2520, 3500]) + tools.assert_near(household.max(salary), [1500, 3000]) + tools.assert_near(household.min(salary), [0, 500]) + tools.assert_near(household.all(salary > 0), [False, True]) + tools.assert_near(household.any(salary > 2000), [False, True]) + tools.assert_near(household.first_person('salary', "2016-01"), [0, 3000]) + tools.assert_near(household.first_parent('salary', "2016-01"), [1000, 3000]) + tools.assert_near(household.second_parent('salary', "2016-01"), [1500, 0]) + tools.assert_near(person.value_from_partner(salary, person.household, PARENT), [0, 0, 1000, 0, 0, 1500]) + + tools.assert_near(household.sum(salary, role = PARENT), [2500, 3000]) + tools.assert_near(household.sum(salary, role = CHILD), [20, 500]) + tools.assert_near(household.max(salary, role = PARENT), [1500, 3000]) + tools.assert_near(household.max(salary, role = CHILD), [20, 500]) + tools.assert_near(household.min(salary, role = PARENT), [1000, 3000]) + tools.assert_near(household.min(salary, role = CHILD), [0, 500]) + tools.assert_near(household.all(salary > 0, role = PARENT), [True, True]) + tools.assert_near(household.all(salary > 0, role = CHILD), [False, True]) + tools.assert_near(household.any(salary < 1500, role = PARENT), [True, False]) + tools.assert_near(household.any(salary > 200, role = CHILD), [False, True]) # nb_persons - assert_near(household.nb_persons(), [4, 2]) - assert_near(household.nb_persons(role = PARENT), [2, 1]) - assert_near(household.nb_persons(role = CHILD), [2, 1]) + tools.assert_near(household.nb_persons(), [4, 2]) + tools.assert_near(household.nb_persons(role = PARENT), [2, 1]) + tools.assert_near(household.nb_persons(role = CHILD), [2, 1]) # Projection entity -> persons - assert_near(household.project(accommodation_size), [60, 160, 160, 160, 60, 160]) - assert_near(household.project(accommodation_size, role = PARENT), [60, 0, 160, 0, 0, 160]) - assert_near(household.project(accommodation_size, role = CHILD), [0, 160, 0, 160, 60, 0]) + tools.assert_near(household.project(accommodation_size), [60, 160, 160, 160, 60, 160]) + tools.assert_near(household.project(accommodation_size, role = PARENT), [60, 0, 160, 0, 0, 160]) + tools.assert_near(household.project(accommodation_size, role = CHILD), [0, 160, 0, 160, 60, 0]) diff --git a/tests/core/test_extensions.py b/tests/core/test_extensions.py index 864adf606e..5c3da81d66 100644 --- a/tests/core/test_extensions.py +++ b/tests/core/test_extensions.py @@ -1,29 +1,24 @@ import pytest -from openfisca_country_template import CountryTaxBenefitSystem - -original_tbs = CountryTaxBenefitSystem() - - -def test_load_extension(): - tbs = original_tbs.clone() +def test_load_extension(tax_benefit_system): + tbs = tax_benefit_system.clone() assert tbs.get_variable('local_town_child_allowance') is None tbs.load_extension('openfisca_extension_template') assert tbs.get_variable('local_town_child_allowance') is not None - assert original_tbs.get_variable('local_town_child_allowance') is None + assert tax_benefit_system.get_variable('local_town_child_allowance') is None -def test_access_to_parameters(): - tbs = original_tbs.clone() +def test_access_to_parameters(tax_benefit_system): + tbs = tax_benefit_system.clone() tbs.load_extension('openfisca_extension_template') assert tbs.parameters('2016-01').local_town.child_allowance.amount == 100.0 assert tbs.parameters.local_town.child_allowance.amount('2016-01') == 100.0 -def test_failure_to_load_extension_when_directory_doesnt_exist(): +def test_failure_to_load_extension_when_directory_doesnt_exist(tax_benefit_system): with pytest.raises(ValueError): - original_tbs.load_extension('/this/is/not/a/real/path') + tax_benefit_system.load_extension('/this/is/not/a/real/path') diff --git a/tests/core/test_formulas.py b/tests/core/test_formulas.py index 19dd6bbf4e..876ca239d1 100644 --- a/tests/core/test_formulas.py +++ b/tests/core/test_formulas.py @@ -1,29 +1,25 @@ -# -*- coding: utf-8 -*- +import numpy +from openfisca_country_template import entities -import numpy as np - -from openfisca_core.periods import MONTH -from openfisca_core.simulation_builder import SimulationBuilder +from openfisca_core import commons, periods +from openfisca_core.simulations import SimulationBuilder from openfisca_core.variables import Variable -from openfisca_core.formula_helpers import switch -from openfisca_country_template import CountryTaxBenefitSystem -from openfisca_country_template.entities import Person from pytest import fixture, approx class choice(Variable): value_type = int - entity = Person - definition_period = MONTH + entity = entities.Person + definition_period = periods.MONTH class uses_multiplication(Variable): value_type = int - entity = Person + entity = entities.Person label = 'Variable with formula that uses multiplication' - definition_period = MONTH + definition_period = periods.MONTH def formula(person, period): choice = person('choice', period) @@ -33,9 +29,9 @@ def formula(person, period): class returns_scalar(Variable): value_type = int - entity = Person + entity = entities.Person label = 'Variable with formula that returns a scalar value' - definition_period = MONTH + definition_period = periods.MONTH def formula(person, period): return 666 @@ -43,13 +39,13 @@ def formula(person, period): class uses_switch(Variable): value_type = int - entity = Person + entity = entities.Person label = 'Variable with formula that uses switch' - definition_period = MONTH + definition_period = periods.MONTH def formula(person, period): choice = person('choice', period) - result = switch( + result = commons.switch( choice, { 1: 80, @@ -59,9 +55,9 @@ def formula(person, period): return result -# TaxBenefitSystem instance declared after formulas -our_tbs = CountryTaxBenefitSystem() -our_tbs.add_variables(choice, uses_multiplication, uses_switch, returns_scalar) +@fixture(scope = "module", autouse = True) +def add_variables_to_tax_benefit_system(tax_benefit_system): + tax_benefit_system.add_variables(choice, uses_multiplication, uses_switch, returns_scalar) @fixture @@ -70,31 +66,31 @@ def month(): @fixture -def simulation(month): - builder = SimulationBuilder() - builder.default_period = month - simulation = builder.build_from_variables(our_tbs, {'choice': np.random.randint(2, size = 1000) + 1}) +def simulation(tax_benefit_system, month): + simulation_builder = SimulationBuilder() + simulation_builder.default_period = month + simulation = simulation_builder.build_from_variables(tax_benefit_system, {'choice': numpy.random.randint(2, size = 1000) + 1}) simulation.debug = True return simulation def test_switch(simulation, month): uses_switch = simulation.calculate('uses_switch', period = month) - assert isinstance(uses_switch, np.ndarray) + assert isinstance(uses_switch, numpy.ndarray) def test_multiplication(simulation, month): uses_multiplication = simulation.calculate('uses_multiplication', period = month) - assert isinstance(uses_multiplication, np.ndarray) + assert isinstance(uses_multiplication, numpy.ndarray) def test_broadcast_scalar(simulation, month): array_value = simulation.calculate('returns_scalar', period = month) - assert isinstance(array_value, np.ndarray) - assert array_value == approx(np.repeat(666, 1000)) + assert isinstance(array_value, numpy.ndarray) + assert array_value == approx(numpy.repeat(666, 1000)) def test_compare_multiplication_and_switch(simulation, month): uses_multiplication = simulation.calculate('uses_multiplication', period = month) uses_switch = simulation.calculate('uses_switch', period = month) - assert np.all(uses_switch == uses_multiplication) + assert numpy.all(uses_switch == uses_multiplication) diff --git a/tests/core/test_holders.py b/tests/core/test_holders.py index 9e62d6e64b..cd26231037 100644 --- a/tests/core/test_holders.py +++ b/tests/core/test_holders.py @@ -1,56 +1,56 @@ -# -*- coding: utf-8 -*- - -import numpy as np import pytest -import openfisca_country_template.situation_examples -from openfisca_core.simulation_builder import SimulationBuilder -from openfisca_country_template.variables.housing import HousingOccupancyStatus -from openfisca_core.periods import period as make_period, ETERNITY -from openfisca_core.tools import assert_near -from openfisca_core.memory_config import MemoryConfig -from openfisca_core.holders import Holder, set_input_dispatch_by_period -from openfisca_core.errors import PeriodMismatchError -from .test_countries import tax_benefit_system +import numpy -from pytest import fixture +from openfisca_country_template import situation_examples +from openfisca_country_template.variables import housing + +from openfisca_core import holders, periods, tools +from openfisca_core.errors import PeriodMismatchError +from openfisca_core.memory_config import MemoryConfig +from openfisca_core.simulations import SimulationBuilder +from openfisca_core.holders import Holder -@fixture -def single(): - return SimulationBuilder().build_from_entities(tax_benefit_system, openfisca_country_template.situation_examples.single) +@pytest.fixture +def single(tax_benefit_system): + return \ + SimulationBuilder() \ + .build_from_entities(tax_benefit_system, situation_examples.single) -@fixture -def couple(): - return SimulationBuilder().build_from_entities(tax_benefit_system, openfisca_country_template.situation_examples.couple) +@pytest.fixture +def couple(tax_benefit_system): + return \ + SimulationBuilder(). \ + build_from_entities(tax_benefit_system, situation_examples.couple) -period = make_period('2017-12') +period = periods.period('2017-12') def test_set_input_enum_string(couple): simulation = couple - status_occupancy = np.asarray(['free_lodger']) + status_occupancy = numpy.asarray(['free_lodger']) simulation.household.get_holder('housing_occupancy_status').set_input(period, status_occupancy) result = simulation.calculate('housing_occupancy_status', period) - assert result == HousingOccupancyStatus.free_lodger + assert result == housing.HousingOccupancyStatus.free_lodger def test_set_input_enum_int(couple): simulation = couple - status_occupancy = np.asarray([2], dtype = np.int16) + status_occupancy = numpy.asarray([2], dtype = numpy.int16) simulation.household.get_holder('housing_occupancy_status').set_input(period, status_occupancy) result = simulation.calculate('housing_occupancy_status', period) - assert result == HousingOccupancyStatus.free_lodger + assert result == housing.HousingOccupancyStatus.free_lodger def test_set_input_enum_item(couple): simulation = couple - status_occupancy = np.asarray([HousingOccupancyStatus.free_lodger]) + status_occupancy = numpy.asarray([housing.HousingOccupancyStatus.free_lodger]) simulation.household.get_holder('housing_occupancy_status').set_input(period, status_occupancy) result = simulation.calculate('housing_occupancy_status', period) - assert result == HousingOccupancyStatus.free_lodger + assert result == housing.HousingOccupancyStatus.free_lodger def test_yearly_input_month_variable(couple): @@ -73,7 +73,7 @@ def test_month_input_year_variable(couple): def test_enum_dtype(couple): simulation = couple - status_occupancy = np.asarray([2], dtype = np.int16) + status_occupancy = numpy.asarray([2], dtype = numpy.int16) simulation.household.get_holder('housing_occupancy_status').set_input(period, status_occupancy) result = simulation.calculate('housing_occupancy_status', period) assert result.dtype.kind is not None @@ -88,22 +88,22 @@ def test_permanent_variable_empty(single): def test_permanent_variable_filled(single): simulation = single holder = simulation.person.get_holder('birth') - value = np.asarray(['1980-01-01'], dtype = holder.variable.dtype) - holder.set_input(make_period(ETERNITY), value) + value = numpy.asarray(['1980-01-01'], dtype = holder.variable.dtype) + holder.set_input(periods.period(periods.ETERNITY), value) assert holder.get_array(None) == value - assert holder.get_array(ETERNITY) == value + assert holder.get_array(periods.ETERNITY) == value assert holder.get_array('2016-01') == value def test_delete_arrays(single): simulation = single salary_holder = simulation.person.get_holder('salary') - salary_holder.set_input(make_period(2017), np.asarray([30000])) - salary_holder.set_input(make_period(2018), np.asarray([60000])) + salary_holder.set_input(periods.period(2017), numpy.asarray([30000])) + salary_holder.set_input(periods.period(2018), numpy.asarray([60000])) assert simulation.person('salary', '2017-01') == 2500 assert simulation.person('salary', '2018-01') == 5000 salary_holder.delete_arrays(period = 2018) - salary_holder.set_input(make_period(2018), np.asarray([15000])) + salary_holder.set_input(periods.period(2018), numpy.asarray([15000])) assert simulation.person('salary', '2017-01') == 2500 assert simulation.person('salary', '2018-01') == 1250 @@ -113,7 +113,7 @@ def test_get_memory_usage(single): salary_holder = simulation.person.get_holder('salary') memory_usage = salary_holder.get_memory_usage() assert memory_usage['total_nb_bytes'] == 0 - salary_holder.set_input(make_period(2017), np.asarray([30000])) + salary_holder.set_input(periods.period(2017), numpy.asarray([30000])) memory_usage = salary_holder.get_memory_usage() assert memory_usage['nb_cells_by_array'] == 1 assert memory_usage['cell_size'] == 4 # float 32 @@ -126,7 +126,7 @@ def test_get_memory_usage_with_trace(single): simulation = single simulation.trace = True salary_holder = simulation.person.get_holder('salary') - salary_holder.set_input(make_period(2017), np.asarray([30000])) + salary_holder.set_input(periods.period(2017), numpy.asarray([30000])) simulation.calculate('salary', '2017-01') simulation.calculate('salary', '2017-01') simulation.calculate('salary', '2017-02') @@ -141,7 +141,7 @@ def test_set_input_dispatch_by_period(single): variable = simulation.tax_benefit_system.get_variable('housing_occupancy_status') entity = simulation.household holder = Holder(variable, entity) - set_input_dispatch_by_period(holder, make_period(2019), 'owner') + holders.set_input_dispatch_by_period(holder, periods.period(2019), 'owner') assert holder.get_array('2019-01') == holder.get_array('2019-12') # Check the feature assert holder.get_array('2019-01') is holder.get_array('2019-12') # Check that the vectors are the same in memory, to avoid duplication @@ -153,12 +153,12 @@ def test_delete_arrays_on_disk(single): simulation = single simulation.memory_config = force_storage_on_disk salary_holder = simulation.person.get_holder('salary') - salary_holder.set_input(make_period(2017), np.asarray([30000])) - salary_holder.set_input(make_period(2018), np.asarray([60000])) + salary_holder.set_input(periods.period(2017), numpy.asarray([30000])) + salary_holder.set_input(periods.period(2018), numpy.asarray([60000])) assert simulation.person('salary', '2017-01') == 2500 assert simulation.person('salary', '2018-01') == 5000 salary_holder.delete_arrays(period = 2018) - salary_holder.set_input(make_period(2018), np.asarray([15000])) + salary_holder.set_input(periods.period(2018), numpy.asarray([15000])) assert simulation.person('salary', '2017-01') == 2500 assert simulation.person('salary', '2018-01') == 1250 @@ -166,21 +166,21 @@ def test_delete_arrays_on_disk(single): def test_cache_disk(couple): simulation = couple simulation.memory_config = force_storage_on_disk - month = make_period('2017-01') + month = periods.period('2017-01') holder = simulation.person.get_holder('disposable_income') - data = np.asarray([2000, 3000]) + data = numpy.asarray([2000, 3000]) holder.put_in_cache(data, month) stored_data = holder.get_array(month) - assert_near(data, stored_data) + tools.assert_near(data, stored_data) def test_known_periods(couple): simulation = couple simulation.memory_config = force_storage_on_disk - month = make_period('2017-01') - month_2 = make_period('2017-02') + month = periods.period('2017-01') + month_2 = periods.period('2017-02') holder = simulation.person.get_holder('disposable_income') - data = np.asarray([2000, 3000]) + data = numpy.asarray([2000, 3000]) holder.put_in_cache(data, month) holder._memory_storage.put(data, month_2) @@ -190,10 +190,10 @@ def test_known_periods(couple): def test_cache_enum_on_disk(single): simulation = single simulation.memory_config = force_storage_on_disk - month = make_period('2017-01') + month = periods.period('2017-01') simulation.calculate('housing_occupancy_status', month) # First calculation housing_occupancy_status = simulation.calculate('housing_occupancy_status', month) # Read from cache - assert housing_occupancy_status == HousingOccupancyStatus.tenant + assert housing_occupancy_status == housing.HousingOccupancyStatus.tenant def test_set_not_cached_variable(single): @@ -201,14 +201,14 @@ def test_set_not_cached_variable(single): simulation = single simulation.memory_config = dont_cache_variable holder = simulation.person.get_holder('salary') - array = np.asarray([2000]) + array = numpy.asarray([2000]) holder.set_input('2015-01', array) assert simulation.calculate('salary', '2015-01') == array def test_set_input_float_to_int(single): simulation = single - age = np.asarray([50.6]) + age = numpy.asarray([50.6]) simulation.person.get_holder('age').set_input(period, age) result = simulation.calculate('age', period) - assert result == np.asarray([50]) + assert result == numpy.asarray([50]) diff --git a/tests/core/test_opt_out_cache.py b/tests/core/test_opt_out_cache.py index 1b76287264..b4eab3e5a5 100644 --- a/tests/core/test_opt_out_cache.py +++ b/tests/core/test_opt_out_cache.py @@ -1,26 +1,13 @@ -# -*- coding: utf-8 -*- +import pytest -from pytest import fixture - -from openfisca_core.simulation_builder import SimulationBuilder -from openfisca_country_template import CountryTaxBenefitSystem from openfisca_country_template.entities import Person -from openfisca_core.variables import Variable -from openfisca_core.periods import MONTH - -@fixture -def month(): - return '2016-05' +from openfisca_core import periods +from openfisca_core.periods import MONTH +from openfisca_core.variables import Variable -@fixture -def make_isolated_simulation(month): - def _make_simulation(tbs, data): - builder = SimulationBuilder() - builder.default_period = month - return builder.build_from_variables(tbs, data) - return _make_simulation +PERIOD = periods.period("2016-01") class input(Variable): @@ -50,43 +37,34 @@ def formula(person, period): return person('intermediate', period) -def get_filled_tbs(): - tax_benefit_system = CountryTaxBenefitSystem() +@pytest.fixture(scope = "module", autouse = True) +def add_variables_to_tax_benefit_system(tax_benefit_system): tax_benefit_system.add_variables(input, intermediate, output) - return tax_benefit_system - -# TaxBenefitSystem instance declared after formulas +@pytest.fixture(scope = "module", autouse = True) +def add_variables_to_cache_blakclist(tax_benefit_system): + tax_benefit_system.cache_blacklist = set(['intermediate']) -tax_benefit_system = get_filled_tbs() - - -tax_benefit_system.cache_blacklist = set(['intermediate']) - - -def test_without_cache_opt_out(make_isolated_simulation, month): - simulation = make_isolated_simulation(tax_benefit_system, {'input': 1}) - simulation.calculate('output', period = month) +@pytest.mark.parametrize("simulation", [({'input': 1}, PERIOD)], indirect = True) +def test_without_cache_opt_out(simulation): + simulation.calculate('output', period = PERIOD) intermediate_cache = simulation.persons.get_holder('intermediate') - assert(intermediate_cache.get_array(month) is not None) + assert(intermediate_cache.get_array(PERIOD) is not None) -def test_with_cache_opt_out(make_isolated_simulation, month): - simulation = make_isolated_simulation(tax_benefit_system, {'input': 1}) +@pytest.mark.parametrize("simulation", [({'input': 1}, PERIOD)], indirect = True) +def test_with_cache_opt_out(simulation): simulation.debug = True simulation.opt_out_cache = True - simulation.calculate('output', period = month) + simulation.calculate('output', period = PERIOD) intermediate_cache = simulation.persons.get_holder('intermediate') - assert(intermediate_cache.get_array(month) is None) - - -tax_benefit_system2 = get_filled_tbs() + assert(intermediate_cache.get_array(PERIOD) is None) -def test_with_no_blacklist(make_isolated_simulation, month): - simulation = make_isolated_simulation(tax_benefit_system2, {'input': 1}) - simulation.calculate('output', period = month) +@pytest.mark.parametrize("simulation", [({'input': 1}, PERIOD)], indirect = True) +def test_with_no_blacklist(simulation): + simulation.calculate('output', period = PERIOD) intermediate_cache = simulation.persons.get_holder('intermediate') - assert(intermediate_cache.get_array(month) is not None) + assert(intermediate_cache.get_array(PERIOD) is not None) diff --git a/tests/core/test_parameters.py b/tests/core/test_parameters.py index 88fedcabab..40d8bb3fc9 100644 --- a/tests/core/test_parameters.py +++ b/tests/core/test_parameters.py @@ -1,14 +1,11 @@ -# -*- coding: utf-8 -*- - import tempfile import pytest from openfisca_core.parameters import ParameterNotFound, ParameterNode, ParameterNodeAtInstant, load_parameter_file -from .test_countries import tax_benefit_system -def test_get_at_instant(): +def test_get_at_instant(tax_benefit_system): parameters = tax_benefit_system.parameters assert isinstance(parameters, ParameterNode), parameters parameters_at_instant = parameters('2016-01-01') @@ -17,7 +14,7 @@ def test_get_at_instant(): assert parameters_at_instant.benefits.basic_income == 600 -def test_param_values(): +def test_param_values(tax_benefit_system): dated_values = { '2015-01-01': 0.15, '2014-01-01': 0.14, @@ -29,37 +26,37 @@ def test_param_values(): assert tax_benefit_system.get_parameters_at_instant(date).taxes.income_tax_rate == value -def test_param_before_it_is_defined(): +def test_param_before_it_is_defined(tax_benefit_system): with pytest.raises(ParameterNotFound): tax_benefit_system.get_parameters_at_instant('1997-12-31').taxes.income_tax_rate # The placeholder should have no effect on the parameter computation -def test_param_with_placeholder(): +def test_param_with_placeholder(tax_benefit_system): assert tax_benefit_system.get_parameters_at_instant('2018-01-01').taxes.income_tax_rate == 0.15 -def test_stopped_parameter_before_end_value(): +def test_stopped_parameter_before_end_value(tax_benefit_system): assert tax_benefit_system.get_parameters_at_instant('2011-12-31').benefits.housing_allowance == 0.25 -def test_stopped_parameter_after_end_value(): +def test_stopped_parameter_after_end_value(tax_benefit_system): with pytest.raises(ParameterNotFound): tax_benefit_system.get_parameters_at_instant('2016-12-01').benefits.housing_allowance -def test_parameter_for_period(): +def test_parameter_for_period(tax_benefit_system): income_tax_rate = tax_benefit_system.parameters.taxes.income_tax_rate assert income_tax_rate("2015") == income_tax_rate("2015-01-01") -def test_wrong_value(): +def test_wrong_value(tax_benefit_system): income_tax_rate = tax_benefit_system.parameters.taxes.income_tax_rate with pytest.raises(ValueError): income_tax_rate("test") -def test_parameter_repr(): +def test_parameter_repr(tax_benefit_system): parameters = tax_benefit_system.parameters tf = tempfile.NamedTemporaryFile(delete = False) tf.write(repr(parameters).encode('utf-8')) @@ -68,7 +65,7 @@ def test_parameter_repr(): assert repr(parameters) == repr(tf_parameters) -def test_parameters_metadata(): +def test_parameters_metadata(tax_benefit_system): parameter = tax_benefit_system.parameters.benefits.basic_income assert parameter.metadata['reference'] == 'https://law.gov.example/basic-income/amount' assert parameter.metadata['unit'] == 'currency-EUR' @@ -79,7 +76,7 @@ def test_parameters_metadata(): assert scale.metadata['rate_unit'] == '/1' -def test_parameter_node_metadata(): +def test_parameter_node_metadata(tax_benefit_system): parameter = tax_benefit_system.parameters.benefits assert parameter.description == 'Social benefits' @@ -87,12 +84,12 @@ def test_parameter_node_metadata(): assert parameter_2.description == 'Housing tax' -def test_parameter_documentation(): +def test_parameter_documentation(tax_benefit_system): parameter = tax_benefit_system.parameters.benefits.housing_allowance assert parameter.documentation == 'A fraction of the rent.\nFrom the 1st of Dec 2016, the housing allowance no longer exists.\n' -def test_get_descendants(): +def test_get_descendants(tax_benefit_system): all_parameters = {parameter.name for parameter in tax_benefit_system.parameters.get_descendants()} assert all_parameters.issuperset({'taxes', 'taxes.housing_tax', 'taxes.housing_tax.minimal_amount'}) diff --git a/tests/core/test_reforms.py b/tests/core/test_reforms.py index c76739691d..8735cee18f 100644 --- a/tests/core/test_reforms.py +++ b/tests/core/test_reforms.py @@ -1,27 +1,13 @@ -# -*- coding: utf-8 -*- - import warnings -from pytest import fixture, raises +import pytest from openfisca_core import periods from openfisca_core.periods import Instant -from openfisca_core.simulation_builder import SimulationBuilder from openfisca_core.tools import assert_near from openfisca_core.parameters import ValuesHistory, ParameterNode from openfisca_country_template.entities import Household, Person from openfisca_core.model_api import * # noqa analysis:ignore -from openfisca_country_template import CountryTaxBenefitSystem -tax_benefit_system = CountryTaxBenefitSystem() - - -@fixture -def make_simulation(): - def _make_simulation(tbs, period, data): - builder = SimulationBuilder() - builder.default_period = period - return builder.build_from_variables(tbs, data) - return _make_simulation class goes_to_school(Variable): @@ -32,19 +18,21 @@ class goes_to_school(Variable): definition_period = MONTH -tax_benefit_system.add_variable(goes_to_school) - - class WithBasicIncomeNeutralized(Reform): def apply(self): self.neutralize_variable('basic_income') -def test_formula_neutralization(make_simulation): +@pytest.fixture(scope = "module", autouse = True) +def add_variables_to_tax_benefit_system(tax_benefit_system): + tax_benefit_system.add_variables(goes_to_school) + + +def test_formula_neutralization(make_simulation, tax_benefit_system): reform = WithBasicIncomeNeutralized(tax_benefit_system) period = '2017-01' - simulation = make_simulation(reform.base_tax_benefit_system, period, {}) + simulation = make_simulation(reform.base_tax_benefit_system, {}, period) simulation.debug = True basic_income = simulation.calculate('basic_income', period = period) @@ -52,7 +40,7 @@ def test_formula_neutralization(make_simulation): disposable_income = simulation.calculate('disposable_income', period = period) assert disposable_income > 0 - reform_simulation = make_simulation(reform, period, {}) + reform_simulation = make_simulation(reform, {}, period) reform_simulation.debug = True basic_income_reform = reform_simulation.calculate('basic_income', period = '2013-01') @@ -61,7 +49,7 @@ def test_formula_neutralization(make_simulation): assert_near(disposable_income_reform, 0) -def test_neutralization_variable_with_default_value(make_simulation): +def test_neutralization_variable_with_default_value(make_simulation, tax_benefit_system): class test_goes_to_school_neutralization(Reform): def apply(self): self.neutralize_variable('goes_to_school') @@ -69,17 +57,17 @@ def apply(self): reform = test_goes_to_school_neutralization(tax_benefit_system) period = "2017-01" - simulation = make_simulation(reform.base_tax_benefit_system, period, {}) + simulation = make_simulation(reform.base_tax_benefit_system, {}, period) goes_to_school = simulation.calculate('goes_to_school', period) assert_near(goes_to_school, [True], absolute_error_margin = 0) -def test_neutralization_optimization(make_simulation): +def test_neutralization_optimization(make_simulation, tax_benefit_system): reform = WithBasicIncomeNeutralized(tax_benefit_system) period = '2017-01' - simulation = make_simulation(reform, period, {}) + simulation = make_simulation(reform, {}, period) simulation.debug = True simulation.calculate('basic_income', period = '2013-01') @@ -90,7 +78,7 @@ def test_neutralization_optimization(make_simulation): assert basic_income_holder.get_known_periods() == [] -def test_input_variable_neutralization(make_simulation): +def test_input_variable_neutralization(make_simulation, tax_benefit_system): class test_salary_neutralization(Reform): def apply(self): @@ -103,7 +91,7 @@ def apply(self): reform = test_salary_neutralization(tax_benefit_system) with warnings.catch_warnings(record=True) as raised_warnings: - reform_simulation = make_simulation(reform, period, {'salary': [1200, 1000]}) + reform_simulation = make_simulation(reform, {'salary': [1200, 1000]}, period) assert 'You cannot set a value for the variable' in raised_warnings[0].message.args[0] salary = reform_simulation.calculate('salary', period) assert_near(salary, [0, 0],) @@ -111,7 +99,7 @@ def apply(self): assert_near(disposable_income_reform, [600, 600]) -def test_permanent_variable_neutralization(make_simulation): +def test_permanent_variable_neutralization(make_simulation, tax_benefit_system): class test_date_naissance_neutralization(Reform): def apply(self): @@ -120,9 +108,9 @@ def apply(self): reform = test_date_naissance_neutralization(tax_benefit_system) period = '2017-01' - simulation = make_simulation(reform.base_tax_benefit_system, period, {'birth': '1980-01-01'}) + simulation = make_simulation(reform.base_tax_benefit_system, {'birth': '1980-01-01'}, period) with warnings.catch_warnings(record=True) as raised_warnings: - reform_simulation = make_simulation(reform, period, {'birth': '1980-01-01'}) + reform_simulation = make_simulation(reform, {'birth': '1980-01-01'}, period) assert 'You cannot set a value for the variable' in raised_warnings[0].message.args[0] assert str(simulation.calculate('birth', None)[0]) == '1980-01-01' assert str(reform_simulation.calculate('birth', None)[0]) == '1970-01-01' @@ -223,7 +211,7 @@ def check_update_items(description, value_history, start_instant, stop_instant, ) -def test_add_variable(make_simulation): +def test_add_variable(make_simulation, tax_benefit_system): class new_variable(Variable): value_type = int label = "Nouvelle variable introduite par la réforme" @@ -241,13 +229,13 @@ def apply(self): reform = test_add_variable(tax_benefit_system) assert tax_benefit_system.get_variable('new_variable') is None - reform_simulation = make_simulation(reform, 2013, {}) + reform_simulation = make_simulation(reform, {}, 2013) reform_simulation.debug = True new_variable1 = reform_simulation.calculate('new_variable', period = '2013-01') assert_near(new_variable1, 10, absolute_error_margin = 0) -def test_add_dated_variable(make_simulation): +def test_add_dated_variable(make_simulation, tax_benefit_system): class new_dated_variable(Variable): value_type = int label = "Nouvelle variable introduite par la réforme" @@ -266,13 +254,13 @@ def apply(self): reform = test_add_variable(tax_benefit_system) - reform_simulation = make_simulation(reform, period, {}) + reform_simulation = make_simulation(reform, {}, '2013-01') reform_simulation.debug = True new_dated_variable1 = reform_simulation.calculate('new_dated_variable', period = '2013-01') assert_near(new_dated_variable1, 15, absolute_error_margin = 0) -def test_update_variable(make_simulation): +def test_update_variable(make_simulation, tax_benefit_system): class disposable_income(Variable): definition_period = MONTH @@ -294,7 +282,7 @@ def apply(self): assert disposable_income_reform.name == disposable_income_baseline.name assert disposable_income_reform.label == disposable_income_baseline.label - reform_simulation = make_simulation(reform, 2018, {}) + reform_simulation = make_simulation(reform, {}, 2018) disposable_income1 = reform_simulation.calculate('disposable_income', period = '2018-01') assert_near(disposable_income1, 10, absolute_error_margin = 0) @@ -303,7 +291,7 @@ def apply(self): assert(disposable_income2 > 100) -def test_replace_variable(): +def test_replace_variable(tax_benefit_system): class disposable_income(Variable): definition_period = MONTH @@ -324,16 +312,16 @@ def apply(self): assert disposable_income_reform.get_formula('2017') is None -def test_wrong_reform(): +def test_wrong_reform(tax_benefit_system): class wrong_reform(Reform): # A Reform must implement an `apply` method pass - with raises(Exception): + with pytest.raises(Exception): wrong_reform(tax_benefit_system) -def test_modify_parameters(): +def test_modify_parameters(tax_benefit_system): def modify_parameters(reference_parameters): reform_parameters_subtree = ParameterNode( @@ -361,7 +349,7 @@ def apply(self): assert parameters_at_instant.new_node.new_param is True -def test_attributes_conservation(): +def test_attributes_conservation(tax_benefit_system): class some_variable(Variable): value_type = int @@ -391,7 +379,7 @@ def apply(self): assert reform_variable.calculate_output == baseline_variable.calculate_output -def test_formulas_removal(): +def test_formulas_removal(tax_benefit_system): class reform(Reform): def apply(self): diff --git a/tests/core/test_simulation_builder.py b/tests/core/test_simulation_builder.py index 09e594cce1..b6a558751d 100644 --- a/tests/core/test_simulation_builder.py +++ b/tests/core/test_simulation_builder.py @@ -1,47 +1,24 @@ -# -*- coding: utf-8 -*- - +import datetime from typing import Iterable -from enum import Enum -from datetime import date +import pytest -from pytest import raises, fixture, approx +from openfisca_country_template import entities, situation_examples -from openfisca_core.simulation_builder import SimulationBuilder, Simulation -from openfisca_core.tools import assert_near -from openfisca_core.tools.test_runner import yaml -from openfisca_core.entities import Entity, GroupEntity +from openfisca_core import periods, tools +from openfisca_core.errors import SituationParsingError +from openfisca_core.indexed_enums import Enum from openfisca_core.populations import Population +from openfisca_core.simulations import Simulation, SimulationBuilder +from openfisca_core.tools import test_runner from openfisca_core.variables import Variable -from openfisca_country_template.entities import Household -from openfisca_country_template.situation_examples import couple -from openfisca_core.errors import SituationParsingError -from openfisca_core.periods import ETERNITY -from openfisca_core.indexed_enums import Enum as OFEnum - - -from .test_countries import tax_benefit_system - -class TestVariable(Variable): - definition_period = ETERNITY - value_type = float - def __init__(self, entity): - self.__class__.entity = entity - super().__init__() - - -@fixture -def simulation_builder(): - return SimulationBuilder() - - -@fixture +@pytest.fixture def int_variable(persons): class intvar(Variable): - definition_period = ETERNITY + definition_period = periods.ETERNITY value_type = int entity = persons @@ -51,12 +28,12 @@ def __init__(self): return intvar() -@fixture +@pytest.fixture def date_variable(persons): class datevar(Variable): - definition_period = ETERNITY - value_type = date + definition_period = periods.ETERNITY + value_type = datetime.date entity = persons def __init__(self): @@ -65,12 +42,12 @@ def __init__(self): return datevar() -@fixture +@pytest.fixture def enum_variable(): class TestEnum(Variable): - definition_period = ETERNITY - value_type = OFEnum + definition_period = periods.ETERNITY + value_type = Enum dtype = 'O' default_value = '0' is_neutralized = False @@ -84,100 +61,69 @@ def __init__(self): return TestEnum() -@fixture -def persons(): - class TestPersonEntity(Entity): - def get_variable(self, variable_name): - result = TestVariable(self) - result.name = variable_name - return result - - def check_variable_defined_for_entity(self, variable_name): - return True - - return TestPersonEntity("person", "persons", "", "") - - -@fixture -def group_entity(): - class Household(GroupEntity): - def get_variable(self, variable_name): - result = TestVariable(self) - result.name = variable_name - return result - - def check_variable_defined_for_entity(self, variable_name): - return True - - roles = [{ - 'key': 'parent', - 'plural': 'parents', - 'max': 2 - }, { - 'key': 'child', - 'plural': 'children' - }] - - return Household("household", "households", "", "", roles) - - -def test_build_default_simulation(simulation_builder): - one_person_simulation = simulation_builder.build_default_simulation(tax_benefit_system, 1) +def test_build_default_simulation(tax_benefit_system): + one_person_simulation = SimulationBuilder().build_default_simulation(tax_benefit_system, 1) assert one_person_simulation.persons.count == 1 assert one_person_simulation.household.count == 1 assert one_person_simulation.household.members_entity_id == [0] - assert one_person_simulation.household.members_role == Household.FIRST_PARENT + assert one_person_simulation.household.members_role == entities.Household.FIRST_PARENT - several_persons_simulation = simulation_builder.build_default_simulation(tax_benefit_system, 4) + several_persons_simulation = SimulationBuilder().build_default_simulation(tax_benefit_system, 4) assert several_persons_simulation.persons.count == 4 assert several_persons_simulation.household.count == 4 assert (several_persons_simulation.household.members_entity_id == [0, 1, 2, 3]).all() - assert (several_persons_simulation.household.members_role == Household.FIRST_PARENT).all() + assert (several_persons_simulation.household.members_role == entities.Household.FIRST_PARENT).all() -def test_explicit_singular_entities(simulation_builder): - assert simulation_builder.explicit_singular_entities( +def test_explicit_singular_entities(tax_benefit_system): + assert SimulationBuilder().explicit_singular_entities( tax_benefit_system, {'persons': {'Javier': {}}, 'household': {'parents': ['Javier']}} ) == {'persons': {'Javier': {}}, 'households': {'household': {'parents': ['Javier']}}} -def test_add_person_entity(simulation_builder, persons): +def test_add_person_entity(persons): persons_json = {'Alicia': {'salary': {}}, 'Javier': {}} + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, persons_json) assert simulation_builder.get_count('persons') == 2 assert simulation_builder.get_ids('persons') == ['Alicia', 'Javier'] -def test_numeric_ids(simulation_builder, persons): +def test_numeric_ids(persons): persons_json = {1: {'salary': {}}, 2: {}} + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, persons_json) assert simulation_builder.get_count('persons') == 2 assert simulation_builder.get_ids('persons') == ['1', '2'] -def test_add_person_entity_with_values(simulation_builder, persons): +def test_add_person_entity_with_values(persons): persons_json = {'Alicia': {'salary': {'2018-11': 3000}}, 'Javier': {}} + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, persons_json) - assert_near(simulation_builder.get_input('salary', '2018-11'), [3000, 0]) + tools.assert_near(simulation_builder.get_input('salary', '2018-11'), [3000, 0]) -def test_add_person_values_with_default_period(simulation_builder, persons): - simulation_builder.set_default_period('2018-11') +def test_add_person_values_with_default_period(persons): persons_json = {'Alicia': {'salary': 3000}, 'Javier': {}} + simulation_builder = SimulationBuilder() + simulation_builder.set_default_period('2018-11') simulation_builder.add_person_entity(persons, persons_json) - assert_near(simulation_builder.get_input('salary', '2018-11'), [3000, 0]) + tools.assert_near(simulation_builder.get_input('salary', '2018-11'), [3000, 0]) -def test_add_person_values_with_default_period_old_syntax(simulation_builder, persons): - simulation_builder.set_default_period('month:2018-11') +def test_add_person_values_with_default_period_old_syntax(persons): persons_json = {'Alicia': {'salary': 3000}, 'Javier': {}} + simulation_builder = SimulationBuilder() + simulation_builder.set_default_period('month:2018-11') simulation_builder.add_person_entity(persons, persons_json) - assert_near(simulation_builder.get_input('salary', '2018-11'), [3000, 0]) + tools.assert_near(simulation_builder.get_input('salary', '2018-11'), [3000, 0]) -def test_add_group_entity(simulation_builder, group_entity): - simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Sarah', 'Tom'], group_entity, { +def test_add_group_entity(households): + simulation_builder = SimulationBuilder() + simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Sarah', 'Tom'], households, { 'Household_1': {'parents': ['Alicia', 'Javier']}, 'Household_2': {'parents': ['Tom'], 'children': ['Sarah']}, }) @@ -187,8 +133,9 @@ def test_add_group_entity(simulation_builder, group_entity): assert [role.key for role in simulation_builder.get_roles('households')] == ['parent', 'parent', 'child', 'parent'] -def test_add_group_entity_loose_syntax(simulation_builder, group_entity): - simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Sarah', '1'], group_entity, { +def test_add_group_entity_loose_syntax(households): + simulation_builder = SimulationBuilder() + simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Sarah', '1'], households, { 'Household_1': {'parents': ['Alicia', 'Javier']}, 'Household_2': {'parents': 1, 'children': 'Sarah'}, }) @@ -198,95 +145,105 @@ def test_add_group_entity_loose_syntax(simulation_builder, group_entity): assert [role.key for role in simulation_builder.get_roles('households')] == ['parent', 'parent', 'child', 'parent'] -def test_add_variable_value(simulation_builder, persons): +def test_add_variable_value(persons): salary = persons.get_variable('salary') instance_index = 0 + simulation_builder = SimulationBuilder() simulation_builder.entity_counts['persons'] = 1 simulation_builder.add_variable_value(persons, salary, instance_index, 'Alicia', '2018-11', 3000) input_array = simulation_builder.get_input('salary', '2018-11') - assert input_array[instance_index] == approx(3000) + assert input_array[instance_index] == pytest.approx(3000) -def test_add_variable_value_as_expression(simulation_builder, persons): +def test_add_variable_value_as_expression(persons): salary = persons.get_variable('salary') instance_index = 0 + simulation_builder = SimulationBuilder() simulation_builder.entity_counts['persons'] = 1 simulation_builder.add_variable_value(persons, salary, instance_index, 'Alicia', '2018-11', '3 * 1000') input_array = simulation_builder.get_input('salary', '2018-11') - assert input_array[instance_index] == approx(3000) + assert input_array[instance_index] == pytest.approx(3000) -def test_fail_on_wrong_data(simulation_builder, persons): +def test_fail_on_wrong_data(persons): salary = persons.get_variable('salary') instance_index = 0 + simulation_builder = SimulationBuilder() simulation_builder.entity_counts['persons'] = 1 - with raises(SituationParsingError) as excinfo: + with pytest.raises(SituationParsingError) as excinfo: simulation_builder.add_variable_value(persons, salary, instance_index, 'Alicia', '2018-11', 'alicia') assert excinfo.value.error == {'persons': {'Alicia': {'salary': {'2018-11': "Can't deal with value: expected type number, received 'alicia'."}}}} -def test_fail_on_ill_formed_expression(simulation_builder, persons): +def test_fail_on_ill_formed_expression(persons): salary = persons.get_variable('salary') instance_index = 0 + simulation_builder = SimulationBuilder() simulation_builder.entity_counts['persons'] = 1 - with raises(SituationParsingError) as excinfo: + with pytest.raises(SituationParsingError) as excinfo: simulation_builder.add_variable_value(persons, salary, instance_index, 'Alicia', '2018-11', '2 * / 1000') assert excinfo.value.error == {'persons': {'Alicia': {'salary': {'2018-11': "I couldn't understand '2 * / 1000' as a value for 'salary'"}}}} -def test_fail_on_integer_overflow(simulation_builder, persons, int_variable): +def test_fail_on_integer_overflow(persons, int_variable): instance_index = 0 + simulation_builder = SimulationBuilder() simulation_builder.entity_counts['persons'] = 1 - with raises(SituationParsingError) as excinfo: + with pytest.raises(SituationParsingError) as excinfo: simulation_builder.add_variable_value(persons, int_variable, instance_index, 'Alicia', '2018-11', 9223372036854775808) assert excinfo.value.error == {'persons': {'Alicia': {'intvar': {'2018-11': "Can't deal with value: '9223372036854775808', it's too large for type 'integer'."}}}} -def test_fail_on_date_parsing(simulation_builder, persons, date_variable): +def test_fail_on_date_parsing(persons, date_variable): instance_index = 0 + simulation_builder = SimulationBuilder() simulation_builder.entity_counts['persons'] = 1 - with raises(SituationParsingError) as excinfo: + with pytest.raises(SituationParsingError) as excinfo: simulation_builder.add_variable_value(persons, date_variable, instance_index, 'Alicia', '2018-11', '2019-02-30') assert excinfo.value.error == {'persons': {'Alicia': {'datevar': {'2018-11': "Can't deal with date: '2019-02-30'."}}}} -def test_add_unknown_enum_variable_value(simulation_builder, persons, enum_variable): +def test_add_unknown_enum_variable_value(persons, enum_variable): instance_index = 0 + simulation_builder = SimulationBuilder() simulation_builder.entity_counts['persons'] = 1 - with raises(SituationParsingError): + with pytest.raises(SituationParsingError): simulation_builder.add_variable_value(persons, enum_variable, instance_index, 'Alicia', '2018-11', 'baz') -def test_finalize_person_entity(simulation_builder, persons): +def test_finalize_person_entity(persons): persons_json = {'Alicia': {'salary': {'2018-11': 3000}}, 'Javier': {}} + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, persons_json) population = Population(persons) simulation_builder.finalize_variables_init(population) - assert_near(population.get_holder('salary').get_array('2018-11'), [3000, 0]) + tools.assert_near(population.get_holder('salary').get_array('2018-11'), [3000, 0]) assert population.count == 2 assert population.ids == ['Alicia', 'Javier'] -def test_canonicalize_period_keys(simulation_builder, persons): +def test_canonicalize_period_keys(persons): persons_json = {'Alicia': {'salary': {'year:2018-01': 100}}} + simulation_builder = SimulationBuilder() simulation_builder.add_person_entity(persons, persons_json) population = Population(persons) simulation_builder.finalize_variables_init(population) - assert_near(population.get_holder('salary').get_array('2018-12'), [100]) + tools.assert_near(population.get_holder('salary').get_array('2018-12'), [100]) -def test_finalize_group_entity(simulation_builder): +def test_finalize_households(tax_benefit_system): simulation = Simulation(tax_benefit_system, tax_benefit_system.instantiate_entities()) + simulation_builder = SimulationBuilder() simulation_builder.add_group_entity('persons', ['Alicia', 'Javier', 'Sarah', 'Tom'], simulation.household.entity, { 'Household_1': {'parents': ['Alicia', 'Javier']}, 'Household_2': {'parents': ['Tom'], 'children': ['Sarah']}, }) simulation_builder.finalize_variables_init(simulation.household) - assert_near(simulation.household.members_entity_id, [0, 0, 1, 1]) - assert_near(simulation.persons.has_role(Household.PARENT), [True, True, False, True]) + tools.assert_near(simulation.household.members_entity_id, [0, 0, 1, 1]) + tools.assert_near(simulation.persons.has_role(entities.Household.PARENT), [True, True, False, True]) -def test_check_persons_to_allocate(simulation_builder): +def test_check_persons_to_allocate(): entity_plural = 'familles' persons_plural = 'individus' person_id = 'Alicia' @@ -295,13 +252,19 @@ def test_check_persons_to_allocate(simulation_builder): persons_to_allocate = ['Alicia'] persons_ids = ['Alicia'] index = 0 - simulation_builder.check_persons_to_allocate(persons_plural, entity_plural, - persons_ids, - person_id, entity_id, role_id, - persons_to_allocate, index) + SimulationBuilder().check_persons_to_allocate( + persons_plural, + entity_plural, + persons_ids, + person_id, + entity_id, + role_id, + persons_to_allocate, + index, + ) -def test_allocate_undeclared_person(simulation_builder): +def test_allocate_undeclared_person(): entity_plural = 'familles' persons_plural = 'individus' person_id = 'Alicia' @@ -310,8 +273,8 @@ def test_allocate_undeclared_person(simulation_builder): persons_to_allocate = ['Alicia'] persons_ids = [] index = 0 - with raises(SituationParsingError) as exception: - simulation_builder.check_persons_to_allocate( + with pytest.raises(SituationParsingError) as exception: + SimulationBuilder().check_persons_to_allocate( persons_plural, entity_plural, persons_ids, person_id, entity_id, role_id, @@ -319,7 +282,7 @@ def test_allocate_undeclared_person(simulation_builder): assert exception.value.error == {'familles': {'famille1': {'parents': 'Unexpected value: Alicia. Alicia has been declared in famille1 parents, but has not been declared in individus.'}}} -def test_allocate_person_twice(simulation_builder): +def test_allocate_person_twice(): entity_plural = 'familles' persons_plural = 'individus' person_id = 'Alicia' @@ -328,8 +291,8 @@ def test_allocate_person_twice(simulation_builder): persons_to_allocate = [] persons_ids = ['Alicia'] index = 0 - with raises(SituationParsingError) as exception: - simulation_builder.check_persons_to_allocate( + with pytest.raises(SituationParsingError) as exception: + SimulationBuilder().check_persons_to_allocate( persons_plural, entity_plural, persons_ids, person_id, entity_id, role_id, @@ -337,30 +300,31 @@ def test_allocate_person_twice(simulation_builder): assert exception.value.error == {'familles': {'famille1': {'parents': 'Alicia has been declared more than once in familles'}}} -def test_one_person_without_household(simulation_builder): +def test_one_person_without_household(tax_benefit_system): simulation_dict = {'persons': {'Alicia': {}}} - simulation = simulation_builder.build_from_dict(tax_benefit_system, simulation_dict) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, simulation_dict) assert simulation.household.count == 1 - parents_in_households = simulation.household.nb_persons(role = Household.PARENT) + parents_in_households = simulation.household.nb_persons(role = entities.Household.PARENT) assert parents_in_households.tolist() == [1] # household member default role is first_parent -def test_some_person_without_household(simulation_builder): +def test_some_person_without_household(tax_benefit_system): input_yaml = """ persons: {'Alicia': {}, 'Bob': {}} household: {'parents': ['Alicia']} """ - simulation = simulation_builder.build_from_dict(tax_benefit_system, yaml.safe_load(input_yaml)) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, test_runner.yaml.safe_load(input_yaml)) assert simulation.household.count == 2 - parents_in_households = simulation.household.nb_persons(role = Household.PARENT) + parents_in_households = simulation.household.nb_persons(role = entities.Household.PARENT) assert parents_in_households.tolist() == [1, 1] # household member default role is first_parent -def test_nb_persons_in_group_entity(simulation_builder): +def test_nb_persons_in_households(tax_benefit_system): persons_ids: Iterable = [2, 0, 1, 4, 3] households_ids: Iterable = ['c', 'a', 'b'] persons_households: Iterable = ['c', 'a', 'a', 'b', 'a'] + simulation_builder = SimulationBuilder() simulation_builder.create_entities(tax_benefit_system) simulation_builder.declare_person_entity('person', persons_ids) household_instance = simulation_builder.declare_entity('household', households_ids) @@ -371,27 +335,29 @@ def test_nb_persons_in_group_entity(simulation_builder): assert persons_in_households.tolist() == [1, 3, 1] -def test_nb_persons_no_role(simulation_builder): +def test_nb_persons_no_role(tax_benefit_system): persons_ids: Iterable = [2, 0, 1, 4, 3] households_ids: Iterable = ['c', 'a', 'b'] persons_households: Iterable = ['c', 'a', 'a', 'b', 'a'] + simulation_builder = SimulationBuilder() simulation_builder.create_entities(tax_benefit_system) simulation_builder.declare_person_entity('person', persons_ids) household_instance = simulation_builder.declare_entity('household', households_ids) simulation_builder.join_with_persons(household_instance, persons_households, ['first_parent'] * 5) - parents_in_households = household_instance.nb_persons(role = Household.PARENT) + parents_in_households = household_instance.nb_persons(role = entities.Household.PARENT) assert parents_in_households.tolist() == [1, 3, 1] # household member default role is first_parent -def test_nb_persons_by_role(simulation_builder): +def test_nb_persons_by_role(tax_benefit_system): persons_ids: Iterable = [2, 0, 1, 4, 3] households_ids: Iterable = ['c', 'a', 'b'] persons_households: Iterable = ['c', 'a', 'a', 'b', 'a'] persons_households_roles: Iterable = ['child', 'first_parent', 'second_parent', 'first_parent', 'child'] + simulation_builder = SimulationBuilder() simulation_builder.create_entities(tax_benefit_system) simulation_builder.declare_person_entity('person', persons_ids) household_instance = simulation_builder.declare_entity('household', households_ids) @@ -401,18 +367,19 @@ def test_nb_persons_by_role(simulation_builder): persons_households, persons_households_roles ) - parents_in_households = household_instance.nb_persons(role = Household.FIRST_PARENT) + parents_in_households = household_instance.nb_persons(role = entities.Household.FIRST_PARENT) assert parents_in_households.tolist() == [0, 1, 1] -def test_integral_roles(simulation_builder): +def test_integral_roles(tax_benefit_system): persons_ids: Iterable = [2, 0, 1, 4, 3] households_ids: Iterable = ['c', 'a', 'b'] persons_households: Iterable = ['c', 'a', 'a', 'b', 'a'] # Same roles as test_nb_persons_by_role persons_households_roles: Iterable = [2, 0, 1, 0, 2] + simulation_builder = SimulationBuilder() simulation_builder.create_entities(tax_benefit_system) simulation_builder.declare_person_entity('person', persons_ids) household_instance = simulation_builder.declare_entity('household', households_ids) @@ -422,7 +389,7 @@ def test_integral_roles(simulation_builder): persons_households, persons_households_roles ) - parents_in_households = household_instance.nb_persons(role = Household.FIRST_PARENT) + parents_in_households = household_instance.nb_persons(role = entities.Household.FIRST_PARENT) assert parents_in_households.tolist() == [0, 1, 1] @@ -430,7 +397,7 @@ def test_integral_roles(simulation_builder): # Test Intégration -def test_from_person_variable_to_group(simulation_builder): +def test_from_person_variable_to_group(tax_benefit_system): persons_ids: Iterable = [2, 0, 1, 4, 3] households_ids: Iterable = ['c', 'a', 'b'] @@ -441,6 +408,7 @@ def test_from_person_variable_to_group(simulation_builder): period = '2018-12' + simulation_builder = SimulationBuilder() simulation_builder.create_entities(tax_benefit_system) simulation_builder.declare_person_entity('person', persons_ids) @@ -452,43 +420,43 @@ def test_from_person_variable_to_group(simulation_builder): simulation.set_input('rent', period, households_rents) total_taxes = simulation.calculate('total_taxes', period) - assert total_taxes == approx(households_rents) - assert total_taxes / simulation.calculate('rent', period) == approx(1) + assert total_taxes == pytest.approx(households_rents) + assert total_taxes / simulation.calculate('rent', period) == pytest.approx(1) -def test_simulation(simulation_builder): +def test_simulation(tax_benefit_system): input_yaml = """ salary: 2016-10: 12000 """ - simulation = simulation_builder.build_from_dict(tax_benefit_system, yaml.safe_load(input_yaml)) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, test_runner.yaml.safe_load(input_yaml)) assert simulation.get_array("salary", "2016-10") == 12000 simulation.calculate("income_tax", "2016-10") simulation.calculate("total_taxes", "2016-10") -def test_vectorial_input(simulation_builder): +def test_vectorial_input(tax_benefit_system): input_yaml = """ salary: 2016-10: [12000, 20000] """ - simulation = simulation_builder.build_from_dict(tax_benefit_system, yaml.safe_load(input_yaml)) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, test_runner.yaml.safe_load(input_yaml)) - assert_near(simulation.get_array("salary", "2016-10"), [12000, 20000]) + tools.assert_near(simulation.get_array("salary", "2016-10"), [12000, 20000]) simulation.calculate("income_tax", "2016-10") simulation.calculate("total_taxes", "2016-10") -def test_fully_specified_entities(simulation_builder): - simulation = simulation_builder.build_from_dict(tax_benefit_system, couple) +def test_fully_specified_entities(tax_benefit_system): + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, situation_examples.couple) assert simulation.household.count == 1 assert simulation.persons.count == 2 -def test_single_entity_shortcut(simulation_builder): +def test_single_entity_shortcut(tax_benefit_system): input_yaml = """ persons: Alicia: {} @@ -497,11 +465,11 @@ def test_single_entity_shortcut(simulation_builder): parents: [Alicia, Javier] """ - simulation = simulation_builder.build_from_dict(tax_benefit_system, yaml.safe_load(input_yaml)) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, test_runner.yaml.safe_load(input_yaml)) assert simulation.household.count == 1 -def test_order_preserved(simulation_builder): +def test_order_preserved(tax_benefit_system): input_yaml = """ persons: Javier: {} @@ -513,19 +481,19 @@ def test_order_preserved(simulation_builder): children: [Tom, Sarah] """ - data = yaml.safe_load(input_yaml) - simulation = simulation_builder.build_from_dict(tax_benefit_system, data) + data = test_runner.yaml.safe_load(input_yaml) + simulation = SimulationBuilder().build_from_dict(tax_benefit_system, data) assert simulation.persons.ids == ['Javier', 'Alicia', 'Sarah', 'Tom'] -def test_inconsistent_input(simulation_builder): +def test_inconsistent_input(tax_benefit_system): input_yaml = """ salary: 2016-10: [12000, 20000] income_tax: 2016-10: [100, 200, 300] """ - with raises(ValueError) as error: - simulation_builder.build_from_dict(tax_benefit_system, yaml.safe_load(input_yaml)) + with pytest.raises(ValueError) as error: + SimulationBuilder().build_from_dict(tax_benefit_system, test_runner.yaml.safe_load(input_yaml)) assert "its length is 3 while there are 2" in error.value.args[0] diff --git a/tests/core/test_simulations.py b/tests/core/test_simulations.py index 6665cce8e1..d5f3ac8008 100644 --- a/tests/core/test_simulations.py +++ b/tests/core/test_simulations.py @@ -1,14 +1,9 @@ -# -*- coding: utf-8 -*- - - -from openfisca_core.simulation_builder import SimulationBuilder - from openfisca_country_template.situation_examples import single -from .test_countries import tax_benefit_system +from openfisca_core.simulations import SimulationBuilder -def test_calculate_full_tracer(): +def test_calculate_full_tracer(tax_benefit_system): simulation = SimulationBuilder().build_default_simulation(tax_benefit_system) simulation.trace = True simulation.calculate('income_tax', '2017-01') @@ -29,12 +24,12 @@ def test_calculate_full_tracer(): assert income_tax_node.parameters[0].value == 0.15 -def test_get_entity_not_found(): +def test_get_entity_not_found(tax_benefit_system): simulation = SimulationBuilder().build_default_simulation(tax_benefit_system) assert simulation.get_entity(plural = "no_such_entities") is None -def test_clone(): +def test_clone(tax_benefit_system): simulation = SimulationBuilder().build_from_entities(tax_benefit_system, { "persons": { @@ -63,7 +58,7 @@ def test_clone(): assert salary_holder_clone.population == simulation_clone.persons -def test_get_memory_usage(): +def test_get_memory_usage(tax_benefit_system): simulation = SimulationBuilder().build_from_entities(tax_benefit_system, single) simulation.calculate('disposable_income', '2017-01') memory_usage = simulation.get_memory_usage(variables = ['salary']) diff --git a/tests/core/test_yaml.py b/tests/core/test_yaml.py index 2390eb6929..15085dbbf3 100644 --- a/tests/core/test_yaml.py +++ b/tests/core/test_yaml.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import pkg_resources import os import subprocess @@ -9,8 +7,6 @@ from openfisca_core.tools.test_runner import run_tests -from .test_countries import tax_benefit_system - openfisca_core_dir = pkg_resources.get_distribution('OpenFisca-Core').location yaml_tests_dir = os.path.join(openfisca_core_dir, 'tests', 'core', 'yaml_tests') @@ -18,7 +14,7 @@ EXIT_TESTSFAILED = 1 -def run_yaml_test(path, options = None): +def run_yaml_test(tax_benefit_system, path, options = None): yaml_path = os.path.join(yaml_tests_dir, path) if options is None: @@ -28,53 +24,54 @@ def run_yaml_test(path, options = None): return result -def test_success(): - assert run_yaml_test('test_success.yml') == EXIT_OK +def test_success(tax_benefit_system): + assert run_yaml_test(tax_benefit_system, 'test_success.yml') == EXIT_OK -def test_fail(): - assert run_yaml_test('test_failure.yaml') == EXIT_TESTSFAILED +def test_fail(tax_benefit_system): + assert run_yaml_test(tax_benefit_system, 'test_failure.yaml') == EXIT_TESTSFAILED -def test_relative_error_margin_success(): - assert run_yaml_test('test_relative_error_margin.yaml') == EXIT_OK +def test_relative_error_margin_success(tax_benefit_system): + assert run_yaml_test(tax_benefit_system, 'test_relative_error_margin.yaml') == EXIT_OK -def test_relative_error_margin_fail(): - assert run_yaml_test('failing_test_relative_error_margin.yaml') == EXIT_TESTSFAILED +def test_relative_error_margin_fail(tax_benefit_system): + assert run_yaml_test(tax_benefit_system, 'failing_test_relative_error_margin.yaml') == EXIT_TESTSFAILED -def test_absolute_error_margin_success(): - assert run_yaml_test('test_absolute_error_margin.yaml') == EXIT_OK +def test_absolute_error_margin_success(tax_benefit_system): + assert run_yaml_test(tax_benefit_system, 'test_absolute_error_margin.yaml') == EXIT_OK -def test_absolute_error_margin_fail(): - assert run_yaml_test('failing_test_absolute_error_margin.yaml') == EXIT_TESTSFAILED +def test_absolute_error_margin_fail(tax_benefit_system): + assert run_yaml_test(tax_benefit_system, 'failing_test_absolute_error_margin.yaml') == EXIT_TESTSFAILED -def test_run_tests_from_directory(): +def test_run_tests_from_directory(tax_benefit_system): dir_path = os.path.join(yaml_tests_dir, 'directory') - assert run_yaml_test(dir_path) == EXIT_OK + assert run_yaml_test(tax_benefit_system, dir_path) == EXIT_OK -def test_with_reform(): - assert run_yaml_test('test_with_reform.yaml') == EXIT_OK +def test_with_reform(tax_benefit_system): + assert run_yaml_test(tax_benefit_system, 'test_with_reform.yaml') == EXIT_OK -def test_with_extension(): - assert run_yaml_test('test_with_extension.yaml') == EXIT_OK +def test_with_extension(tax_benefit_system): + assert run_yaml_test(tax_benefit_system, 'test_with_extension.yaml') == EXIT_OK -def test_with_anchors(): - assert run_yaml_test('test_with_anchors.yaml') == EXIT_OK +def test_with_anchors(tax_benefit_system): + assert run_yaml_test(tax_benefit_system, 'test_with_anchors.yaml') == EXIT_OK -def test_run_tests_from_directory_fail(): - assert run_yaml_test(yaml_tests_dir) == EXIT_TESTSFAILED +def test_run_tests_from_directory_fail(tax_benefit_system): + assert run_yaml_test(tax_benefit_system, yaml_tests_dir) == EXIT_TESTSFAILED -def test_name_filter(): +def test_name_filter(tax_benefit_system): assert run_yaml_test( + tax_benefit_system, yaml_tests_dir, options = {'name_filter': 'success'} ) == EXIT_OK diff --git a/tests/core/tools/test_assert_near.py b/tests/core/tools/test_assert_near.py index 597e3d612b..eecf9d1d1f 100644 --- a/tests/core/tools/test_assert_near.py +++ b/tests/core/tools/test_assert_near.py @@ -1,23 +1,20 @@ - import numpy as np from openfisca_core.tools import assert_near -from ..test_countries import tax_benefit_system - def test_date(): assert_near(np.array("2012-03-24", dtype = 'datetime64[D]'), "2012-03-24") -def test_enum(): +def test_enum(tax_benefit_system): possible_values = tax_benefit_system.variables['housing_occupancy_status'].possible_values value = possible_values.encode(np.array(['tenant'])) expected_value = 'tenant' assert_near(value, expected_value) -def test_enum_2(): +def test_enum_2(tax_benefit_system): possible_values = tax_benefit_system.variables['housing_occupancy_status'].possible_values value = possible_values.encode(np.array(['tenant', 'owner'])) expected_value = ['tenant', 'owner'] diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/entities.py b/tests/fixtures/entities.py new file mode 100644 index 0000000000..99b6196599 --- /dev/null +++ b/tests/fixtures/entities.py @@ -0,0 +1,44 @@ +import pytest + +from openfisca_core.entities import Entity, GroupEntity + +from .variables import TestVariable + + +class TestEntity(Entity): + def get_variable(self, variable_name): + result = TestVariable(self) + result.name = variable_name + return result + + def check_variable_defined_for_entity(self, variable_name): + return True + + +class TestGroupEntity(GroupEntity): + def get_variable(self, variable_name): + result = TestVariable(self) + result.name = variable_name + return result + + def check_variable_defined_for_entity(self, variable_name): + return True + + +@pytest.fixture +def persons(): + return TestEntity("person", "persons", "", "") + + +@pytest.fixture +def households(): + roles = [{ + 'key': 'parent', + 'plural': 'parents', + 'max': 2 + }, { + 'key': 'child', + 'plural': 'children' + }] + + return TestGroupEntity("household", "households", "", "", roles) diff --git a/tests/fixtures/simulations.py b/tests/fixtures/simulations.py new file mode 100644 index 0000000000..9d343d5ac0 --- /dev/null +++ b/tests/fixtures/simulations.py @@ -0,0 +1,31 @@ +import functools + +import pytest + +from openfisca_core.simulations import SimulationBuilder + + +@pytest.fixture +def simulation(tax_benefit_system, request): + variables, period = request.param + + return _simulation( + SimulationBuilder(), + tax_benefit_system, + variables, + period, + ) + + +@pytest.fixture +def make_simulation(): + return functools.partial(_simulation, SimulationBuilder()) + + +def _simulation(simulation_builder, tax_benefit_system, variables, period): + simulation_builder.set_default_period(period) + simulation = \ + simulation_builder \ + .build_from_variables(tax_benefit_system, variables) + + return simulation diff --git a/tests/fixtures/taxbenefitsystems.py b/tests/fixtures/taxbenefitsystems.py new file mode 100644 index 0000000000..c2c47071ca --- /dev/null +++ b/tests/fixtures/taxbenefitsystems.py @@ -0,0 +1,13 @@ +import pytest + +from openfisca_country_template import CountryTaxBenefitSystem + + +@pytest.fixture(scope = "module") +def tax_benefit_system(): + return CountryTaxBenefitSystem() + + +@pytest.fixture +def isolated_tax_benefit_system(): + return CountryTaxBenefitSystem() diff --git a/tests/fixtures/variables.py b/tests/fixtures/variables.py new file mode 100644 index 0000000000..cd0d9b70ce --- /dev/null +++ b/tests/fixtures/variables.py @@ -0,0 +1,11 @@ +from openfisca_core import periods +from openfisca_core.variables import Variable + + +class TestVariable(Variable): + definition_period = periods.ETERNITY + value_type = float + + def __init__(self, entity): + self.__class__.entity = entity + super().__init__()