Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit test parameter formatters #708

Merged
merged 10 commits into from
Oct 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion webapp/apps/taxbrain/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,11 @@ def get_default_policy_param_name(param, default_params):
ix = int(end_piece)
except ValueError:
msg = "Parsing {}: Expected integer for index but got {}"
raise ValueError(msg.format(param, ix))
raise ValueError(msg.format(param, end_piece))
num_columns = len(default_params[no_suffix]['col_label'])
if ix < 0 or ix >= num_columns:
msg = "Parsing {}: Index {} not in range ({}, {})"
raise IndexError(msg.format(param, ix, 0, num_columns))
col_label = default_params[no_suffix]['col_label'][ix]
return no_suffix + '_' + col_label
msg = "Received unexpected parameter: {}"
Expand Down
17 changes: 17 additions & 0 deletions webapp/apps/test_assets/test_assumptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,20 @@
"consumption": {},
"growdiff_baseline": {}
}"""

exp_assumptions_text = {
'growdiff_response': {},
'consumption': {},
'behavior': {
2017: {u'_BE_sub': [1.0], u'_BE_inc': [-0.6], u'_BE_cg': [-0.67]}},
'growdiff_baseline': {}
}

no_assumptions_text = """
{
"growdiff_response": {},
"consumption": {},
"behavior": {},
"growdiff_baseline": {}
}
"""
127 changes: 127 additions & 0 deletions webapp/apps/test_assets/test_param_formatters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import json
import pytest
import taxcalc
import numpy as np

from ..taxbrain.views import read_json_reform, parse_errors_warnings
from ..taxbrain.helpers import (get_default_policy_param_name, to_json_reform)

from test_reform import (test_coverage_fields, test_coverage_reform,
test_coverage_json_reform,
test_coverage_exp_read_json_reform,
errors_warnings_fields, errors_warnings_reform,
errors_warnings_json_reform,
errors_warnings_exp_read_json_reform,
errors_warnings, exp_errors_warnings,
map_back_to_tb)

from test_assumptions import (assumptions_text, exp_assumptions_text, no_assumptions_text)

START_YEAR = 2017

@pytest.fixture
def default_params_Policy():
return taxcalc.Policy.default_data(start_year=START_YEAR,
metadata=True)


###############################################################################
# Test get_default_policy_param_name
# 3 Cases for search success:
# 1. "_" + param name
# 2. "_" + param name + index name (i.e. STD_0 --> _STD_single)
# 3. "_" + param name minus "_cpi"
@pytest.mark.parametrize("param,exp_param",
[("FICA_ss_trt", "_FICA_ss_trt"),
("ID_BenefitSurtax_Switch_0", "_ID_BenefitSurtax_Switch_medical"),
("CG_brk3_cpi", "_CG_brk3_cpi")])
def test_get_default_policy_param_name_passing(param, exp_param, default_params_Policy):
act_param = get_default_policy_param_name(param, default_params_Policy)
np.testing.assert_equal(act_param, exp_param)

@pytest.mark.parametrize("param", ["CG_brk3_extra_cpi", "not_a_param"])
def test_get_default_policy_param_name_failing0(param, default_params_Policy):
"""
Check that non-recognized parameters throw a ValueError
"""
match="Received unexpected parameter: {0}".format(param)
with pytest.raises(ValueError, match=match):
get_default_policy_param_name(param, default_params_Policy)


def test_get_default_policy_param_name_failing1(default_params_Policy):
"""
Check that parameter with non-integer characters after the final '_'
throws ValueError
"""
param = "ID_BenefitSurtax_Switch_idx"
match = "Parsing {}: Expected integer for index but got {}".format(param, "idx")
with pytest.raises(ValueError, match=match):
get_default_policy_param_name(param, default_params_Policy)


def test_get_default_policy_param_name_failing2(default_params_Policy):
"""
Check that parameter with correct name but out of bounds index throws
IndexError
"""
param = "ID_BenefitSurtax_Switch_12"
# comment out "(" since this is treated as a regexp string
match = "Parsing {}: Index {} not in range \({}, {}\)"
match = match.format(param, 12, 0, 7)
with pytest.raises(IndexError, match=match):
get_default_policy_param_name(param, default_params_Policy)

###############################################################################
# Test to_json_reform
# 2 Cases:
# 1. Fields do not cause errors
# 2. Fields cause errors
@pytest.mark.parametrize(
("fields,exp_reform"),
[(test_coverage_fields, test_coverage_reform),
(errors_warnings_fields, errors_warnings_reform)]
)
def test_to_json_reform(fields, exp_reform):
act, _ = to_json_reform(fields, START_YEAR)
np.testing.assert_equal(act, exp_reform)

###############################################################################
# Test parse_errors_warnings
def test_parse_errors_warnings():
act = parse_errors_warnings(errors_warnings, map_back_to_tb)
np.testing.assert_equal(exp_errors_warnings, act)


###############################################################################
# Test read_json_reform
# 3 Cases:
# 1. Reform does not throw errors and no behavior assumptions are made
# 2. Reform does not throw errors and behavior assumptions are made
# 3. Reform throws errors and warnings and behavior assumptions are not made
@pytest.mark.parametrize(
("test_reform,test_assump,map_back_to_tb,exp_reform,exp_assump,"
"exp_errors_warnings"),
[(test_coverage_json_reform, no_assumptions_text,
map_back_to_tb, test_coverage_exp_read_json_reform,
json.loads(no_assumptions_text),
{'errors': {}, 'warnings': {}}),
(test_coverage_json_reform, assumptions_text,
map_back_to_tb, test_coverage_exp_read_json_reform,
exp_assumptions_text,
{'errors': {}, 'warnings': {}}),
(errors_warnings_json_reform, no_assumptions_text,
map_back_to_tb, errors_warnings_exp_read_json_reform,
json.loads(no_assumptions_text), exp_errors_warnings)
]
)
def test_read_json_reform(test_reform, test_assump, map_back_to_tb,
exp_reform, exp_assump, exp_errors_warnings):
act_reform, act_assump, act_errors_warnings = read_json_reform(
test_reform,
test_assump,
map_back_to_tb
)
np.testing.assert_equal(exp_reform, act_reform)
np.testing.assert_equal(exp_assump, act_assump)
np.testing.assert_equal(exp_errors_warnings, act_errors_warnings)
212 changes: 212 additions & 0 deletions webapp/apps/test_assets/test_reform.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,215 @@
}
}
"""

"""
********************************************************************
The following objects were created for test_param_formatters.py.

fields_base -- typical metadata associated with TaxBrain run

test_coverage_* objects -- these objects do not throw TC warnings or errors
but include a representative for each type of TC parameter in
current_law_policy.json

errors_warnings_* -- these objects do throw warnings and errors and include
a mostly representative set of TC parameters

map_back_to_tb -- required for mapping Tax-Calculator styled parameter
names to TaxBrain styled names
********************************************************************
"""

fields_base = {
'_state': "<django.db.models.base.ModelState object at 0x10c764950>",
'creation_date': "datetime.datetime(2015, 1, 1, 0, 0)",
'id': 64,
'quick_calc': False,
'first_year': 2017,
}

test_coverage_fields = dict(
CG_nodiff = [False],
FICA_ss_trt = [u'*', 0.1, u'*', 0.2],
STD_0 = [8000.0, '*', 10000.0],
ID_BenefitSurtax_Switch_0 = [True],
ID_Charity_c_cpi = True,
EITC_rt_2 = [1.0],
**fields_base
)

test_coverage_reform = {
'_CG_nodiff': {'2017': [False]},
'_FICA_ss_trt': {'2020': [0.2], '2018': [0.1]},
'_STD_single': {'2017': [8000.0], '2019': [10000.0]},
'_ID_Charity_c_cpi': {'2017': True},
'_ID_BenefitSurtax_Switch_medical': {'2017': [True]},
'_EITC_rt_2kids': {'2017': [1.0]}
}

errors_warnings_fields = dict(
STD_0 = [7000.0],
FICA_ss_trt = [-1.0,'*',0.1],
II_brk4_0 = [500.0],
STD_3= [10000.0, '*', '*', 150.0],
ID_BenefitSurtax_Switch_0= [True],
**fields_base
)

errors_warnings_reform = {
u'_STD_single': {u'2017': [7000.0]},
u'_FICA_ss_trt': {u'2017': [-1.0], u'2019': [0.1]},
u'_II_brk4_single': {u'2017': [500.0]},
u'_STD_headhousehold': {u'2017': [10000.0], u'2020': [150.0]},
u'_ID_BenefitSurtax_Switch_medical': {u'2017': [True]}
}


map_back_to_tb = {
u'_ID_BenefitSurtax_Switch_charity': 'ID_BenefitSurtax_Switch_6',
'_ALD_InvInc_ec_base_RyanBrady': 'ALD_InvInc_ec_base_RyanBrady',
u'_ID_BenefitSurtax_Switch_interest': 'ID_BenefitSurtax_Switch_5',
'_EITC_indiv': 'EITC_indiv',
u'_ID_BenefitSurtax_Switch_misc': 'ID_BenefitSurtax_Switch_4',
u'_ID_BenefitCap_Switch_charity': 'ID_BenefitCap_Switch_6',
u'_STD_single': 'STD_0',
'_II_no_em_nu18': 'II_no_em_nu18',
u'_ID_BenefitSurtax_Switch_realestate': 'ID_BenefitSurtax_Switch_2',
u'_ID_BenefitCap_Switch_misc': 'ID_BenefitCap_Switch_4',
'_CG_nodiff': 'CG_nodiff',
u'_ID_BenefitSurtax_Switch_statelocal': 'ID_BenefitSurtax_Switch_1',
u'_ID_BenefitCap_Switch_medical': 'ID_BenefitCap_Switch_0',
'_FICA_ss_trt': 'FICA_ss_trt',
u'_ID_BenefitCap_Switch_casualty': 'ID_BenefitCap_Switch_3',
'_ID_Charity_c_cpi': 'ID_Charity_c_cpi',
u'_ID_BenefitCap_Switch_statelocal': 'ID_BenefitCap_Switch_1',
u'_EITC_rt_2kids': 'EITC_rt_2',
u'_ID_BenefitSurtax_Switch_casualty': 'ID_BenefitSurtax_Switch_3',
'_NIIT_PT_taxed': 'NIIT_PT_taxed',
u'_ID_BenefitSurtax_Switch_medical': 'ID_BenefitSurtax_Switch_0',
u'_ID_BenefitCap_Switch_interest': 'ID_BenefitCap_Switch_5',
'_CTC_new_refund_limited': 'CTC_new_refund_limited',
u'_ID_BenefitCap_Switch_realestate': 'ID_BenefitCap_Switch_2',
u'_STD_single': 'STD_0',
u'_STD_headhousehold': 'STD_3',
u'_II_brk4_single': 'II_brk4_0'
}

test_coverage_json_reform = """
{
"policy": {
"_ID_BenefitSurtax_Switch_charity": {"2017": [0.0]},
"_ALD_InvInc_ec_base_RyanBrady": {"2017": [false]},
"_ID_BenefitSurtax_Switch_interest": {"2017": [0.0]},
"_EITC_indiv": {"2017": [false]},
"_ID_BenefitSurtax_Switch_misc": {"2017": [0.0]},
"_ID_BenefitCap_Switch_charity": {"2017": [0.0]},
"_STD_single": {"2017": [10000.0]},
"_II_no_em_nu18": {"2017": [false]},
"_ID_BenefitSurtax_Switch_realestate": {"2017": [0.0]},
"_ID_BenefitCap_Switch_misc": {"2017": [0.0]},
"_CG_nodiff": {"2017": [false]},
"_ID_BenefitSurtax_Switch_statelocal": {"2017": [0.0]},
"_ID_BenefitCap_Switch_medical": {"2017": [0.0]},
"_FICA_ss_trt": {"2020": [0.2], "2018": [0.1]},
"_ID_BenefitCap_Switch_casualty": {"2017": [0.0]},
"_ID_Charity_c_cpi": {"2017": true},
"_ID_BenefitCap_Switch_statelocal": {"2017": [0.0]},
"_EITC_rt_2kids": {"2017": [1.0]},
"_ID_BenefitSurtax_Switch_casualty": {"2017": [0.0]},
"_NIIT_PT_taxed": {"2017": [false]},
"_ID_BenefitSurtax_Switch_medical": {"2017": [1.0]},
"_ID_BenefitCap_Switch_interest": {"2017": [0.0]},
"_CTC_new_refund_limited": {"2017": [false]},
"_ID_BenefitCap_Switch_realestate": {"2017": [0.0]}
}
}
"""

errors_warnings_json_reform = """
{
"policy": {
"_ID_BenefitSurtax_Switch_medical": {"2017": [true]},
"_STD_headhousehold": {"2017": [10000.0], "2020": [150.0]},
"_FICA_ss_trt": {"2017": [-1.0], "2019": [0.1]},
"_STD_single": {"2017": [7000.0]},
"_II_brk4_single": {"2017": [500.0]}
}
}
"""

test_coverage_exp_read_json_reform = {
2017: {u'_EITC_rt': [[0.0765, 0.34, 1.0, 0.45]],
u'_NIIT_PT_taxed': [False],
u'_ID_BenefitCap_Switch': [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]],
u'_ALD_InvInc_ec_base_RyanBrady': [False],
u'_EITC_indiv': [False],
u'_ID_BenefitSurtax_Switch': [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]],
u'_STD': [[10000.0, 12700.0, 6350.0, 9350.0, 12700.0]],
u'_II_no_em_nu18': [False],
u'_ID_Charity_c_cpi': True,
u'_CG_nodiff': [False],
u'_CTC_new_refund_limited': [False]},
2018: {u'_FICA_ss_trt': [0.1]},
2020: {u'_FICA_ss_trt': [0.2]}
}


errors_warnings_exp_read_json_reform = {
2017:
{u'_II_brk4': [[500.0, 233350.0, 116675.0, 212500.0, 233350.0]],
u'_STD': [[7000.0, 12700.0, 6350.0, 10000.0, 12700.0]],
u'_ID_BenefitSurtax_Switch': [[True, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]],
u'_FICA_ss_trt': [-1.0]},
2019: {u'_FICA_ss_trt': [0.1]},
2020: {u'_STD': [[7489.8, 13588.64, 6794.31, 150.0, 13588.64]]}
}

errors = ("ERROR: 2017 _FICA_ss_trt value -1.0 < min value 0\n"
"ERROR: 2018 _FICA_ss_trt value -1.0 < min value 0\n"
"ERROR: 2017 _II_brk4_0 value 500.0 < min value 91900.0 for _II_brk3_0\n"
"ERROR: 2018 _II_brk4_0 value 511.1 < min value 93940.18 for _II_brk3_0\n"
"ERROR: 2019 _II_brk4_0 value 522.8 < min value 96091.41 for _II_brk3_0\n"
"ERROR: 2020 _II_brk4_0 value 534.98 < min value 98330.34 for _II_brk3_0\n"
"ERROR: 2021 _II_brk4_0 value 547.45 < min value 100621.44 for _II_brk3_0\n"
"ERROR: 2022 _II_brk4_0 value 560.15 < min value 102955.86 for _II_brk3_0\n"
"ERROR: 2023 _II_brk4_0 value 573.2 < min value 105354.73 for _II_brk3_0\n"
"ERROR: 2024 _II_brk4_0 value 586.56 < min value 107809.5 for _II_brk3_0\n"
"ERROR: 2025 _II_brk4_0 value 600.29 < min value 110332.24 for _II_brk3_0\n"
"ERROR: 2026 _II_brk4_0 value 614.4 < min value 112925.05 for _II_brk3_0\n")

warnings = ("WARNING: 2020 _STD_3 value 150.0 < min value 10004.23\n"
"WARNING: 2021 _STD_3 value 153.5 < min value 10237.33\n"
"WARNING: 2022 _STD_3 value 157.06 < min value 10474.84\n"
"WARNING: 2023 _STD_3 value 160.72 < min value 10718.9\n"
"WARNING: 2024 _STD_3 value 164.46 < min value 10968.65\n"
"WARNING: 2025 _STD_3 value 168.31 < min value 11225.32\n"
"WARNING: 2026 _STD_3 value 172.27 < min value 11489.12\n")

errors_warnings = {'errors': errors, 'warnings': warnings}

exp_errors_warnings = {
'errors': {
'2024': {'II_brk4_0': 'ERROR: value 586.56 < min value 107809.5 for _II_brk3_0 for 2024'},
'2025': {'II_brk4_0': 'ERROR: value 600.29 < min value 110332.24 for _II_brk3_0 for 2025'},
'2026': {'II_brk4_0': 'ERROR: value 614.4 < min value 112925.05 for _II_brk3_0 for 2026'},
'2020': {'II_brk4_0': 'ERROR: value 534.98 < min value 98330.34 for _II_brk3_0 for 2020'},
'2018': {'FICA_ss_trt': 'ERROR: value -1.0 < min value 0 for 2018',
'II_brk4_0': 'ERROR: value 511.1 < min value 93940.18 for _II_brk3_0 for 2018'},
'2022': {'II_brk4_0': 'ERROR: value 560.15 < min value 102955.86 for _II_brk3_0 for 2022'},
'2023': {'II_brk4_0': 'ERROR: value 573.2 < min value 105354.73 for _II_brk3_0 for 2023'},
'2019': {'II_brk4_0': 'ERROR: value 522.8 < min value 96091.41 for _II_brk3_0 for 2019'},
'2017': {'FICA_ss_trt': 'ERROR: value -1.0 < min value 0 for 2017',
'II_brk4_0': 'ERROR: value 500.0 < min value 91900.0 for _II_brk3_0 for 2017'},
'2021': {'II_brk4_0': 'ERROR: value 547.45 < min value 100621.44 for _II_brk3_0 for 2021'}
},
'warnings': {
'2024': {'STD_3': 'WARNING: value 164.46 < min value 10968.65 for 2024'},
'2025': {'STD_3': 'WARNING: value 168.31 < min value 11225.32 for 2025'},
'2026': {'STD_3': 'WARNING: value 172.27 < min value 11489.12 for 2026'},
'2020': {'STD_3': 'WARNING: value 150.0 < min value 10004.23 for 2020'},
'2021': {'STD_3': 'WARNING: value 153.5 < min value 10237.33 for 2021'},
'2022': {'STD_3': 'WARNING: value 157.06 < min value 10474.84 for 2022'},
'2023': {'STD_3': 'WARNING: value 160.72 < min value 10718.9 for 2023'}
}
}