Spaces:
Sleeping
Sleeping
import unittest | |
import pandas as pd | |
import json | |
import app.app as app | |
import app.constants as constants | |
import app.utils as utils | |
import app.Prescriptor as Prescriptor | |
class TestUtilFunctions(unittest.TestCase): | |
def setUp(self): | |
self.df = pd.read_csv(constants.DATA_FILE_PATH, index_col=constants.INDEX_COLS) | |
def test_add_nonland(self): | |
""" | |
Simple vanilla test case for add_nonland(). | |
""" | |
data = [0, 0.01, 0.01, 0.2, 0.4, 0.02, 0.03, 0.01, 0.01, 0.05, 0.01, 0.1] | |
series = pd.Series(dict(zip(constants.LAND_USE_COLS, data))) | |
full = utils.add_nonland(series) | |
self.assertAlmostEqual(full["nonland"], 1 - sum(data), delta=constants.SLIDER_PRECISION) | |
def test_add_nonland_sum_over_one(self): | |
""" | |
Makes sure if the columns sum to >1, we get 0 for nonland | |
""" | |
data = [1 for _ in range(len(constants.LAND_USE_COLS))] | |
series = pd.Series(dict(zip(constants.LAND_USE_COLS, data))) | |
full = utils.add_nonland(series) | |
self.assertAlmostEqual(full["nonland"], 0, delta=constants.SLIDER_PRECISION) | |
def test_create_check_options_length(self): | |
values = ["a", "b", "c"] | |
options = utils.create_check_options(values) | |
self.assertEqual(len(options), len(values)) | |
def test_create_check_options_values(self): | |
""" | |
Checks if the values in the options are correct | |
""" | |
values = ["a", "b", "c"] | |
options = utils.create_check_options(values) | |
for i in range(len(options)): | |
self.assertEqual(options[i]["value"], values[i]) | |
def test_compute_percent_change(self): | |
""" | |
Tests compute percent change on standard example. | |
""" | |
context_data = [0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.12] | |
presc_data = [0.10, 0.06, 0.11, 0.05, 0.12, 0.04, 0.13, 0.03, 0.08] | |
context = pd.Series(dict(zip(constants.LAND_USE_COLS, context_data))) | |
presc = pd.Series(dict(zip(constants.RECO_COLS, presc_data))) | |
percent_change = utils.compute_percent_change(context, presc) | |
self.assertAlmostEqual(percent_change, 0.14, delta=constants.SLIDER_PRECISION) | |
def test_compute_percent_change_no_change(self): | |
""" | |
Tests compute percent change when nothing changes. | |
""" | |
context_data = [0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.12] | |
presc_data = context_data[0:6] + context_data [8:11] | |
context = pd.Series(dict(zip(constants.LAND_USE_COLS, context_data))) | |
presc = pd.Series(dict(zip(constants.RECO_COLS, presc_data))) | |
percent_change = utils.compute_percent_change(context, presc) | |
self.assertAlmostEqual(percent_change, 0, delta=constants.SLIDER_PRECISION) | |
def test_compute_percent_change_all_nonreco(self): | |
""" | |
Tests compute change when there is only urban/primf/primn. | |
""" | |
context_data = [0, 0, 0, 0, 0, 0, 0.33, 0.33, 0, 0, 0, 0.34] | |
presc_data = context_data[0:6] + context_data [8:11] | |
context = pd.Series(dict(zip(constants.LAND_USE_COLS, context_data))) | |
presc = pd.Series(dict(zip(constants.RECO_COLS, presc_data))) | |
percent_change = utils.compute_percent_change(context, presc) | |
self.assertEqual(percent_change, 0) | |
def test_compute_percent_change_not_sum_to_one(self): | |
""" | |
Tests compute percent change on a context with some nonland. | |
""" | |
context_data = [0.01 for _ in range(len(constants.LAND_USE_COLS))] | |
presc_data = [0.02, 0.00, 0.02, 0.00, 0.02, 0.00, 0.02, 0.00, 0.01] | |
context = pd.Series(dict(zip(constants.LAND_USE_COLS, context_data))) | |
presc = pd.Series(dict(zip(constants.RECO_COLS, presc_data))) | |
percent_change = utils.compute_percent_change(context, presc) | |
self.assertAlmostEqual(percent_change, 0.333333, delta=constants.SLIDER_PRECISION) | |
class TestEncoder(unittest.TestCase): | |
""" | |
Since the encoded values are somewhat arbitrary based off what the prescriptor | |
is trained on, we have to test based off what is in the fields file. | |
""" | |
def setUp(self): | |
self.df = pd.read_csv(constants.DATA_FILE_PATH, index_col=constants.INDEX_COLS) | |
self.encoder = None | |
self.fields = None | |
with open(constants.FIELDS_PATH, "r") as f: | |
self.fields = json.load(f) | |
self.encoder = utils.Encoder(self.fields) | |
def test_easy_case(self): | |
""" | |
Tests encoding a simple case. | |
""" | |
row = self.df.iloc[[0]] | |
row = row[constants.CONTEXT_COLUMNS] | |
pred = self.encoder.encode_as_df(row) | |
for col in constants.CONTEXT_COLUMNS: | |
range = self.fields[col]["range"] | |
# Min-max scale formula | |
true = (row[col].values[0] - range[0]) / (range[1] - range[0]) | |
self.assertAlmostEqual(pred[col].values[0], true, delta=constants.SLIDER_PRECISION) | |
def test_non_field_cols(self): | |
""" | |
Test that non-field columns are not encoded and excluded from final dataframe. | |
""" | |
row = self.df.iloc[[0]] | |
row = row[constants.CONTEXT_COLUMNS] | |
row["test"] = 999 | |
enc = self.encoder.encode_as_df(row) | |
# Make sure we didn't add the test column | |
self.assertEqual(sorted(list(enc.columns)), sorted(constants.CONTEXT_COLUMNS)) | |
# Make sure we're still encoding | |
true = (row["primf"].values[0] - self.fields["primf"]["range"][0]) / (self.fields["primf"]["range"][1] - self.fields["primf"]["range"][0]) | |
self.assertAlmostEqual(enc["primf"].values[0], true, delta=constants.SLIDER_PRECISION) | |
def test_multiple_input(self): | |
""" | |
Tests we can pass in a multi-row dataframe and get proper encodings. | |
This isn't strictly necessary for our current use case, but it's good to test. | |
""" | |
rows = self.df.iloc[0:2] | |
rows = rows[constants.CONTEXT_COLUMNS] | |
enc = self.encoder.encode_as_df(rows) | |
for col in constants.CONTEXT_COLUMNS: | |
minmax = self.fields[col]["range"] | |
for i in range(len(rows)): | |
val = rows.iloc[i][col] | |
true = (val - minmax[0]) / (minmax[1] - minmax[0]) | |
self.assertAlmostEqual(enc.iloc[i][col], true, delta=constants.SLIDER_PRECISION) | |
class TestPrescriptor(unittest.TestCase): | |
def setUp(self): | |
self.df = pd.read_csv(constants.DATA_FILE_PATH, index_col=constants.INDEX_COLS) | |
pareto_df = pd.read_csv(constants.PARETO_CSV_PATH) | |
self.prescriptor_id_list = list(pareto_df["id"]) | |
def test_load_all_prescriptors(self): | |
""" | |
Checks if all the prescriptors are loadable | |
""" | |
for presc_id in self.prescriptor_id_list: | |
presc = Prescriptor.Prescriptor(presc_id) | |
self.assertNotEqual(presc, None) | |
def test_prescribe_shape(self): | |
""" | |
Tests if the prescribe function outputs something in the right shape | |
""" | |
presc = Prescriptor.Prescriptor(self.prescriptor_id_list[0]) | |
for i in range(1, 10): | |
sample_context_df = self.df.iloc[0:i][constants.CONTEXT_COLUMNS] | |
prescription = presc.run_prescriptor(sample_context_df) | |
self.assertEqual(set(prescription.columns), set(constants.RECO_COLS)) | |
self.assertEqual(len(prescription), i) | |
def test_scale(self): | |
""" | |
Tests if prescriptor properly scales land use back to what it should be. | |
""" | |
presc = Prescriptor.Prescriptor(self.prescriptor_id_list[0]) | |
sample_context_df = self.df.iloc[0:100][constants.CONTEXT_COLUMNS] | |
old_total = sample_context_df[constants.RECO_COLS].sum(axis=1).reset_index(drop=True) | |
prescription = presc.run_prescriptor(sample_context_df) | |
new_total = prescription.sum(axis=1) | |
self.assertEqual(old_total.equals(new_total), True) |