def test_spreadsheet_with_misconfigured_income_columns(self):
     """
     Test a spreadsheet that doesn't have the column
     headers that were set in config.ini. Having a required
     field set in the config.ini that doesn't exist in the
     corresponding .csv, should throw an assertion error.
     """
     config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')
     config.required_income_columns = set(['Foo', 'Bar'])
     self.assertRaises(AssertionError, SavingsRate, config)
    def test_load_account_config_without_ini(self):
        """
        Test the loading of account_config.ini.
        """
        # Load the config
        config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')

        # Unset the conf_dir path so the account_config.ini won't be found
        config.user_conf_dir = ''

        self.assertRaises(FileNotFoundError, config.load_account_config_from_ini)
Beispiel #3
0
    def test_load_account_config_without_ini(self):
        """
        Test the loading of account_config.ini.
        """
        # Load the config
        config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')

        # Unset the conf_dir path so the account_config.ini won't be found
        config.user_conf_dir = ''

        self.assertRaises(FileNotFoundError,
                          config.load_account_config_from_ini)
    def test_clean_num(self):
        config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')
        sr = SavingsRate(config)

        val1 = sr.clean_num('')
        val2 = sr.clean_num('     ')
        val3 = sr.clean_num(None)
        val4 = sr.clean_num(4)
        val5 = sr.clean_num(4.4)
        val6 = sr.clean_num(Decimal(4.4))

        self.assertRaises(TypeError, sr.clean_num, 'Son of Mogh')
        self.assertRaises(TypeError, sr.clean_num, '4.4')
        self.assertEqual(
            val1, 0.0
        ), 'An empty string should evaluate to 0.0. It evaluated to ' + str(
            val1)
        self.assertEqual(
            val2, 0.0
        ), 'An empty string should evaluate to 0.0. It evaluated to ' + str(
            val2)
        self.assertEqual(
            val3,
            0.0), 'None should evaluate to 0.0. It evaluated to ' + str(val3)
        self.assertEqual(
            val4, 4), '4 should evaluate to 4.4. It evaluated to ' + str(val4)
        self.assertEqual(
            val5,
            4.4), '4.4 should evaluate to 4.4. It evaluated to ' + str(val5)
        self.assertEqual(
            val6, Decimal(4.4)
        ), '4.4 should evaluate to Decimal(4.4). It evaluated to ' + str(val6)
    def test_get_monthly_savings_rates_0_0(self):
        """
        %0 SR each month, %0 average
        """
        config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')
        sr = SavingsRate(config)

        md = OrderedDict()
        md['2015-01'] = {
            'income': [Decimal(0.0)],
            'employer_match': [Decimal(0.0)],
            'taxes_and_fees': [Decimal(0.0)],
            'savings': [Decimal(0.0)]
        }
        md['2015-02'] = {
            'income': [Decimal(0.0)],
            'employer_match': [Decimal(0.0)],
            'taxes_and_fees': [Decimal(0.0)],
            'savings': [Decimal(0.0)]
        }

        r4 = sr.get_monthly_savings_rates(test_data=md)
        for item4 in r4:
            self.assertEqual(item4[1], Decimal(0.0), \
                'Incorrect savings rate. Calculated: ' + str(item4[1]))
        average_rates = sr.average_monthly_savings_rates(r4)
        self.assertEqual(average_rates, Decimal(0.0), \
            'Wrong average for monthly rates.')
    def test_get_monthly_savings_rates_25_75(self):
        """
        %25 SR first month, %75 second month, %50 average
        """
        config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')
        sr = SavingsRate(config)

        md3 = OrderedDict()
        md3['2015-01'] = {
            'income': [Decimal(2000.0)],
            'employer_match': [Decimal(200.0)],
            'taxes_and_fees': [Decimal(200.0)],
            'savings': [Decimal(500.0)]
        }
        md3['2015-02'] = {
            'income': [Decimal(2000.0)],
            'employer_match': [Decimal(200.0)],
            'taxes_and_fees': [Decimal(200.0)],
            'savings': [Decimal(1500.0)]
        }

        r3 = sr.get_monthly_savings_rates(test_data=md3)

        self.assertEqual(r3[0][1], Decimal(25), \
            'Incorrect savings rate. Calculated: ' + str(r3[0][1]))
        self.assertEqual(r3[1][1], Decimal(75), \
            'Incorrect savings rate. Calculated: ' + str(r3[1][1]))
        average_rates = sr.average_monthly_savings_rates(r3)
        self.assertEqual(average_rates, Decimal(50.0), \
            'Wrong average for monthly rates.')
Beispiel #7
0
def run():
    """
    Run the application in, "ini" mode.

    Args:
        config_path: string, path to a directory of config 
        .ini files. Should include a trailing "/".
    """
    # Capture commandline arguments. prog='' argument must
    # match the command name in setup.py entry_points
    parser = argparse.ArgumentParser(prog='savingsrates')
    parser.add_argument('-p',
                        nargs='?',
                        help='A path to a directory of config files.')
    args = parser.parse_args()
    inputs = {'p': args.p}
    config_path = inputs['p']

    # Instantiate a savings rate config object
    config = SRConfig('ini', config_path, 'config.ini')

    # Instantiate a savings rate object for a user
    savings_rate = SavingsRate(config)
    monthly_rates = savings_rate.get_monthly_savings_rates()

    # Plot the user's savings rate
    user_plot = Plot(savings_rate)
    user_plot.plot_savings_rates(monthly_rates)
Beispiel #8
0
 def test_load_account_config_without_option(self):
     """
     Load a config option without the required "self" option.
     """
     config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')
     config.account_config.remove_option('Users', 'self')
     self.assertRaises(configparser.NoOptionError,
                       config.account_config.get, 'Users', 'self')
Beispiel #9
0
 def test_load_account_config_without_section(self):
     """
     Load an account config without the required [Users] section.
     """
     config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')
     config.account_config.remove_section('Users')
     self.assertRaises(configparser.NoSectionError,
                       config.account_config.get, 'Users', 'self')
Beispiel #10
0
    def test_load_account_config_without_enemies(self):
        """
        Loading an account_config.ini wout enemies
        shouldn't blow up.
        """
        config = SRConfig('ini', 'tests/test_config/', 'config-test.ini', \
            test=True, test_file='account-config-test-no-enemies.ini')

        self.assertEqual(config.user_enemies, None)
Beispiel #11
0
 def test_required_account_sections(self):
     """
     A missing required section in account-config.ini 
     should throw an assertion error.
     """
     for section in REQUIRED_INI_ACCOUNT_OPTIONS:
         config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')
         config.account_config.remove_section(section)
         self.assertRaises(AssertionError, config.validate_account_ini)
 def test_get_taxes_from_csv(self):
     """
     There should be as many items as commas in 
     the config +1.
     """
     config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')
     sr = SavingsRate(config)
     commas_in_config = config.user_config.get('Sources',
                                               'taxes_and_fees').count(',')
     self.assertEqual(len(sr.get_taxes_from_csv()), commas_in_config + 1)
 def test_blank_csv_files(self):
     """
     The files exist but they are totally blank.
     PROBLEM - this test shouldn't pass but it does.
     At a minimum, test_columns should throw an 
     AssertionError, shouldn't it? What's going on here?
     """
     config = SRConfig('ini', 'tests/test_config/', 'config-test-blank-csv.ini', \
         test=True, test_file='account-config-blank-csv.ini')
     sr = SavingsRate(config)
Beispiel #14
0
 def test_required_user_options(self):
     """
     A missing required option in config.ini 
     should throw an assertion error.
     """
     for section in REQUIRED_INI_USER_OPTIONS:
         for option in REQUIRED_INI_USER_OPTIONS[section]:
             config = SRConfig('ini', 'tests/test_config/',
                               'config-test.ini')
             config.user_config.remove_option(section, option)
             self.assertRaises(AssertionError, config.validate_user_ini)
    def test_empty_csv_files(self):
        """
        The files exist with the proper column headings
        but they don't have any rows populated. This 
        shouldn't blow up.
        """
        config = SRConfig('ini', 'tests/test_config/', 'config-test-empty-csv.ini', \
            test=True, test_file='account-config-empty-csv.ini')
        sr = SavingsRate(config)

        self.assertEqual(sr.income, OrderedDict())
        self.assertEqual(sr.savings, OrderedDict())
Beispiel #16
0
    def test_load_account_config_with_good_ini(self):
        """
        Load a good account-config.ini.
        """
        config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')

        self.assertEqual(len(config.user), 3, \
            'The "self" option in the [Users] section should have an id, name, and path to user config separated by commas.')
        user_ids = set([])
        main_user_id = config.user[0]
        user_ids.add(main_user_id)

        if config.war_mode:
            for enemy in config.user_enemies:
                user_ids.add(enemy[0])
                self.assertEqual(len(enemy), 3, \
                    'If "war" is on. The "enemies" option must be se in the account-config.ini.')
            self.assertEqual(len(user_ids), 3, 'Every user ID must be unique.')
    def test_average_monthly_savings_rates_1_month(self):
        """
        %0 SR each month, %0 average
        """
        config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')
        sr = SavingsRate(config)

        md = OrderedDict()
        md['2015-01'] = {
            'income': [Decimal(2000.0)],
            'employer_match': [Decimal(200.0)],
            'taxes_and_fees': [Decimal(200.0)],
            'savings': [Decimal(500.0)]
        }

        rates = sr.get_monthly_savings_rates(test_data=md)
        average_rates = sr.average_monthly_savings_rates(rates)
        self.assertEqual(average_rates, Decimal(25.0), \
            'Wrong average for monthly rates.')
    def test_data_loaded_by_load_savings_from_csv(self):
        """
        Dates should be in chronological order assuming
        they were entered that way. All required_income_columns
        should be present in the data structure.
        """
        config = SRConfig('ini', 'tests/test_config/', 'config-test.ini')
        sr = SavingsRate(config)

        dates = []
        i = 0
        for d in sr.savings:
            for req in sr.config.required_savings_columns:
                self.assertEqual(req in sr.savings[d], True, \
                    'Missing a field in SavingsRate.savings.')
            dates.append(d)
            if i > 0:
                assert d > dates[i-1], \
                    'Income transaction dates are not in chronological order. Were they entered chronologically?'
            i += 1
Beispiel #19
0
def return_bad_config():
    """
    Return a bad account-config.ini.
    """
    return SRConfig('ini', 'tests/test_config/', 'config-test.ini', \
            test=True, test_file='account-config-test-bad.ini')