1- # -*- coding: utf-8 -*-
2-
3- from datetime import date
4- from http .client import OK , NOT_FOUND
1+ from http import client
52import json
6- from numpy import where
7- import re
8-
93import pytest
4+ import re
105
11- from openfisca_core .indexed_enums import Enum
12- from openfisca_core .periods import MONTH , ETERNITY
13- from openfisca_core .variables import Variable
14- from openfisca_web_api .app import create_app
15- from .conftest import Person , Household
6+ from openfisca_web_api import app
167
178
189def assert_items_equal (x , y ):
1910 assert set (x ) == set (y )
2011
2112
22- GITHUB_URL_REGEX = r'^https://github\.com/openfisca/openfisca-core /blob/\d+\.\d+\.\d+((.dev|rc)\d+)?/tests/web_api /(.)+\.py#L\d+-L\d+$'
13+ GITHUB_URL_REGEX = r'^https://github\.com/openfisca/country-template /blob/\d+\.\d+\.\d+((.dev|rc)\d+)?/openfisca_country_template/variables /(.)+\.py#L\d+-L\d+$'
2314
2415
2516@pytest .fixture (scope = "module" )
26- def test_client (test_tax_benefit_system ):
27-
28- ###
29- # In this section you define the mock Variables you will need for tests in this module
30- class birth (Variable ):
31- value_type = date
32- default_value = date (1970 , 1 , 1 ) # By default, if no value is set for a simulation, we consider the people involved in a simulation to be born on the 1st of Jan 1970.
33- entity = Person
34- label = "Birth date"
35- definition_period = ETERNITY # This variable cannot change over time.
36- reference = "https://en.wiktionary.org/wiki/birthdate"
37-
38- class income_tax (Variable ):
39- value_type = float
40- entity = Person
41- definition_period = MONTH
42- label = "Income tax"
43- reference = "https://law.gov.example/income_tax" # Always use the most official source
44-
45- def formula (person , period , parameters ):
46- """
47- Income tax.
48-
49- The formula to compute the income tax for a given person at a given period
50- """
51- return person ("salary" , period ) * parameters (period ).taxes .income_tax_rate
52-
53- class age (Variable ):
54- value_type = int
55- entity = Person
56- definition_period = MONTH
57- label = "Person's age (in years)"
58-
59- def formula (person , period , _parameters ):
60- """
61- Person's age (in years).
62-
63- A person's age is computed according to its birth date.
64- """
65- birth = person ("birth" , period )
66- birth_year = birth .astype ("datetime64[Y]" ).astype (int ) + 1970
67- birth_month = birth .astype ("datetime64[M]" ).astype (int ) % 12 + 1
68- birth_day = (birth - birth .astype ("datetime64[M]" ) + 1 ).astype (int )
69-
70- is_birthday_past = (birth_month < period .start .month ) + (birth_month == period .start .month ) * (birth_day <= period .start .day )
71-
72- return (period .start .year - birth_year ) - where (is_birthday_past , 0 , 1 ) # If the birthday is not passed this year, subtract one year
73-
74- class housing_allowance (Variable ):
75- value_type = float
76- entity = Household
77- definition_period = MONTH
78- label = "Housing allowance"
79- reference = "https://law.gov.example/housing_allowance" # Always use the most official source
80- end = "2016-11-30" # This allowance was removed on the 1st of Dec 2016. Calculating it before this date will always return the variable default value, 0.
81- unit = "currency-EUR"
82- documentation = """
83- This allowance was introduced on the 1st of Jan 1980.
84- It disappeared in Dec 2016.
85- """
86-
87- def formula_1980 (household , period , parameters ):
88- """
89- Housing allowance.
90-
91- This allowance was introduced on the 1st of Jan 1980.
92- Calculating it before this date will always return the variable default value, 0.
93-
94- To compute this allowance, the 'rent' value must be provided for the same month,
95- but 'housing_occupancy_status' is not necessary.
96- """
97- return household ("rent" , period ) * parameters (period ).benefits .housing_allowance
98-
99- class HousingOccupancyStatus (Enum ):
100- __order__ = "owner tenant free_lodger homeless"
101- owner = "Owner"
102- tenant = "Tenant"
103- free_lodger = "Free lodger"
104- homeless = "Homeless"
105-
106- class housing_occupancy_status (Variable ):
107- value_type = Enum
108- possible_values = HousingOccupancyStatus
109- default_value = HousingOccupancyStatus .tenant
110- entity = Household
111- definition_period = MONTH
112- label = "Legal housing situation of the household concerning their main residence"
113-
114- class basic_income (Variable ):
115- value_type = float
116- entity = Person
117- definition_period = MONTH
118- label = "Basic income provided to adults"
119- reference = "https://law.gov.example/basic_income" # Always use the most official source
120-
121- def formula_2016_12 (person , period , parameters ):
122- """
123- Basic income provided to adults.
124-
125- Since Dec 1st 2016, the basic income is provided to any adult, without considering their income.
126- """
127- age_condition = person ("age" , period ) >= parameters (period ).general .age_of_majority
128- return age_condition * parameters (period ).benefits .basic_income # This '*' is a vectorial 'if'. See https://openfisca.org/doc/coding-the-legislation/25_vectorial_computing.html#control-structures
129-
130- def formula_2015_12 (person , period , parameters ):
131- """
132- Basic income provided to adults.
133-
134- From Dec 1st 2015 to Nov 30 2016, the basic income is provided to adults who have no income.
135- Before Dec 1st 2015, the basic income does not exist in the law, and calculating it returns its default value, which is 0.
136- """
137- age_condition = person ("age" , period ) >= parameters (period ).general .age_of_majority
138- salary_condition = person ("salary" , period ) == 0
139- return age_condition * salary_condition * parameters (period ).benefits .basic_income # The '*' is also used as a vectorial 'and'. See https://openfisca.org/doc/coding-the-legislation/25_vectorial_computing.html#boolean-operations
140-
141- class pension (Variable ):
142- value_type = float
143- entity = Person
144- definition_period = MONTH
145- label = "Pension for the elderly. Pension attribuée aux personnes âgées. تقاعد."
146- reference = ["https://fr.wikipedia.org/wiki/Retraite_(économie)" , "https://ar.wikipedia.org/wiki/تقاعد" ]
147-
148- def formula (person , period , parameters ):
149- """
150- Pension for the elderly.
151-
152- A person's pension depends on their birth date.
153- In French: retraite selon l'âge.
154- In Arabic: تقاعد.
155- """
156- age_condition = person ("age" , period ) >= parameters (period ).general .age_of_retirement
157- return age_condition
158-
159- ###
160- # Add the Variables above to the `test_tax_benefit_system` fixture
161- test_tax_benefit_system .add_variable (birth )
162- test_tax_benefit_system .add_variable (income_tax )
163- test_tax_benefit_system .add_variable (age )
164- test_tax_benefit_system .add_variable (housing_allowance )
165- test_tax_benefit_system .add_variable (housing_occupancy_status )
166- test_tax_benefit_system .add_variable (basic_income )
167- test_tax_benefit_system .add_variable (pension )
168-
169- ###
17+ def test_client (tax_benefit_system ):
18+ """ This module-scoped fixture creates an API client for the TBS defined in the `tax_benefit_system`
19+ fixture. This `tax_benefit_system` is mutable, so you can add/update variables. Example:
20+
21+ ```
22+ from openfisca_country_template import entities
23+ from openfisca_core import periods
24+ from openfisca_core.variables import Variable
25+ ...
26+
27+ class new_variable(Variable):
28+ value_type = float
29+ entity = entities.Person
30+ definition_period = periods.MONTH
31+ label = "New variable"
32+ reference = "https://law.gov.example/new_variable" # Always use the most official source
33+
34+ tax_benefit_system.add_variable(new_variable)
35+ flask_app = app.create_app(tax_benefit_system)
36+ ```
37+ """
38+
17039 # Create the test API client
171- app = create_app (test_tax_benefit_system )
172- return app .test_client ()
40+ flask_app = app . create_app (tax_benefit_system )
41+ return flask_app .test_client ()
17342
17443
17544# /variables
@@ -182,7 +51,7 @@ def variables_response(test_client):
18251
18352
18453def test_return_code (variables_response ):
185- assert variables_response .status_code == OK
54+ assert variables_response .status_code == client . OK
18655
18756
18857def test_response_data (variables_response ):
@@ -198,7 +67,7 @@ def test_response_data(variables_response):
19867
19968def test_error_code_non_existing_variable (test_client ):
20069 response = test_client .get ('/variable/non_existing_variable' )
201- assert response .status_code == NOT_FOUND
70+ assert response .status_code == client . NOT_FOUND
20271
20372
20473@pytest .fixture (scope = "module" )
@@ -208,7 +77,7 @@ def input_variable_response(test_client):
20877
20978
21079def test_return_code_existing_input_variable (input_variable_response ):
211- assert input_variable_response .status_code == OK
80+ assert input_variable_response .status_code == client . OK
21281
21382
21483def check_input_variable_value (key , expected_value , input_variable = None ):
@@ -238,7 +107,7 @@ def test_input_variable_github_url(test_client):
238107
239108def test_return_code_existing_variable (test_client ):
240109 variable_response = test_client .get ('/variable/income_tax' )
241- assert variable_response .status_code == OK
110+ assert variable_response .status_code == client . OK
242111
243112
244113def check_variable_value (key , expected_value , variable = None ):
@@ -306,7 +175,7 @@ def dated_variable_response(test_client):
306175
307176
308177def test_return_code_existing_dated_variable (dated_variable_response ):
309- assert dated_variable_response .status_code == OK
178+ assert dated_variable_response .status_code == client . OK
310179
311180
312181def test_dated_variable_formulas_dates (dated_variable_response ):
@@ -327,7 +196,7 @@ def test_dated_variable_formulas_content(dated_variable_response):
327196
328197def test_variable_encoding (test_client ):
329198 variable_response = test_client .get ('/variable/pension' )
330- assert variable_response .status_code == OK
199+ assert variable_response .status_code == client . OK
331200
332201
333202def test_variable_documentation (test_client ):
0 commit comments