taxcalc 4.2.1__py3-none-any.whl → 4.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- taxcalc/__init__.py +1 -1
- taxcalc/assumptions/ASSUMPTIONS.md +53 -0
- taxcalc/assumptions/README.md +17 -0
- taxcalc/assumptions/economic_assumptions_template.json +77 -0
- taxcalc/calcfunctions.py +7 -4
- taxcalc/data.py +10 -5
- taxcalc/policy_current_law.json +2033 -184
- taxcalc/reforms/2017_law.json +125 -0
- taxcalc/reforms/2017_law.out.csv +10 -0
- taxcalc/reforms/ARPA.json +78 -0
- taxcalc/reforms/ARPA.out.csv +10 -0
- taxcalc/reforms/BrownKhanna.json +23 -0
- taxcalc/reforms/BrownKhanna.out.csv +10 -0
- taxcalc/reforms/CARES.json +40 -0
- taxcalc/reforms/CARES.out.csv +10 -0
- taxcalc/reforms/ConsolidatedAppropriationsAct2021.json +15 -0
- taxcalc/reforms/ConsolidatedAppropriationsAct2021.out.csv +10 -0
- taxcalc/reforms/Larson2019.json +36 -0
- taxcalc/reforms/Larson2019.out.csv +10 -0
- taxcalc/reforms/README.md +22 -0
- taxcalc/reforms/REFORMS.md +92 -0
- taxcalc/reforms/Renacci.json +61 -0
- taxcalc/reforms/Renacci.out.csv +10 -0
- taxcalc/reforms/SandersDeFazio.json +15 -0
- taxcalc/reforms/SandersDeFazio.out.csv +10 -0
- taxcalc/reforms/TCJA.json +160 -0
- taxcalc/reforms/TCJA.md +48 -0
- taxcalc/reforms/TCJA.out.csv +10 -0
- taxcalc/reforms/Trump2016.json +71 -0
- taxcalc/reforms/Trump2016.out.csv +10 -0
- taxcalc/reforms/Trump2017.json +51 -0
- taxcalc/reforms/Trump2017.out.csv +10 -0
- taxcalc/reforms/archive/Clinton2016.json +56 -0
- taxcalc/reforms/archive/RyanBrady.json +104 -0
- taxcalc/reforms/archive/TCJA_House.json +144 -0
- taxcalc/reforms/archive/TCJA_House_Amended.json +152 -0
- taxcalc/reforms/archive/TCJA_Reconciliation.json +187 -0
- taxcalc/reforms/archive/TCJA_Senate.json +116 -0
- taxcalc/reforms/archive/TCJA_Senate_111417.json +169 -0
- taxcalc/reforms/archive/TCJA_Senate_120117.json +174 -0
- taxcalc/reforms/cases.csv +10 -0
- taxcalc/reforms/clp.out.csv +10 -0
- taxcalc/reforms/ext.json +59 -0
- taxcalc/reforms/growfactors_ext.csv +65 -0
- taxcalc/reforms/ptaxes0.json +37 -0
- taxcalc/reforms/ptaxes0.out.csv +10 -0
- taxcalc/reforms/ptaxes1.json +21 -0
- taxcalc/reforms/ptaxes1.out.csv +10 -0
- taxcalc/reforms/ptaxes2.json +18 -0
- taxcalc/reforms/ptaxes2.out.csv +10 -0
- taxcalc/reforms/ptaxes3.json +28 -0
- taxcalc/reforms/ptaxes3.out.csv +10 -0
- taxcalc/reforms/rounding2022.json +153 -0
- taxcalc/reforms/rounding2022.out.csv +10 -0
- taxcalc/tests/benefits_expect.csv +169 -0
- taxcalc/tests/cmpi_cps_expect.txt +132 -0
- taxcalc/tests/cmpi_puf_expect.txt +132 -0
- taxcalc/tests/conftest.py +143 -0
- taxcalc/tests/cpscsv_agg_expect.csv +26 -0
- taxcalc/tests/puf_var_correl_coeffs_2016.csv +80 -0
- taxcalc/tests/puf_var_wght_means_by_year.csv +80 -0
- taxcalc/tests/pufcsv_agg_expect.csv +26 -0
- taxcalc/tests/pufcsv_mtr_expect.txt +63 -0
- taxcalc/tests/reforms.json +649 -0
- taxcalc/tests/reforms_expect.csv +65 -0
- taxcalc/tests/test_4package.py +67 -0
- taxcalc/tests/test_benefits.py +86 -0
- taxcalc/tests/test_calcfunctions.py +871 -0
- taxcalc/tests/test_calculator.py +1021 -0
- taxcalc/tests/test_compare.py +336 -0
- taxcalc/tests/test_compatible_data.py +338 -0
- taxcalc/tests/test_consumption.py +144 -0
- taxcalc/tests/test_cpscsv.py +163 -0
- taxcalc/tests/test_data.py +133 -0
- taxcalc/tests/test_decorators.py +332 -0
- taxcalc/tests/test_growdiff.py +102 -0
- taxcalc/tests/test_growfactors.py +94 -0
- taxcalc/tests/test_parameters.py +617 -0
- taxcalc/tests/test_policy.py +1575 -0
- taxcalc/tests/test_puf_var_stats.py +194 -0
- taxcalc/tests/test_pufcsv.py +385 -0
- taxcalc/tests/test_records.py +234 -0
- taxcalc/tests/test_reforms.py +385 -0
- taxcalc/tests/test_responses.py +41 -0
- taxcalc/tests/test_taxcalcio.py +755 -0
- taxcalc/tests/test_tmdcsv.py +38 -0
- taxcalc/tests/test_utils.py +792 -0
- taxcalc/tmd_growfactors.csv +54 -54
- taxcalc/tmd_weights.csv.gz +0 -0
- taxcalc/validation/CSV_INPUT_VARS.md +29 -0
- taxcalc/validation/CSV_OUTPUT_VARS.md +63 -0
- taxcalc/validation/README.md +68 -0
- taxcalc/validation/taxsim35/Differences_Explained.md +54 -0
- taxcalc/validation/taxsim35/README.md +139 -0
- taxcalc/validation/taxsim35/expected_differences/a17-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/a18-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/a19-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/a20-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/a21-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/b17-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/b18-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/b19-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/b20-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/b21-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/c17-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/c18-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/expected_differences/c19-taxdiffs-expect.csv +25 -0
- taxcalc/validation/taxsim35/input_setup.py +67 -0
- taxcalc/validation/taxsim35/main_comparison.py +183 -0
- taxcalc/validation/taxsim35/prepare_taxcalc_input.py +161 -0
- taxcalc/validation/taxsim35/process_taxcalc_output.py +140 -0
- taxcalc/validation/taxsim35/taxsim_emulation.json +49 -0
- taxcalc/validation/taxsim35/taxsim_input.py +321 -0
- taxcalc/validation/taxsim35/tc_sims.py +98 -0
- taxcalc/validation/taxsim35/tests_35.py +80 -0
- taxcalc/validation/tests_35.sh +13 -0
- {taxcalc-4.2.1.dist-info → taxcalc-4.2.2.dist-info}/METADATA +3 -4
- taxcalc-4.2.2.dist-info/RECORD +144 -0
- {taxcalc-4.2.1.dist-info → taxcalc-4.2.2.dist-info}/WHEEL +1 -1
- taxcalc-4.2.1.dist-info/RECORD +0 -34
- {taxcalc-4.2.1.dist-info → taxcalc-4.2.2.dist-info}/LICENSE +0 -0
- {taxcalc-4.2.1.dist-info → taxcalc-4.2.2.dist-info}/entry_points.txt +0 -0
- {taxcalc-4.2.1.dist-info → taxcalc-4.2.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,871 @@
|
|
1
|
+
"""
|
2
|
+
Tests for Tax-Calculator calcfunctions.py logic.
|
3
|
+
"""
|
4
|
+
# CODING-STYLE CHECKS:
|
5
|
+
# pycodestyle test_calcfunctions.py
|
6
|
+
# pylint --disable=locally-disabled test_calcfunctions.py
|
7
|
+
|
8
|
+
import os
|
9
|
+
import re
|
10
|
+
import ast
|
11
|
+
from taxcalc import Records # pylint: disable=import-error
|
12
|
+
from taxcalc import calcfunctions
|
13
|
+
import numpy as np
|
14
|
+
import pytest
|
15
|
+
|
16
|
+
|
17
|
+
class GetFuncDefs(ast.NodeVisitor):
|
18
|
+
"""
|
19
|
+
Return information about each function defined in the functions.py file.
|
20
|
+
"""
|
21
|
+
def __init__(self):
|
22
|
+
"""
|
23
|
+
GetFuncDefs class constructor
|
24
|
+
"""
|
25
|
+
self.fname = ''
|
26
|
+
self.fnames = list() # function name (fname) list
|
27
|
+
self.fargs = dict() # lists of function arguments indexed by fname
|
28
|
+
self.cvars = dict() # lists of calc vars in function indexed by fname
|
29
|
+
self.rvars = dict() # lists of function return vars indexed by fname
|
30
|
+
|
31
|
+
def visit_Module(self, node): # pylint: disable=invalid-name
|
32
|
+
"""
|
33
|
+
visit the specified Module node
|
34
|
+
"""
|
35
|
+
self.generic_visit(node)
|
36
|
+
return (self.fnames, self.fargs, self.cvars, self.rvars)
|
37
|
+
|
38
|
+
def visit_FunctionDef(self, node): # pylint: disable=invalid-name
|
39
|
+
"""
|
40
|
+
visit the specified FunctionDef node
|
41
|
+
"""
|
42
|
+
self.fname = node.name
|
43
|
+
self.fnames.append(self.fname)
|
44
|
+
self.fargs[self.fname] = list()
|
45
|
+
for anode in ast.iter_child_nodes(node.args):
|
46
|
+
self.fargs[self.fname].append(anode.arg)
|
47
|
+
self.cvars[self.fname] = list()
|
48
|
+
for bodynode in node.body:
|
49
|
+
if isinstance(bodynode, ast.Return):
|
50
|
+
continue # skip function's Return node
|
51
|
+
for bnode in ast.walk(bodynode):
|
52
|
+
if isinstance(bnode, ast.Name):
|
53
|
+
if isinstance(bnode.ctx, ast.Store):
|
54
|
+
if bnode.id not in self.cvars[self.fname]:
|
55
|
+
self.cvars[self.fname].append(bnode.id)
|
56
|
+
self.generic_visit(node)
|
57
|
+
|
58
|
+
def visit_Return(self, node): # pylint: disable=invalid-name
|
59
|
+
"""
|
60
|
+
visit the specified Return node
|
61
|
+
"""
|
62
|
+
if isinstance(node.value, ast.Tuple):
|
63
|
+
self.rvars[self.fname] = [r_v.id for r_v in node.value.elts]
|
64
|
+
elif isinstance(node.value, ast.BinOp):
|
65
|
+
self.rvars[self.fname] = [] # no vars returned; only an expression
|
66
|
+
else:
|
67
|
+
self.rvars[self.fname] = [node.value.id]
|
68
|
+
self.generic_visit(node)
|
69
|
+
|
70
|
+
|
71
|
+
def test_calc_and_used_vars(tests_path):
|
72
|
+
"""
|
73
|
+
Runs two kinds of tests on variables used in the calcfunctions.py file:
|
74
|
+
|
75
|
+
(1) Checks that each var in Records.CALCULATED_VARS is actually calculated
|
76
|
+
|
77
|
+
If test (1) fails, a variable in Records.CALCULATED_VARS was not
|
78
|
+
calculated in any function in the calcfunctions.py file. With the
|
79
|
+
exception of a few variables listed in this test, all
|
80
|
+
Records.CALCULATED_VARS must be calculated in the calcfunctions.py file.
|
81
|
+
|
82
|
+
(2) Check that each variable that is calculated in a function and
|
83
|
+
returned by that function is an argument of that function.
|
84
|
+
"""
|
85
|
+
# pylint: disable=too-many-locals
|
86
|
+
funcpath = os.path.join(tests_path, '..', 'calcfunctions.py')
|
87
|
+
gfd = GetFuncDefs()
|
88
|
+
fnames, fargs, cvars, rvars = gfd.visit(ast.parse(open(funcpath).read()))
|
89
|
+
# Test (1):
|
90
|
+
# .. create set of vars that are actually calculated in calcfunctions.py
|
91
|
+
all_cvars = set()
|
92
|
+
for fname in fnames:
|
93
|
+
if fname == 'BenefitSurtax':
|
94
|
+
continue # because BenefitSurtax is not really a function
|
95
|
+
all_cvars.update(set(cvars[fname]))
|
96
|
+
# .. add to all_cvars set variables calculated in Records class
|
97
|
+
all_cvars.update(set(['num', 'sep', 'exact']))
|
98
|
+
# .. add to all_cvars set variables calculated elsewhere
|
99
|
+
all_cvars.update(set(['mtr_paytax', 'mtr_inctax']))
|
100
|
+
all_cvars.update(set(['benefit_cost_total', 'benefit_value_total']))
|
101
|
+
# .. check that each var in Records.CALCULATED_VARS is in the all_cvars set
|
102
|
+
records_varinfo = Records(data=None)
|
103
|
+
found_error1 = False
|
104
|
+
if not records_varinfo.CALCULATED_VARS <= all_cvars:
|
105
|
+
msg1 = ('all Records.CALCULATED_VARS not calculated '
|
106
|
+
'in calcfunctions.py\n')
|
107
|
+
for var in records_varinfo.CALCULATED_VARS - all_cvars:
|
108
|
+
found_error1 = True
|
109
|
+
msg1 += 'VAR NOT CALCULATED: {}\n'.format(var)
|
110
|
+
# Test (2):
|
111
|
+
faux_functions = ['EITCamount', 'ComputeBenefit', 'BenefitPrograms',
|
112
|
+
'BenefitSurtax', 'BenefitLimitation']
|
113
|
+
found_error2 = False
|
114
|
+
msg2 = 'calculated & returned variables are not function arguments\n'
|
115
|
+
for fname in fnames:
|
116
|
+
if fname in faux_functions:
|
117
|
+
continue # because fname is not a genuine function
|
118
|
+
crvars_set = set(cvars[fname]) & set(rvars[fname])
|
119
|
+
if not crvars_set <= set(fargs[fname]):
|
120
|
+
found_error2 = True
|
121
|
+
for var in crvars_set - set(fargs[fname]):
|
122
|
+
msg2 += 'FUNCTION,VARIABLE: {} {}\n'.format(fname, var)
|
123
|
+
# Report errors for the two tests:
|
124
|
+
if found_error1 and found_error2:
|
125
|
+
raise ValueError('{}\n{}'.format(msg1, msg2))
|
126
|
+
if found_error1:
|
127
|
+
raise ValueError(msg1)
|
128
|
+
if found_error2:
|
129
|
+
raise ValueError(msg2)
|
130
|
+
|
131
|
+
|
132
|
+
def test_function_args_usage(tests_path):
|
133
|
+
"""
|
134
|
+
Checks each function argument in calcfunctions.py for use in its
|
135
|
+
function body.
|
136
|
+
"""
|
137
|
+
funcfilename = os.path.join(tests_path, '..', 'calcfunctions.py')
|
138
|
+
with open(funcfilename, 'r') as funcfile:
|
139
|
+
fcontent = funcfile.read()
|
140
|
+
fcontent = re.sub('#.*', '', fcontent) # remove all '#...' comments
|
141
|
+
fcontent = re.sub('\n', ' ', fcontent) # replace EOL character with space
|
142
|
+
funcs = fcontent.split('def ') # list of function text
|
143
|
+
msg = 'FUNCTION ARGUMENT(S) NEVER USED:\n'
|
144
|
+
found_error = False
|
145
|
+
for func in funcs[1:]: # skip first item in list, which is imports, etc.
|
146
|
+
fcode = func.split('return ')[0] # fcode is between def and return
|
147
|
+
match = re.search(r'^(.+?)\((.*?)\):(.*)$', fcode)
|
148
|
+
if match is None:
|
149
|
+
msg = ('Could not find function name, arguments, '
|
150
|
+
'and code portions in the following text:\n')
|
151
|
+
msg += '--------------------------------------------------------\n'
|
152
|
+
msg += '{}\n'.format(fcode)
|
153
|
+
msg += '--------------------------------------------------------\n'
|
154
|
+
raise ValueError(msg)
|
155
|
+
fname = match.group(1)
|
156
|
+
fargs = match.group(2).split(',') # list of function arguments
|
157
|
+
fbody = match.group(3)
|
158
|
+
if fname == 'Taxes':
|
159
|
+
continue # because Taxes has part of fbody in return statement
|
160
|
+
for farg in fargs:
|
161
|
+
arg = farg.strip()
|
162
|
+
if fbody.find(arg) < 0:
|
163
|
+
found_error = True
|
164
|
+
msg += 'FUNCTION,ARGUMENT= {} {}\n'.format(fname, arg)
|
165
|
+
if found_error:
|
166
|
+
raise ValueError(msg)
|
167
|
+
|
168
|
+
|
169
|
+
def test_DependentCare(skip_jit):
|
170
|
+
"""
|
171
|
+
Tests the DependentCare function
|
172
|
+
"""
|
173
|
+
|
174
|
+
test_tuple = (3, 2, 100000, 1, [250000, 500000, 250000, 500000, 250000],
|
175
|
+
.2, 7165, 5000, 0)
|
176
|
+
test_value = calcfunctions.DependentCare(*test_tuple)
|
177
|
+
expected_value = 25196
|
178
|
+
|
179
|
+
assert np.allclose(test_value, expected_value)
|
180
|
+
|
181
|
+
|
182
|
+
STD_in = [6000, 12000, 6000, 12000, 12000]
|
183
|
+
STD_Aged_in = [1500, 1200, 1500, 1500, 1500]
|
184
|
+
Charity_max_in = [300, 600, 300, 300, 300]
|
185
|
+
tuple1 = (0, 1000, STD_in, 45, 44, STD_Aged_in, 1000, 2, 0, 0, 0, 2,
|
186
|
+
False, 0, 0, 0, Charity_max_in)
|
187
|
+
tuple2 = (0, 1000, STD_in, 66, 44, STD_Aged_in, 1000, 2, 0, 1, 1, 2,
|
188
|
+
True, 200, 100000, 1, Charity_max_in)
|
189
|
+
tuple3 = (0, 1000, STD_in, 44, 66, STD_Aged_in, 1000, 2, 0, 0, 0, 2,
|
190
|
+
True, 700, 100000, 1, Charity_max_in)
|
191
|
+
tuple4 = (0, 1200, STD_in, 66, 67, STD_Aged_in, 1000, 2, 0, 0, 0, 2,
|
192
|
+
True, 0, 100000, 1, Charity_max_in)
|
193
|
+
tuple5 = (0, 1000, STD_in, 44, 0, STD_Aged_in, 1000, 1, 0, 0, 0, 2,
|
194
|
+
True, 0, 100000, 1, Charity_max_in)
|
195
|
+
tuple6 = (0, 1000, STD_in, 44, 0, STD_Aged_in, 1000, 1, 0, 0, 0, 2,
|
196
|
+
True, 0, 100000, 1, Charity_max_in)
|
197
|
+
tuple7 = (0, 1000, STD_in, 44, 0, STD_Aged_in, 1000, 3, 1, 0, 0, 2,
|
198
|
+
True, 0, 100000, 1, Charity_max_in)
|
199
|
+
tuple8 = (1, 200, STD_in, 44, 0, STD_Aged_in, 1000, 3, 0, 0, 0, 2,
|
200
|
+
True, 0, 100000, 1, Charity_max_in)
|
201
|
+
tuple9 = (1, 1000, STD_in, 44, 0, STD_Aged_in, 1000, 3, 0, 0, 0, 2,
|
202
|
+
True, 0,100000, 1, Charity_max_in)
|
203
|
+
expected = [12000, 15800, 13800, 14400, 6000, 6000, 0, 1000, 1350]
|
204
|
+
|
205
|
+
|
206
|
+
@pytest.mark.stded
|
207
|
+
@pytest.mark.parametrize(
|
208
|
+
'test_tuple,expected_value', [
|
209
|
+
(tuple1, expected[0]), (tuple2, expected[1]),
|
210
|
+
(tuple3, expected[2]), (tuple4, expected[3]),
|
211
|
+
(tuple5, expected[4]), (tuple6, expected[5]),
|
212
|
+
(tuple7, expected[6]), (tuple8, expected[7]),
|
213
|
+
(tuple9, expected[8])], ids=[
|
214
|
+
'Married, young', 'Married, allow charity',
|
215
|
+
'Married, allow charity, over limit',
|
216
|
+
'Married, two old', 'Single 1', 'Single 2', 'Married, Single',
|
217
|
+
'Marrid, Single, dep, under earn',
|
218
|
+
'Married, Single, dep, over earn'])
|
219
|
+
def test_StdDed(test_tuple, expected_value, skip_jit):
|
220
|
+
"""
|
221
|
+
Tests the StdDed function
|
222
|
+
"""
|
223
|
+
avalue = calcfunctions.StdDed(*test_tuple)
|
224
|
+
assert np.allclose(avalue, expected_value), f"{avalue} != {expected_value}"
|
225
|
+
|
226
|
+
|
227
|
+
tuple1 = (120000, 10000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 99999999999,
|
228
|
+
400, 0, 0, 0, 0, 0, 0, None, None, None, None, None, None,
|
229
|
+
None, None, None, None, None)
|
230
|
+
tuple2 = (120000, 10000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 99999999999,
|
231
|
+
400, 2000, 0, 10000, 0, 0, 3000, None, None, None, None, None,
|
232
|
+
None, None, None, None, None, None)
|
233
|
+
tuple3 = (120000, 150000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 99999999999,
|
234
|
+
400, 2000, 0, 10000, 0, 0, 3000, None, None, None, None, None,
|
235
|
+
None, None, None, None, None, None)
|
236
|
+
tuple4 = (120000, 500000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 400000,
|
237
|
+
400, 2000, 0, 10000, 0, 0, 3000, None, None, None, None, None,
|
238
|
+
None, None, None, None, None, None)
|
239
|
+
tuple5 = (120000, 10000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 99999999999,
|
240
|
+
400, 300, 0, 0, 0, 0, 0, None, None, None, None, None,
|
241
|
+
None, None, None, None, None, None)
|
242
|
+
tuple6 = (120000, 10000, 15000, 100, 2000, 0.06, 0.06, 0.015, 0.015, 0, 99999999999,
|
243
|
+
400, 0, 0, 0, 0, -40000, 0, None, None, None, None, None,
|
244
|
+
None, None, None, None, None, None)
|
245
|
+
expected1 = (0, 4065, 4065, 0, 0, 3252, 25000, 10000, 15000, 10100,
|
246
|
+
17000)
|
247
|
+
expected2 = (15000, 6146.25, 4065, 2081.25, 1040.625, 4917, 38959.375,
|
248
|
+
21167.5, 17791.875, 21380, 19820)
|
249
|
+
expected3 = (15000, 22202.25, 21453, 749.25, 374.625, 16773, 179625.375,
|
250
|
+
161833.5, 17791.875, 161380, 19820)
|
251
|
+
expected4 = (15000, 46067.85, 31953, 749.25, 374.625, 30138.6,
|
252
|
+
529625.375, 511833.5, 17791.875, 511380, 19820)
|
253
|
+
expected5 = (300, 4065, 4065, 0, 0, 3285.3, 25300, 10279.1875, 15000,
|
254
|
+
10382, 17000)
|
255
|
+
expected6 = (-40000, 4065, 4065, 0, 0, 3252, 0, 0, 15000, 10100, 17000)
|
256
|
+
|
257
|
+
@pytest.mark.parametrize(
|
258
|
+
'test_tuple,expected_value', [
|
259
|
+
(tuple1, expected1),
|
260
|
+
(tuple2, expected2),
|
261
|
+
(tuple3, expected3),
|
262
|
+
(tuple4, expected4),
|
263
|
+
(tuple5, expected5),
|
264
|
+
(tuple6, expected6)], ids=[
|
265
|
+
'case 1', 'case 2', 'case 3', 'case 4', 'case 5', 'case 6'])
|
266
|
+
def test_EI_PayrollTax(test_tuple, expected_value, skip_jit):
|
267
|
+
"""
|
268
|
+
Tests the EI_PayrollTax function
|
269
|
+
"""
|
270
|
+
test_value = calcfunctions.EI_PayrollTax(*test_tuple)
|
271
|
+
print('Test value = ', test_value)
|
272
|
+
|
273
|
+
assert np.allclose(test_value, expected_value)
|
274
|
+
|
275
|
+
|
276
|
+
def test_AfterTaxIncome(skip_jit):
|
277
|
+
'''
|
278
|
+
Tests the AfterTaxIncome function
|
279
|
+
'''
|
280
|
+
test_tuple = (1000, 5000, 4000)
|
281
|
+
test_value = calcfunctions.AfterTaxIncome(*test_tuple)
|
282
|
+
expected_value = 4000
|
283
|
+
assert np.allclose(test_value, expected_value)
|
284
|
+
|
285
|
+
|
286
|
+
def test_ExpandIncome(skip_jit):
|
287
|
+
'''
|
288
|
+
Tests the ExpandIncome function
|
289
|
+
'''
|
290
|
+
test_tuple = (10000, 1000, 500, 100, 200, 300, 400, 20, 500, 50, 250, 10,
|
291
|
+
20, 30, 40, 60, 70, 80, 1500, 2000, 16380)
|
292
|
+
test_value = calcfunctions.ExpandIncome(*test_tuple)
|
293
|
+
expected_value = 16380
|
294
|
+
assert np.allclose(test_value, expected_value)
|
295
|
+
|
296
|
+
|
297
|
+
tuple1 = (1, 1, 2, 0, 0, 1000)
|
298
|
+
tuple2 = (0, 1, 2, 0, 0, 1000)
|
299
|
+
tuple3 = (1, 1, 2, 100, 0, 1000)
|
300
|
+
tuple4 = (0, 2, 1, 100, 200, 1000)
|
301
|
+
tuple5 = (0, 1, 3, 100, 300, 1000)
|
302
|
+
expected1 = (0, 1000)
|
303
|
+
expected2 = (0, 1000)
|
304
|
+
expected3 = (0, 1000)
|
305
|
+
expected4 = (200, 1200)
|
306
|
+
expected5 = (300, 1300)
|
307
|
+
|
308
|
+
|
309
|
+
@pytest.mark.parametrize(
|
310
|
+
'test_tuple,expected_value', [
|
311
|
+
(tuple1, expected1), (tuple2, expected2), (tuple3, expected3),
|
312
|
+
(tuple4, expected4), (tuple5, expected5)])
|
313
|
+
def test_LumpSumTax(test_tuple, expected_value, skip_jit):
|
314
|
+
'''
|
315
|
+
Tests LumpSumTax function
|
316
|
+
'''
|
317
|
+
test_value = calcfunctions.LumpSumTax(*test_tuple)
|
318
|
+
assert np.allclose(test_value, expected_value)
|
319
|
+
|
320
|
+
|
321
|
+
FST_AGI_thd_lo_in = [1000000, 1000000, 500000, 1000000, 1000000]
|
322
|
+
FST_AGI_thd_hi_in = [2000000, 2000000, 1000000, 2000000, 2000000]
|
323
|
+
tuple1 = (1100000, 1, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
|
324
|
+
FST_AGI_thd_hi_in, 100, 200, 2000, 300)
|
325
|
+
tuple2 = (2100000, 1, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
|
326
|
+
FST_AGI_thd_hi_in, 100, 200, 2000, 300)
|
327
|
+
tuple3 = (1100000, 1, 1000, 100, 100, 0, FST_AGI_thd_lo_in,
|
328
|
+
FST_AGI_thd_hi_in, 100, 200, 2000, 300)
|
329
|
+
tuple4 = (1100000, 2, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
|
330
|
+
FST_AGI_thd_hi_in, 100, 200, 2000, 300)
|
331
|
+
tuple5 = (2100000, 2, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
|
332
|
+
FST_AGI_thd_hi_in, 100, 200, 2000, 300)
|
333
|
+
tuple6 = (1100000, 2, 1000, 100, 100, 0, FST_AGI_thd_lo_in,
|
334
|
+
FST_AGI_thd_hi_in, 100, 200, 2000, 300)
|
335
|
+
tuple7 = (510000, 3, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
|
336
|
+
FST_AGI_thd_hi_in, 100, 200, 2000, 300)
|
337
|
+
tuple8 = (1100000, 3, 1000, 100, 100, 0.1, FST_AGI_thd_lo_in,
|
338
|
+
FST_AGI_thd_hi_in, 100, 200, 2000, 300)
|
339
|
+
tuple9 = (510000, 3, 1000, 100, 100, 0, FST_AGI_thd_lo_in,
|
340
|
+
FST_AGI_thd_hi_in, 100, 200, 2000, 300)
|
341
|
+
expected1 = (10915, 11115, 12915, 11215)
|
342
|
+
expected2 = (209150, 209350, 211150, 209450)
|
343
|
+
expected3 = (0, 200, 2000, 300)
|
344
|
+
expected4 = (10915, 11115, 12915, 11215)
|
345
|
+
expected5 = (209150, 209350, 211150, 209450)
|
346
|
+
expected6 = (0, 200, 2000, 300)
|
347
|
+
expected7 = (1003, 1203, 3003, 1303)
|
348
|
+
expected8 = (109150, 109350, 111150, 109450)
|
349
|
+
expected9 = (0, 200, 2000, 300)
|
350
|
+
|
351
|
+
|
352
|
+
@pytest.mark.parametrize(
|
353
|
+
'test_tuple,expected_value', [
|
354
|
+
(tuple1, expected1), (tuple2, expected2), (tuple3, expected3),
|
355
|
+
(tuple4, expected4), (tuple5, expected5), (tuple6, expected6),
|
356
|
+
(tuple7, expected7), (tuple8, expected8), (tuple9, expected9)])
|
357
|
+
def test_FairShareTax(test_tuple, expected_value, skip_jit):
|
358
|
+
'''
|
359
|
+
Tests FairShareTax function
|
360
|
+
'''
|
361
|
+
test_value = calcfunctions.FairShareTax(*test_tuple)
|
362
|
+
assert np.allclose(test_value, expected_value)
|
363
|
+
|
364
|
+
|
365
|
+
II_credit_ARPA = [0, 0, 0, 0, 0]
|
366
|
+
II_credit_ps_ARPA = [0, 0, 0, 0, 0]
|
367
|
+
II_credit_nr_ARPA = [0, 0, 0, 0, 0]
|
368
|
+
II_credit_nr_ps_ARPA = [0, 0, 0, 0, 0]
|
369
|
+
RRC_ps_ARPA = [75000, 150000, 75000, 112500, 150000]
|
370
|
+
RRC_pe_ARPA = [80000, 160000, 80000, 120000, 160000]
|
371
|
+
RRC_c_unit_ARPA = [0, 0, 0, 0, 0]
|
372
|
+
II_credit_CARES = [0, 0, 0, 0, 0]
|
373
|
+
II_credit_ps_CARES = [0, 0, 0, 0, 0]
|
374
|
+
II_credit_nr_CARES = [0, 0, 0, 0, 0]
|
375
|
+
II_credit_nr_ps_CARES = [0, 0, 0, 0, 0]
|
376
|
+
RRC_ps_CARES = [75000, 150000, 75000, 112500, 75000]
|
377
|
+
RRC_pe_CARES = [0, 0, 0, 0, 0]
|
378
|
+
RRC_c_unit_CARES = [1200, 2400, 1200, 1200, 1200]
|
379
|
+
tuple1 = (1, 50000, 1, 0, II_credit_ARPA, II_credit_ps_ARPA, 0,
|
380
|
+
II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
|
381
|
+
RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
|
382
|
+
tuple2 = (1, 76000, 1, 0, II_credit_ARPA, II_credit_ps_ARPA, 0,
|
383
|
+
II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
|
384
|
+
RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
|
385
|
+
tuple3 = (1, 90000, 1, 0, II_credit_ARPA, II_credit_ps_ARPA, 0,
|
386
|
+
II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
|
387
|
+
RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
|
388
|
+
tuple4 = (2, 50000, 3, 1, II_credit_ARPA, II_credit_ps_ARPA, 0,
|
389
|
+
II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
|
390
|
+
RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
|
391
|
+
tuple5 = (2, 155000, 4, 2, II_credit_ARPA, II_credit_ps_ARPA, 0,
|
392
|
+
II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
|
393
|
+
RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
|
394
|
+
tuple6 = (2, 170000, 4, 2, II_credit_ARPA, II_credit_ps_ARPA, 0,
|
395
|
+
II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
|
396
|
+
RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
|
397
|
+
tuple7 = (4, 50000, 2, 1, II_credit_ARPA, II_credit_ps_ARPA, 0,
|
398
|
+
II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
|
399
|
+
RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
|
400
|
+
tuple8 = (4, 117000, 1, 0, II_credit_ARPA, II_credit_ps_ARPA, 0,
|
401
|
+
II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
|
402
|
+
RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
|
403
|
+
tuple9 = (4, 130000, 1, 0, II_credit_ARPA, II_credit_ps_ARPA, 0,
|
404
|
+
II_credit_nr_ARPA, II_credit_nr_ps_ARPA, 0, 1400, RRC_ps_ARPA,
|
405
|
+
RRC_pe_ARPA, 0, 0, RRC_c_unit_ARPA, 0, 0, 0)
|
406
|
+
tuple10 = (1, 50000, 1, 0, II_credit_CARES, II_credit_ps_CARES, 0,
|
407
|
+
II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
|
408
|
+
RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
|
409
|
+
tuple11 = (1, 97000, 2, 1, II_credit_CARES, II_credit_ps_CARES, 0,
|
410
|
+
II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
|
411
|
+
RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
|
412
|
+
tuple12 = (1, 150000, 2, 1, II_credit_CARES, II_credit_ps_CARES, 0,
|
413
|
+
II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
|
414
|
+
RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
|
415
|
+
tuple13 = (2, 50000, 4, 2, II_credit_CARES, II_credit_ps_CARES, 0,
|
416
|
+
II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
|
417
|
+
RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
|
418
|
+
tuple14 = (2, 160000, 5, 3, II_credit_CARES, II_credit_ps_CARES, 0,
|
419
|
+
II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
|
420
|
+
RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
|
421
|
+
tuple15 = (2, 300000, 2, 0, II_credit_CARES, II_credit_ps_CARES, 0,
|
422
|
+
II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
|
423
|
+
RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
|
424
|
+
tuple16 = (4, 50000, 3, 2, II_credit_CARES, II_credit_ps_CARES, 0,
|
425
|
+
II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
|
426
|
+
RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
|
427
|
+
tuple17 = (4, 130000, 2, 1, II_credit_CARES, II_credit_ps_CARES, 0,
|
428
|
+
II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
|
429
|
+
RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
|
430
|
+
tuple18 = (4, 170000, 3, 2, II_credit_CARES, II_credit_ps_CARES, 0,
|
431
|
+
II_credit_nr_CARES, II_credit_nr_ps_CARES, 0, 0, RRC_ps_CARES,
|
432
|
+
RRC_pe_CARES, 0.05, 500, RRC_c_unit_CARES, 0, 0, 0)
|
433
|
+
expected1 = (0, 0, 1400)
|
434
|
+
expected2 = (0, 0, 1120)
|
435
|
+
expected3 = (0, 0, 0)
|
436
|
+
expected4 = (0, 0, 4200)
|
437
|
+
expected5 = (0, 0, 2800)
|
438
|
+
expected6 = (0, 0, 0)
|
439
|
+
expected7 = (0, 0, 2800)
|
440
|
+
expected8 = (0, 0, 560)
|
441
|
+
expected9 = (0, 0, 0)
|
442
|
+
expected10 = (0, 0, 1200)
|
443
|
+
expected11 = (0, 0, 600)
|
444
|
+
expected12 = (0, 0, 0)
|
445
|
+
expected13 = (0, 0, 3400)
|
446
|
+
expected14 = (0, 0, 3400)
|
447
|
+
expected15 = (0, 0, 0)
|
448
|
+
expected16 = (0, 0, 2200)
|
449
|
+
expected17 = (0, 0, 825)
|
450
|
+
expected18 = (0, 0, 0)
|
451
|
+
|
452
|
+
|
453
|
+
@pytest.mark.parametrize(
|
454
|
+
'test_tuple,expected_value', [
|
455
|
+
(tuple1, expected1), (tuple2, expected2), (tuple3, expected3),
|
456
|
+
(tuple4, expected4), (tuple5, expected5), (tuple6, expected6),
|
457
|
+
(tuple7, expected7), (tuple8, expected8), (tuple9, expected9),
|
458
|
+
(tuple10, expected10), (tuple11, expected11), (tuple12, expected12),
|
459
|
+
(tuple13, expected13), (tuple14, expected14), (tuple15, expected15),
|
460
|
+
(tuple16, expected16), (tuple17, expected17), (tuple18, expected18)])
|
461
|
+
def test_PersonalTaxCredit(test_tuple, expected_value, skip_jit):
|
462
|
+
"""
|
463
|
+
Tests the PersonalTaxCredit function
|
464
|
+
"""
|
465
|
+
test_value = calcfunctions.PersonalTaxCredit(*test_tuple)
|
466
|
+
assert np.allclose(test_value, expected_value)
|
467
|
+
|
468
|
+
|
469
|
+
# MARS = 4
|
470
|
+
# Kids = 3+
|
471
|
+
basic_frac = 0.0
|
472
|
+
phasein_rate = 0.45
|
473
|
+
earnings = 19330
|
474
|
+
max_amount = 6660
|
475
|
+
phaseout_start = 19330
|
476
|
+
agi = 19330
|
477
|
+
phaseout_rate = 0.2106
|
478
|
+
tuple1 = (basic_frac, phasein_rate, earnings, max_amount,
|
479
|
+
phaseout_start, agi, phaseout_rate)
|
480
|
+
expected1 = 6660
|
481
|
+
|
482
|
+
|
483
|
+
@pytest.mark.parametrize(
|
484
|
+
'test_tuple,expected_value', [
|
485
|
+
(tuple1, expected1)])
|
486
|
+
def test_EITCamount(test_tuple, expected_value, skip_jit):
|
487
|
+
'''
|
488
|
+
Tests FairShareTax function
|
489
|
+
'''
|
490
|
+
test_value = calcfunctions.EITCamount(*test_tuple)
|
491
|
+
assert np.allclose(test_value, expected_value)
|
492
|
+
|
493
|
+
|
494
|
+
MARS = 4
|
495
|
+
DSI = 0
|
496
|
+
EIC = 3
|
497
|
+
c00100 = 19330
|
498
|
+
e00300 = 0
|
499
|
+
e00400 = 0
|
500
|
+
e00600 = 0
|
501
|
+
c01000 = 0
|
502
|
+
e02000 = 0
|
503
|
+
e26270 = 0
|
504
|
+
age_head = 0
|
505
|
+
age_spouse = 0
|
506
|
+
earned = 19330
|
507
|
+
earned_p = 19330
|
508
|
+
earned_s = 0
|
509
|
+
EITC_ps = [8790, 19330, 19330, 19330]
|
510
|
+
EITC_MinEligAge = 25
|
511
|
+
EITC_MaxEligAge = 64
|
512
|
+
EITC_ps_MarriedJ = [5890, 5890, 5890, 5890]
|
513
|
+
EITC_rt = [0.0765, 0.34, 0.4, 0.45]
|
514
|
+
EITC_c = [538, 3584, 5920, 6660]
|
515
|
+
EITC_prt = [0.0765, 0.1598, 0.2106, 0.2106]
|
516
|
+
EITC_basic_frac = 0.0
|
517
|
+
EITC_InvestIncome_c = 3650
|
518
|
+
EITC_excess_InvestIncome_rt = 9e+99
|
519
|
+
EITC_indiv = False
|
520
|
+
EITC_sep_filers_elig = False
|
521
|
+
e02300 = 10200
|
522
|
+
UI_thd = [150000, 150000, 150000, 150000, 150000]
|
523
|
+
UI_em = 10200
|
524
|
+
c59660 = 0 # this will be 6660 after the EITC calculation
|
525
|
+
tuple1 = (MARS, DSI, EIC, c00100, e00300, e00400, e00600, c01000,
|
526
|
+
e02000, e26270, age_head, age_spouse, earned, earned_p, earned_s,
|
527
|
+
EITC_ps, EITC_MinEligAge, EITC_MaxEligAge, EITC_ps_MarriedJ,
|
528
|
+
EITC_rt, EITC_c, EITC_prt, EITC_basic_frac,
|
529
|
+
EITC_InvestIncome_c, EITC_excess_InvestIncome_rt,
|
530
|
+
EITC_indiv, EITC_sep_filers_elig, c59660)
|
531
|
+
expected1 = 6660
|
532
|
+
|
533
|
+
|
534
|
+
@pytest.mark.parametrize(
|
535
|
+
'test_tuple,expected_value', [
|
536
|
+
(tuple1, expected1)])
|
537
|
+
def test_EITC(test_tuple, expected_value, skip_jit):
|
538
|
+
'''
|
539
|
+
Tests FairShareTax function
|
540
|
+
'''
|
541
|
+
test_value = calcfunctions.EITC(*test_tuple)
|
542
|
+
assert np.allclose(test_value, expected_value)
|
543
|
+
|
544
|
+
|
545
|
+
# Parameter values for tests
|
546
|
+
PT_qbid_rt = 0.2
|
547
|
+
PT_qbid_taxinc_thd = [160700.0, 321400.0, 160725.0, 160700.0, 321400.0]
|
548
|
+
PT_qbid_taxinc_gap = [50000.0, 100000.0, 50000.0, 50000.0, 100000.0]
|
549
|
+
PT_qbid_w2_wages_rt = 0.5
|
550
|
+
PT_qbid_alt_w2_wages_rt = 0.25
|
551
|
+
PT_qbid_alt_property_rt = 0.025
|
552
|
+
PT_qbid_ps = [9e99, 9e99, 9e99, 9e99, 9e99]
|
553
|
+
PT_qbid_prt = 0.0
|
554
|
+
PT_qbid_limit_switch = True # will want to test with False also
|
555
|
+
|
556
|
+
# Input variable values for tests
|
557
|
+
c00100 = [527860.66, 337675.10, 603700.00, 90700.00]
|
558
|
+
standard = [0.00, 0.00, 24400.00, 0.00]
|
559
|
+
c04470 = [37000.00, 49000.00, 0.00, 32000.00]
|
560
|
+
c04600 = [0.00, 0.00, 0.00, 0.00]
|
561
|
+
MARS = [2, 2, 2, 4]
|
562
|
+
e00900 = [352000.00, 23000.00, 0.00, 0.00]
|
563
|
+
c03260 = [13516.17, 1624.90, 0.00, 0.00]
|
564
|
+
e26270 = [0.00, 0.00, 11000.00, 6000.00]
|
565
|
+
e02100 = [0.00, 0.00, 0.00, 0.00]
|
566
|
+
e27200 = [0.00, 0.00, 0.00, 0.00]
|
567
|
+
e00650 = [5000.00, 8000.00, 3000.00, 9000.00]
|
568
|
+
c01000 = [7000.00, 4000.00, -3000.00, -3000.00]
|
569
|
+
PT_SSTB_income = [0, 1, 1, 1]
|
570
|
+
PT_binc_w2_wages = [0.00, 0.00, 0.00, 0.00]
|
571
|
+
PT_ubia_property = [0.00, 0.00, 0.00, 0.00]
|
572
|
+
c04800 = [0.0, 0.0, 0.0, 0.0] # unimportant for function
|
573
|
+
qbided = [0.0, 0.0, 0.0, 0.0] # unimportant for function
|
574
|
+
|
575
|
+
tuple0 = (
|
576
|
+
c00100[0], standard[0], c04470[0], c04600[0], MARS[0], e00900[0],
|
577
|
+
c03260[0], e26270[0],
|
578
|
+
e02100[0], e27200[0], e00650[0], c01000[0], PT_SSTB_income[0],
|
579
|
+
PT_binc_w2_wages[0], PT_ubia_property[0], PT_qbid_rt,
|
580
|
+
PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
|
581
|
+
PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[0],
|
582
|
+
PT_qbid_ps, PT_qbid_prt, qbided[0], PT_qbid_limit_switch)
|
583
|
+
expected0 = (490860.66, 0)
|
584
|
+
tuple1 = (
|
585
|
+
c00100[1], standard[1], c04470[1], c04600[1], MARS[1], e00900[1],
|
586
|
+
c03260[1], e26270[1],
|
587
|
+
e02100[1], e27200[1], e00650[1], c01000[1], PT_SSTB_income[1],
|
588
|
+
PT_binc_w2_wages[1], PT_ubia_property[1], PT_qbid_rt,
|
589
|
+
PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
|
590
|
+
PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[1],
|
591
|
+
PT_qbid_ps, PT_qbid_prt, qbided[1], PT_qbid_limit_switch)
|
592
|
+
expected1 = (284400.08, 4275.02)
|
593
|
+
tuple2 = (
|
594
|
+
c00100[2], standard[2], c04470[2], c04600[2], MARS[2], e00900[2],
|
595
|
+
c03260[2], e26270[2],
|
596
|
+
e02100[2], e27200[2], e00650[2], c01000[2], PT_SSTB_income[2],
|
597
|
+
PT_binc_w2_wages[2], PT_ubia_property[2], PT_qbid_rt,
|
598
|
+
PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
|
599
|
+
PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[2],
|
600
|
+
PT_qbid_ps, PT_qbid_prt, qbided[2], PT_qbid_limit_switch)
|
601
|
+
expected2 = (579300.00, 0)
|
602
|
+
tuple3 = (
|
603
|
+
c00100[3], standard[3], c04470[3], c04600[3], MARS[3], e00900[3],
|
604
|
+
c03260[3], e26270[3],
|
605
|
+
|
606
|
+
e02100[3], e27200[3], e00650[3], c01000[3], PT_SSTB_income[3],
|
607
|
+
PT_binc_w2_wages[3], PT_ubia_property[3], PT_qbid_rt,
|
608
|
+
PT_qbid_taxinc_thd, PT_qbid_taxinc_gap, PT_qbid_w2_wages_rt,
|
609
|
+
PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt, c04800[3],
|
610
|
+
PT_qbid_ps, PT_qbid_prt, qbided[3], PT_qbid_limit_switch)
|
611
|
+
expected3 = (57500.00, 1200)
|
612
|
+
|
613
|
+
|
614
|
+
@pytest.mark.parametrize(
|
615
|
+
'test_tuple,expected_value', [
|
616
|
+
(tuple0, expected0),
|
617
|
+
(tuple1, expected1),
|
618
|
+
(tuple2, expected2),
|
619
|
+
(tuple3, expected3)])
|
620
|
+
def test_TaxInc(test_tuple, expected_value, skip_jit):
|
621
|
+
"""
|
622
|
+
Tests the TaxInc function
|
623
|
+
"""
|
624
|
+
test_value = calcfunctions.TaxInc(*test_tuple)
|
625
|
+
assert np.allclose(test_value, expected_value)
|
626
|
+
|
627
|
+
|
628
|
+
# parameterization represents 2021 law
|
629
|
+
age_head = 45
|
630
|
+
age_spouse = 0
|
631
|
+
nu18 = 0
|
632
|
+
n24 = 0
|
633
|
+
MARS = 4
|
634
|
+
c00100 = 1000
|
635
|
+
XTOT = 3
|
636
|
+
num = 1
|
637
|
+
c05800 = 0
|
638
|
+
e07260 = 0
|
639
|
+
CR_ResidentialEnergy_hc = 0.0
|
640
|
+
e07300 = 0
|
641
|
+
CR_ForeignTax_hc = 0.0
|
642
|
+
c07180 = 0
|
643
|
+
c07230 = 0
|
644
|
+
e07240 = 0
|
645
|
+
CR_RetirementSavings_hc = 0.0
|
646
|
+
c07200 = 0
|
647
|
+
CTC_c = 2000
|
648
|
+
CTC_ps = [200000.0, 400000.0, 200000.0, 200000.0, 400000.0]
|
649
|
+
CTC_prt = 0.05
|
650
|
+
exact = False
|
651
|
+
ODC_c = 500
|
652
|
+
CTC_c_under6_bonus = 0.0
|
653
|
+
nu06 = 0
|
654
|
+
CTC_refundable = True
|
655
|
+
CTC_include17 = True
|
656
|
+
c07220 = 0 # actual value will be returned from function
|
657
|
+
odc = 0 # actual value will be returned from function
|
658
|
+
codtc_limited = 0 # actual value will be returned from function
|
659
|
+
tuple0 = (
|
660
|
+
age_head, age_spouse, nu18, n24, MARS, c00100, XTOT, num,
|
661
|
+
c05800, e07260, CR_ResidentialEnergy_hc,
|
662
|
+
e07300, CR_ForeignTax_hc,
|
663
|
+
c07180,
|
664
|
+
c07230,
|
665
|
+
e07240, CR_RetirementSavings_hc,
|
666
|
+
c07200,
|
667
|
+
CTC_c, CTC_ps, CTC_prt, exact, ODC_c,
|
668
|
+
CTC_c_under6_bonus, nu06,
|
669
|
+
CTC_refundable, CTC_include17,
|
670
|
+
c07220, odc, codtc_limited)
|
671
|
+
# output tuple is : (c07220, odc, codtc_limited)
|
672
|
+
expected0 = (0, 1000, 0)
|
673
|
+
|
674
|
+
|
675
|
+
@pytest.mark.parametrize(
|
676
|
+
'test_tuple,expected_value', [
|
677
|
+
(tuple0, expected0)])
|
678
|
+
def test_ChildDepTaxCredit_2021(test_tuple, expected_value, skip_jit):
|
679
|
+
"""
|
680
|
+
Tests the ChildDepTaxCredit function
|
681
|
+
"""
|
682
|
+
test_value = calcfunctions.ChildDepTaxCredit(*test_tuple)
|
683
|
+
assert np.allclose(test_value, expected_value)
|
684
|
+
|
685
|
+
# parameterization represents 2022 law
|
686
|
+
age_head = 45
|
687
|
+
age_spouse = 0
|
688
|
+
nu18 = 0
|
689
|
+
n24 = 0
|
690
|
+
MARS = 4
|
691
|
+
c00100 = 1000
|
692
|
+
XTOT = 3
|
693
|
+
num = 1
|
694
|
+
c05800 = 0
|
695
|
+
e07260 = 0
|
696
|
+
CR_ResidentialEnergy_hc = 0.0
|
697
|
+
e07300 = 0
|
698
|
+
CR_ForeignTax_hc = 0.0
|
699
|
+
c07180 = 0
|
700
|
+
c07230 = 0
|
701
|
+
e07240 = 0
|
702
|
+
CR_RetirementSavings_hc = 0.0
|
703
|
+
c07200 = 0
|
704
|
+
CTC_c = 2000
|
705
|
+
CTC_ps = [200000.0, 400000.0, 200000.0, 200000.0, 400000.0]
|
706
|
+
CTC_prt = 0.05
|
707
|
+
exact = False
|
708
|
+
ODC_c = 500
|
709
|
+
CTC_c_under6_bonus = 0.0
|
710
|
+
nu06 = 0
|
711
|
+
CTC_refundable = False
|
712
|
+
CTC_include17 = False
|
713
|
+
c07220 = 0 # actual value will be returned from function
|
714
|
+
odc = 0 # actual value will be returned from function
|
715
|
+
codtc_limited = 0 # actual value will be returned from function
|
716
|
+
tuple0 = (
|
717
|
+
age_head, age_spouse, nu18, n24, MARS, c00100, XTOT, num,
|
718
|
+
c05800, e07260, CR_ResidentialEnergy_hc,
|
719
|
+
e07300, CR_ForeignTax_hc,
|
720
|
+
c07180,
|
721
|
+
c07230,
|
722
|
+
e07240, CR_RetirementSavings_hc,
|
723
|
+
c07200,
|
724
|
+
CTC_c, CTC_ps, CTC_prt, exact, ODC_c,
|
725
|
+
CTC_c_under6_bonus, nu06,
|
726
|
+
CTC_refundable, CTC_include17,
|
727
|
+
c07220, odc, codtc_limited)
|
728
|
+
# output tuple is : (c07220, odc, codtc_limited)
|
729
|
+
expected0 = (0, 0, 1000)
|
730
|
+
|
731
|
+
|
732
|
+
@pytest.mark.parametrize(
|
733
|
+
'test_tuple,expected_value', [
|
734
|
+
(tuple0, expected0)])
|
735
|
+
def test_ChildDepTaxCredit_2022(test_tuple, expected_value, skip_jit):
|
736
|
+
"""
|
737
|
+
Tests the ChildDepTaxCredit function
|
738
|
+
"""
|
739
|
+
test_value = calcfunctions.ChildDepTaxCredit(*test_tuple)
|
740
|
+
assert np.allclose(test_value, expected_value)
|
741
|
+
|
742
|
+
# parameterization represents 2021 law
|
743
|
+
CTC_new_c = 1000
|
744
|
+
CTC_new_rt = 0
|
745
|
+
CTC_new_c_under6_bonus = 600
|
746
|
+
CTC_new_ps = [75000, 150000, 75000, 125000, 150000]
|
747
|
+
CTC_new_prt = 0.05
|
748
|
+
CTC_new_for_all = True
|
749
|
+
CTC_include17 = True
|
750
|
+
CTC_new_refund_limited = False
|
751
|
+
CTC_new_refund_limit_payroll_rt = 0.0
|
752
|
+
CTC_new_refund_limited_all_payroll = False
|
753
|
+
payrolltax = 0
|
754
|
+
exact = 0
|
755
|
+
n24 = 0
|
756
|
+
nu06 = 0
|
757
|
+
age_head = 45
|
758
|
+
age_spouse = 0
|
759
|
+
nu18 = 0
|
760
|
+
num = 1
|
761
|
+
c00100 = 1000
|
762
|
+
MARS = 4
|
763
|
+
ptax_oasdi = 0
|
764
|
+
c09200 = 0
|
765
|
+
ctc_new = 0 # actual value will be returned from function
|
766
|
+
tuple0 = (
|
767
|
+
CTC_new_c, CTC_new_rt, CTC_new_c_under6_bonus,
|
768
|
+
CTC_new_ps, CTC_new_prt, CTC_new_for_all, CTC_include17,
|
769
|
+
CTC_new_refund_limited, CTC_new_refund_limit_payroll_rt,
|
770
|
+
CTC_new_refund_limited_all_payroll, payrolltax, exact,
|
771
|
+
n24, nu06, age_head, age_spouse, nu18, c00100, MARS, ptax_oasdi,
|
772
|
+
c09200, ctc_new)
|
773
|
+
# output tuple is : (ctc_new)
|
774
|
+
expected0 = (0)
|
775
|
+
|
776
|
+
@pytest.mark.parametrize(
|
777
|
+
'test_tuple,expected_value', [
|
778
|
+
(tuple0, expected0)])
|
779
|
+
def test_CTCnew_2021(test_tuple, expected_value, skip_jit):
|
780
|
+
"""
|
781
|
+
Tests the CTCnew function
|
782
|
+
"""
|
783
|
+
test_value = calcfunctions.CTC_new(*test_tuple)
|
784
|
+
assert np.allclose(test_value, expected_value)
|
785
|
+
|
786
|
+
# parameterization represents 2022 law
|
787
|
+
CTC_new_c = 0
|
788
|
+
CTC_new_rt = 0
|
789
|
+
CTC_new_c_under6_bonus = 0
|
790
|
+
CTC_new_ps = [0, 0, 0, 0, 0]
|
791
|
+
CTC_new_prt = 0
|
792
|
+
CTC_new_for_all = False
|
793
|
+
CTC_include17 = False
|
794
|
+
CTC_new_refund_limited = False
|
795
|
+
CTC_new_refund_limit_payroll_rt = 0.0
|
796
|
+
CTC_new_refund_limited_all_payroll = False
|
797
|
+
payrolltax = 0
|
798
|
+
exact = 0
|
799
|
+
n24 = 0
|
800
|
+
nu06 = 0
|
801
|
+
age_head = 45
|
802
|
+
age_spouse = 0
|
803
|
+
nu18 = 0
|
804
|
+
num = 1
|
805
|
+
c00100 = 1000
|
806
|
+
MARS = 4
|
807
|
+
ptax_oasdi = 0
|
808
|
+
c09200 = 0
|
809
|
+
ctc_new = 0 # actual value will be returned from function
|
810
|
+
tuple0 = (
|
811
|
+
CTC_new_c, CTC_new_rt, CTC_new_c_under6_bonus,
|
812
|
+
CTC_new_ps, CTC_new_prt, CTC_new_for_all, CTC_include17,
|
813
|
+
CTC_new_refund_limited, CTC_new_refund_limit_payroll_rt,
|
814
|
+
CTC_new_refund_limited_all_payroll, payrolltax, exact,
|
815
|
+
n24, nu06, age_head, age_spouse, nu18, c00100, MARS, ptax_oasdi,
|
816
|
+
c09200, ctc_new)
|
817
|
+
# output tuple is : (ctc_new)
|
818
|
+
expected0 = (0)
|
819
|
+
|
820
|
+
@pytest.mark.parametrize(
|
821
|
+
'test_tuple,expected_value', [
|
822
|
+
(tuple0, expected0)])
|
823
|
+
def test_CTCnew_2022(test_tuple, expected_value, skip_jit):
|
824
|
+
"""
|
825
|
+
Tests the CTCnew function
|
826
|
+
"""
|
827
|
+
test_value = calcfunctions.CTC_new(*test_tuple)
|
828
|
+
assert np.allclose(test_value, expected_value)
|
829
|
+
|
830
|
+
|
831
|
+
|
832
|
+
ymod1 = 19330 + 10200
|
833
|
+
c02500 = 0
|
834
|
+
c02900 = 0
|
835
|
+
XTOT = 0
|
836
|
+
MARS = 4
|
837
|
+
sep = 1
|
838
|
+
DSI = 0
|
839
|
+
exact = False
|
840
|
+
nu18 = 0
|
841
|
+
taxable_ubi = 0
|
842
|
+
II_em = 0.0
|
843
|
+
II_em_ps = [9e+99, 9e+99, 9e+99, 9e+99, 9e+99]
|
844
|
+
II_prt = 0.02
|
845
|
+
II_no_em_nu18 = False
|
846
|
+
e02300 = 10200
|
847
|
+
UI_thd = [150000, 150000, 150000, 150000, 150000]
|
848
|
+
UI_em = 10200
|
849
|
+
c00100 = 0 # calculated in function
|
850
|
+
pre_c04600 = 0 # calculated in functio
|
851
|
+
c04600 = 0 # calculated in functio
|
852
|
+
|
853
|
+
tuple0 = (
|
854
|
+
ymod1, c02500, c02900, XTOT, MARS, sep, DSI, exact, nu18, taxable_ubi,
|
855
|
+
II_em, II_em_ps, II_prt, II_no_em_nu18,
|
856
|
+
e02300, UI_thd, UI_em, c00100, pre_c04600, c04600)
|
857
|
+
# returned tuple is (c00100, pre_c04600, c04600)
|
858
|
+
expected0 = (19330, 0, 0)
|
859
|
+
|
860
|
+
|
861
|
+
@pytest.mark.parametrize(
|
862
|
+
'test_tuple,expected_value', [
|
863
|
+
(tuple0, expected0)])
|
864
|
+
def test_AGI(test_tuple, expected_value, skip_jit):
|
865
|
+
"""
|
866
|
+
Tests the TaxInc function
|
867
|
+
"""
|
868
|
+
test_value = calcfunctions.AGI(*test_tuple)
|
869
|
+
print('Returned from agi function: ', test_value)
|
870
|
+
assert np.allclose(test_value, expected_value)
|
871
|
+
|