CSC108-Fall-2022-A2 / a2_checker.py
a2_checker.py
Raw
"""A simple checker for types of functions in mm_functions.py."""

from typing import Any, Dict, Union
import pytest
import checker_generic
import carbon_emissions as ce

FILENAME = 'carbon_emissions.py'
PYTA_CONFIG = 'a2_pythonta.json'
TARGET_LEN = 79
SEP = '='

CONSTANTS = {
    'START_YEAR': 1799,
    'END_YEAR': 2017,
    'EMISSION_FILENAME': 'co2_emissions_per_person.csv',
    'POP_FILENAME': 'populations.csv',
    'G7_COUNTRIES': ['Canada', 'France', 'Germany', 'Italy', 'Japan', 'United Kingdom',
                     'United States']
}

NUMBER_TYPE = (float, int)


class TestChecker:
    """Sanity checker for assignment functions."""

    def test_convert_population(self) -> None:
        """Function convert_population."""

        self._check(ce.convert_population, ['4320'], NUMBER_TYPE)

    def test_get_year_index(self) -> None:
        """Function get_year_index"""

        self._check(ce.get_year_index, [1799], int)

    def test_get_country_row(self) -> None:
        """Function get_country_row"""

        self._check(ce.get_country_row,
                    [ce.SAMPLE_POPULATION_DATA, 'Canada'], list)

    def test_country_with_largest_emissions_by_year(self) -> None:
        """Function country_with_largest_emissions_by_year"""

        self._check(ce.country_with_largest_emissions_by_year,
                    [ce.SAMPLE_EMISSIONS_DATA, 1800], str)

    def test_emissions_by_country_by_year(self) -> None:
        """Function emissions_by_country_by_year"""

        self._check(ce.emissions_by_country_by_year,
                    [ce.SAMPLE_EMISSIONS_DATA,
                     ce.SAMPLE_POPULATION_DATA,
                     'Canada', 1799],
                    NUMBER_TYPE)

    def test_total_emissions_by_countries(self) -> None:
        """Function total_emissions_by_countries"""

        self._check(ce.total_emissions_by_countries,
                    [['Canada', 'Finland'],
                     ce.SAMPLE_POPULATION_DATA,
                     ce.SAMPLE_EMISSIONS_DATA, 1799
                     ], NUMBER_TYPE)

    def test_country_average_over_range(self) -> None:
        """Function country_average_over_range"""

        self._check(ce.country_average_over_range,
                    [ce.SAMPLE_EMISSIONS_DATA, 1799, 1800, 'Canada'], NUMBER_TYPE)

    def test_peak_year_by_country(self) -> None:
        """Function peak_year_by_country"""

        self._check(ce.peak_year_by_country,
                    [ce.SAMPLE_EMISSIONS_DATA, 'Canada'], int)

    def test_create_total_emissions_table(self) -> None:
        """Function create_total_emissions_table"""

        checker_generic.returns_list_of_Ts(
            ce.create_total_emissions_table,
            [ce.SAMPLE_EMISSIONS_DATA, ce.SAMPLE_POPULATION_DATA],
            list)

    def test_update_country_year_data(self) -> None:
        """Function update_country_year_data"""

        self._check(ce.update_country_year_data,
                    [[['France', -1.0, -1.0, -1.0, -1.0] + [-1.0] * 215],
                     'France', 1799, 0.05], NUMBER_TYPE)

    def test_read_data(self) -> None:
        """Function read_data"""

        checker_generic.returns_list_of_Ts(ce.read_data,
                                           ['co2_emissions_per_person.csv'],
                                           list)

    def test_prepare_data(self) -> None:
        """Function prepare_data"""

        checker_generic.returns_list_of_Ts(ce.read_data,
                                           ['co2_emissions_per_person.csv',
                                            True],
                                           list)

    def test_clean_population_data(self) -> None:
        """Function clean_population_data"""

        self._check(ce.clean_population_data,
                    [[['France', '29M', '29.1M', '29.2M', '29.3m'],
                      ['Mauritius', '59k', '60.7k', '62.4k', '64.2k']]],
                    type(None))

    def test_clean_emission_data(self) -> None:
        """Function clean_emission_data"""

        self._check(ce.clean_emission_data, [
            [['Canada', '0.00733', '0.00716', '0.00698', '0.00681'] + [''] * 215,
             ['Finland'] + [''] * 3 + ['0.00341'] + [''] * 215,
             ['Poland', '0.0452', ' 0.0489', '0.0494', '0.0502'] + [''] * 215]],
                    type(None))

    def test_check_constants(self) -> None:
        """Values of constants."""

        print('\nChecking that constants refer to their original values')
        self._check_constants(CONSTANTS, ce)
        print('  check complete')

    def _check(self, func: callable, args: list, ret_type: Union[type, tuple]) -> None:
        """Check that func called with arguments args returns a value of type
        ret_type. Display the progress and the result of the check.

        """

        print('\nChecking {}...'.format(func.__name__))
        result = checker_generic.type_check_simple(func, args, ret_type)
        assert result[0] is True, result[1]
        print('  check complete')

    def _check_constants(self, name2value: Dict[str, object], mod: Any) -> None:
        """Check that, for each (name, value) pair in name2value, the value of
        a variable named name in module mod is value.
        """

        for name, expected in name2value.items():
            actual = getattr(mod, name)
            msg = 'The value of constant {} should be {} but is {}.'.format(
                name, expected, actual)
            assert expected == actual, msg


print(''.center(TARGET_LEN, SEP))
print(' Start: checking coding style with PythonTA '.center(TARGET_LEN, SEP))
checker_generic.run_pyta(FILENAME, PYTA_CONFIG)
print(' End checking coding style with PythonTA '.center(TARGET_LEN, SEP))

print(' Start: checking type contracts '.center(TARGET_LEN, SEP))
pytest.main(['--show-capture', 'no', '--disable-warnings', '--tb=short',
             'a2_checker.py'])
print(' End checking type contracts '.center(TARGET_LEN, SEP))

print('\nScroll up to see ALL RESULTS:')
print('  - checking coding style with Python TA')
print('  - checking type contract\n')