landuse / tests /test_app.py
danyoung's picture
Added app
6d95c4c
raw
history blame
8.02 kB
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)