Skip to content

Commit 1105419

Browse files
Add test for Utah state tax reform (#2418)
* Add test for Utah state tax reform Fixes #2417 * Move test * Fix data input * Fix test * chore: Add docs * Ensure the job saves correctly * Adjust test after running locally to check * Add test for loser share --------- Co-authored-by: Anthony Volk <anth.volk@gmail.com>
1 parent 6a9dfda commit 1105419

4 files changed

Lines changed: 132 additions & 0 deletions

File tree

changelog_entry.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- bump: patch
2+
changes:
3+
added:
4+
- Utah state tax reform test.

policyengine_api/jobs/calculate_economy_simulation_job.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,23 @@ def run(
151151

152152
# Kick off APIv2 job
153153
if use_api_v2:
154+
data = None
155+
v2_region = region
156+
if data == "enhanced_cps":
157+
data = "gs://policyengine-us-data/enhanced_cps_2024.h5"
158+
elif country_id == "us" and region != "us":
159+
data = (
160+
"gs://policyengine-us-data/pooled_3_year_cps_2023.h5"
161+
)
162+
v2_region = "state/" + region
154163
input_data = {
155164
"country": country_id,
156165
"scope": "macro",
157166
"reform": json.loads(reform_policy),
158167
"baseline": json.loads(baseline_policy),
159168
"time_period": time_period,
169+
"region": v2_region,
170+
"data": data,
160171
}
161172
execution = self.api_v2.run(input_data)
162173

tests/data/utah_reform.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"data": {
3+
"gov.states.ut.tax.income.rate": {
4+
"2025-01-01.2100-12-31": 0.0455
5+
},
6+
"gov.states.ut.tax.income.credits.ctc.child_age_threshold[0].amount": {
7+
"2025-01-01.2100-12-31": false
8+
},
9+
"gov.states.ut.tax.income.credits.ctc.child_age_threshold[2].threshold": {
10+
"2025-01-01.2100-12-31": 5
11+
},
12+
"gov.states.ut.tax.income.credits.ss_benefits.phase_out.threshold.JOINT": {
13+
"2025-01-01.2100-12-31": 75000
14+
},
15+
"gov.states.ut.tax.income.credits.ss_benefits.phase_out.threshold.SINGLE": {
16+
"2025-01-01.2100-12-31": 45000
17+
},
18+
"gov.states.ut.tax.income.credits.ss_benefits.phase_out.threshold.SEPARATE": {
19+
"2025-01-01.2100-12-31": 37500
20+
},
21+
"gov.states.ut.tax.income.credits.ss_benefits.phase_out.threshold.SURVIVING_SPOUSE": {
22+
"2025-01-01.2100-12-31": 75000
23+
},
24+
"gov.states.ut.tax.income.credits.ss_benefits.phase_out.threshold.HEAD_OF_HOUSEHOLD": {
25+
"2025-01-01.2100-12-31": 75000
26+
}
27+
}
28+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import json
2+
import time
3+
import datetime
4+
from policyengine_api.data import local_database
5+
import sys
6+
7+
# This test is a temporary test to ensure state impacts work properly.
8+
# It should be replaced with more comprehensive integration tests, then removed.
9+
10+
11+
def test_utah(rest_client):
12+
"""
13+
Test that the a given Utah policy is calculated
14+
and provides logical outputs for a sim
15+
"""
16+
17+
return utah_reform_runner(rest_client, "ut")
18+
19+
20+
def utah_reform_runner(rest_client, region: str = "us"):
21+
"""
22+
Run the given Utah policy test, depending on provided
23+
region (defaults to "us")
24+
"""
25+
26+
test_year = 2025
27+
default_policy = 2
28+
29+
with open(
30+
"./tests/data/utah_reform.json",
31+
"r",
32+
encoding="utf-8",
33+
) as f:
34+
data_object = json.load(f)
35+
36+
local_database.query("DELETE FROM reform_impact WHERE country_id = 'us'")
37+
38+
policy_create = rest_client.post(
39+
"/us/policy",
40+
headers={"Content-Type": "application/json"},
41+
json=data_object,
42+
)
43+
44+
assert policy_create.status_code in [200, 201]
45+
assert policy_create.json["result"] is not None
46+
47+
policy_id = policy_create.json["result"]["policy_id"]
48+
assert policy_id is not None
49+
50+
query = f"/us/economy/{policy_id}/over/{default_policy}?region={region}&time_period={test_year}"
51+
economy_response = rest_client.get(query)
52+
assert economy_response.status_code == 200
53+
assert economy_response.json["status"] == "computing", (
54+
f'Expected first answer status to be "computing" but it is '
55+
f'{str(economy_response.json["status"])}'
56+
)
57+
while economy_response.json["status"] == "computing":
58+
print("Before sleep:", datetime.datetime.now())
59+
time.sleep(3)
60+
print("After sleep:", datetime.datetime.now())
61+
economy_response = rest_client.get(query)
62+
print(json.dumps(economy_response.json))
63+
assert (
64+
economy_response.json["status"] == "ok"
65+
), f'Expected status "ok", got {economy_response.json["status"]} with message "{economy_response.json}"'
66+
67+
result = economy_response.json["result"]
68+
69+
assert result is not None
70+
71+
# Ensure that there is some budgetary impact
72+
cost = round(result["budget"]["budgetary_impact"] / 1e6, 1)
73+
assert (
74+
cost / 95.4 - 1
75+
) < 0.01, (
76+
f"Expected budgetary impact to be 95.4 million, got {cost} million"
77+
)
78+
79+
assert (
80+
result["intra_decile"]["all"]["Lose less than 5%"] / 0.622 - 1
81+
) < 0.01, (
82+
f"Expected 62.2% of people to lose less than 5%, got "
83+
f"{result['intra_decile']['all']['Lose less than 5%']}"
84+
)
85+
86+
local_database.query(
87+
f"DELETE FROM policy WHERE id = ? ",
88+
(policy_id,),
89+
)

0 commit comments

Comments
 (0)