def test_div(): acc_data = AccountData(data_path1) acc_data_div = acc_data / 2 assert (sum(acc_data.get_column("amount")) / 2 == sum( acc_data_div.get_column("amount"))) assert (len(acc_data.get_data()) == len(acc_data_div.get_data()))
def test_update(): account_data1 = AccountData("./example_data/data1.csv", tag_file="./example_data/tags_nested.json") account_data2 = AccountData("./example_data/data2.csv", account_name="other_data") summed_account = account_data1 / 2 + account_data2 summed_account.update("./example_data/data_new.csv", "data1") #Old and new data should be available #Old data summed_account.filter_data("date", "==", datetime.date(2021, 1, 1)) assert (summed_account.get_column("text") == [ "Lorem Ipsum", "Lorem Ipsum" ]) summed_account.reset_filter() #New data summed_account.filter_data("date", "==", datetime.date(2021, 1, 5)) assert (summed_account.get_column("text") == ["A1", "SWISH FRÅN Namn"]) summed_account.reset_filter() #Overlapping data should be updated summed_account.filter_data("date", "==", datetime.date(2021, 1, 4)) assert (summed_account.get_column("text") == [ '201229 A1', '201230 A3 ', '210101 B1', '210102 a4', 'Updated data' ]) #Last one is the new data (not reliable so change if it starts failing) #summed_account.filter_data("account" == "other_data") assert (summed_account.get_column("amount")[-1] == 333.33 / 2) summed_account.reset_filter()
def test_save_load(tmp_path): acc_data = AccountData(data_path1, tag_file=tag_nested_path) acc_data.save(tmp_path / "test_save_load_data.csv") acc_data_loaded = AccountData(tmp_path / "test_save_load_data.csv") #Saving and loading should not affect data acc_data._expenses == acc_data_loaded._expenses acc_data._daterange == acc_data_loaded._daterange
def test_get_data__is_sorted(): #Everything should sorted ascending by the first column (date) after initialization acc_data1 = AccountData(data_path1) all_data = acc_data1.get_data() last_date = all_data[0][0] for data in all_data[1:]: assert (data[0] >= last_date) last_date = data[0]
def test_filter__type_wrong(): acc_data1 = AccountData(data_path1, cat_path) with pytest.raises(ValueError): acc_data1.filter_data("amount", "==", "text") with pytest.raises(ValueError): acc_data1.filter_data("date", ">", 2) with pytest.raises(ValueError): acc_data1.filter_data("text", ">", "text") with pytest.raises(ValueError): acc_data1.filter_data("category", "==", datetime.date(2021, 1, 1))
def test_get_total(): acc_data = AccountData(data_path1, tag_path) assert (acc_data.get_total() == -44559.5) acc_data.filter_data("tags", "==", "tag2") assert (acc_data.get_total() == -24560.0) acc_data.filter_data("date", ">", datetime.date(2020, 12, 25)) assert (acc_data.get_total() == 200.0)
def test_add__is_sorted(): #Everything should still be sorted ascending by the first column (date) after adding two account data acc_data1 = AccountData(data_path1) acc_data2 = AccountData(data_path2) sum_data = acc_data1 + acc_data2 all_data = sum_data.get_data() last_date = all_data[0][0] for data in all_data[1:]: assert (data[0] >= last_date) last_date = data[0]
def test_get_timeseries__correct_sum(): #The total expenses should not change acc_data1 = AccountData(data_path2) sum1 = 0 for data in acc_data1.get_data(): sum1 += data[1] sum2 = 0 for data in acc_data1.get_timeseries().data: sum2 += data[1] assert (sum1 == sum2)
def test_get_timeseries(): acc_data2 = AccountData(data_path2) ts = acc_data2.get_timeseries().data #The lenght of the timeseries should be the number of number of days between first and last day of data 1 assert (len(ts) == 26) #All dates should be present between the first and the last, an only occur once last_date = ts[0][0] for data in ts[1:]: assert (last_date + datetime.timedelta(1) == data[0]) last_date = data[0]
def test_reset_filter(): acc_data1 = AccountData(data_path1, cat_path) original_data = acc_data1.get_data() acc_data1.filter_data("amount", "==", 1000) filtered_data = acc_data1.get_data() acc_data1.reset_filter() reset_data = acc_data1.get_data() assert (original_data == reset_data) assert (reset_data != filtered_data)
def test_filter__empty(): #If filtering twice with an inverted filter the result should be empty acc_data = AccountData(data_path1, cat_path) acc_data.filter_data("amount", ">=", 300) acc_data.filter_data("amount", "<", 300) assert (len(acc_data.get_data()) == 0) #Tags should also be empty assert (len(acc_data.get_tags()) == 0) #It should be possible to still call get_timeseries() assert (type(acc_data.get_timeseries()) == TimeSeries)
def test_get_average(): acc_data = AccountData(data_path1) total_expenses = sum([data[1] for data in acc_data.get_data()]) days = (acc_data.get_data()[-1][0] - acc_data.get_data()[0][0]).days + 1 assert (acc_data.get_average("Day") == total_expenses / days) assert (acc_data.get_average("Week") == sum( [data[1] for data in acc_data.get_data()[1:-1]]) / 3)
def test_update__daterange(): account_data1 = AccountData("./example_data/data1.csv", tag_file="./example_data/tags_nested.json") account_data2 = AccountData("./example_data/data2.csv", account_name="other_data") summed_account = account_data1 + account_data2 / 2 old_range = summed_account._daterange summed_account.update("./example_data/data_new.csv", "other_data") new_range = summed_account._daterange #Start date is same assert (old_range[0] == new_range[0]) #New date range is longer however assert (old_range[1] < new_range[1])
def test_filter__amount(fun): acc_data1 = AccountData(data_path1, cat_path) acc_data1.filter_data("amount", fun, 200) for amount in acc_data1.get_column("amount"): if fun == ">": assert (amount > 200) elif fun == ">=": assert (amount >= 200) elif fun == "==": assert (amount == 200) elif fun == "!=": assert (amount != 200) elif fun == "<=": assert (amount <= 200) elif fun == "<": assert (amount < 200)
def test_filter__date(): acc_data1 = AccountData(data_path1, cat_path) first_date = acc_data1.get_column("date")[0] next_date = acc_data1.get_column("date")[1] acc_data1.filter_data("date", ">", first_date) assert (acc_data1.get_column("date")[0] == next_date)
def test_div__property(): acc_data1 = AccountData(data_path1, tag_nested_path) acc_data2 = AccountData(data_path2, tag_nested_path, account_name="other_data") summed_account = acc_data1 + acc_data2 / 2 #Use the account name to get the scale of the account, either using the file name, or account name if given assert (summed_account.get_scale("data1") == 1) assert (summed_account.get_scale("other_data") == 1 / 2) amount_col = summed_account.columns["amount"] amount_unscaled = summed_account.columns["amount_unscaled"] account_col = summed_account.columns["account"] assert ( summed_account.get_data()[0][amount_col] == summed_account.get_data()[0][amount_unscaled] * summed_account.get_scale(summed_account.get_data()[0][account_col]))
def test_add(): acc_data1 = AccountData(data_path1, tag_nested_path) acc_data2 = AccountData(data_path2, tag_nested_path) sum_data = acc_data1 + acc_data2 #Categories should not change since both acc_data use the same tag file, though order may change (so sorting it) assert (sorted(list(acc_data1.get_tags())) == sorted( list(sum_data.get_tags()))) #Length of get_data should be the sum of both assert (len(sum_data.get_data()) == len(acc_data1.get_data()) + len(acc_data2.get_data()))
def test_get_data(): acc_data1 = AccountData(data_path1) #Check that data corresponds to the first entry assert (acc_data1.get_data()[0][acc_data1.columns['amount']] == 100) #And that lenght is correct assert (len(acc_data1.get_data()) == 19)
def test_filter__type_ok(): acc_data1 = AccountData(data_path1, cat_path) acc_data1.filter_data("amount", ">", 100) acc_data1.filter_data("amount", ">", 200.5) acc_data1.filter_data("text", "!=", "test") acc_data1.filter_data("date", ">", datetime.date(2021, 1, 4))
def test_filter__tags(): acc_data = AccountData(data_path1, tag_file=tag_path) acc_data.filter_data("tags", "!=", "tag1") assert ("tag1" not in acc_data.get_tags()) acc_data.filter_data("tags", "==", "tag3") assert (acc_data.get_tags() == ["tag3"])
def test_filter__multi_tags(): #If a data point has multiple tags, those tags should be preserved acc_data = AccountData(data_path1, tag_file=tag_path) acc_data.filter_data("tags", "==", "överföring") assert (len(acc_data.get_tags()) > 1)
def test_get_average__empty(): #Should return 0 if there is no data acc_data = AccountData(data_path1, tag_nested_path) acc_data.filter_data("tags", "==", "Non-existing") assert (acc_data.get_average("Day") == 0)
def test_update__save_load(tmp_path): account_data1 = AccountData("./example_data/data1.csv", tag_file="./example_data/tags_nested.json") account_data2 = AccountData("./example_data/data2.csv", account_name="other_data") summed_account = account_data1 / 2 + account_data2 summed_account.update("./example_data/data_new.csv", "data1") #Save and load should not affect data summed_account.save(tmp_path / "account_data.csv") summed_account = AccountData(tmp_path / "account_data.csv") #Old data summed_account.filter_data("date", "==", datetime.date(2021, 1, 1)) assert (summed_account.get_column("text") == [ 'Lorem Ipsum', 'Lorem Ipsum' ]) summed_account.reset_filter() #New data summed_account.filter_data("date", "==", datetime.date(2021, 1, 5)) assert (summed_account.get_column("text") == ['A1', 'SWISH FRÅN Namn']) summed_account.reset_filter() #Overlapping data should be updated summed_account.filter_data("date", "==", datetime.date(2021, 1, 4)) assert (summed_account.get_column("text") == [ '201229 A1', '201230 A3 ', '210101 B1', '210102 a4', 'Updated data' ]) summed_account.filter_data("account", "==", "data1") assert (summed_account.get_column("amount") == [333.33 / 2]) summed_account.reset_filter()
def test_filter__tag_list_order(): acc_data = AccountData(data_path1, tag_file=tag_path) #If the order of the tags is different, then it should still yield the same result acc_data.filter_data("tags", "==", ["överföring", "tag1"]) #Should only contain the once that contains all the tags. assert (sorted(acc_data.get_tags()) == sorted(["tag1", "överföring"]))
def test_get_tags_level(): acc_data = AccountData(data_path1, tag_file=tag_nested_path) assert (acc_data.get_tags("==", 0) == ["tag2", "tagABC"]) assert (acc_data.get_tags(">=", 1) == ["B23", "B", "A", "B1"]) #Since there are only 2 levels, getting all levels that are less than 3 should give back all tags assert (acc_data.get_tags("<", 3) == acc_data.get_tags())
def test_get_tags(): acc_data = AccountData(data_path1, tag_file=tag_path) assert (sorted( acc_data.get_tags()) == ["tag1", "tag2", "tag3", "överföring"])
def test_init(): acc_data1 = AccountData(data_path1) acc_data2 = AccountData(data_path2, tag_nested_path)
def test_get_average__filtered(): acc_data = AccountData(data_path1, tag_path) #If we filter by something by other than date, we should still accumulate to the full extent of the data acc_data.filter_data("tags", "==", "tag2") assert (acc_data.get_average("Day") == sum(acc_data.get_column("amount")) / 26) #If filter by date, accumulate should only be within the filtered dates acc_data.reset_filter() acc_data.filter_data("date", ">", datetime.date(2020, 12, 13)) acc_data.filter_data("date", "<=", datetime.date(2020, 12, 20)) assert (acc_data.get_average("Week") == (1000 + 100 - 25000) / 1) #The filter function should detect if the date filter is greater than the data and it should affect the average acc_data.reset_filter() acc_data.filter_data("date", ">=", datetime.date(2020, 12, 7)) acc_data.filter_data("date", "<", datetime.date(2020, 12, 23)) assert (acc_data.get_average("Week") == (1000 + 100 - 25000) / 1)
import matplotlib.pyplot as plt import matplotlib.dates as mdates import datetime import math from homeplotter.accountdata import AccountData tag_file = "./data/personal_tags.json" account_data1 = AccountData("./data/old/konto_gemensamt.csv", tag_file=tag_file) account_data2 = AccountData("./data/old/konto_personligt.csv") account_data3 = AccountData("./data/old/konto_ica.csv") summed_account = (account_data1 / 2) + account_data2 + (account_data3 / 2) start_date = datetime.date(2021, 2, 1) def create_plot(tag, output_path, acc_delta="Month"): summed_account.reset_filter() if tag != "Alla" and tag != "Överskott eller Underskottt": summed_account.filter_data("tags", "==", tag) else: summed_account.filter_data("tags", "!=", "Reservation") summed_account.filter_data("tags", "!=", "Överföring") if tag == "Alla": summed_account.filter_data("tags", "!=", "Lön") summed_account.filter_data("date", ">=", start_date) plt.cla() tsdata = summed_account.get_timeseries() tsdata.accumulate(1, acc_delta) plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y'))
def test_filter__tag_list(): acc_data = AccountData(data_path1, tag_file=tag_path) acc_data.filter_data("tags", "==", ["tag1", "överföring"]) #Should only contain the once that contains all the tags. assert (sorted(acc_data.get_tags()) == sorted(["tag1", "överföring"]))