Beispiel #1
0
    def setUp(self):
        """Sets up shared test data files and shared instances"""

        # Test data directory
        self.test_dir = "{}/test_data/".format(os.path.dirname(__file__))

        # Vulnerability curves
        self.good_curve = "{}/good_curve.tsv".format(self.test_dir)
        self.good_curve_2 = "{}/good_curve_2.tsv".format(self.test_dir)
        self.bad_curve_1 = "{}/bad_curve_1.tsv".format(self.test_dir)
        self.bad_curve_2 = "{}/bad_curve_2.tsv".format(self.test_dir)

        # Depth files
        self.good_depths = "{}/good_depths.tsv".format(self.test_dir)
        self.bad_depths_1 = "{}/bad_depths_1.tsv".format(self.test_dir)
        self.bad_depths_2 = "{}/bad_depths_2.tsv".format(self.test_dir)

        # Test instances
        self.vulnerability_curve = VulnerabilityCurve(self.good_curve)
        self.vulnerability_curve_2 = VulnerabilityCurve(
            self.good_curve_2, max_depth=12, bin_width=2)

        self.postcode = PostCode("AA1 1AA", "Foo", 10)
        self.flood_event = FloodEvent(self.good_depths, self.postcode)
        self.risk = Risk(self.postcode)

        self.bad_flood_event_1 = FloodEvent(self.bad_depths_1, self.postcode)
        self.bad_flood_event_2 = FloodEvent(self.bad_depths_2, self.postcode)
Beispiel #2
0
    def test_risk(self):
        """Tests the Risk class

        Tests are as follows:

          1. Tests the constructor with good and bad calls
          2. Tests that the expected values for floods are correctly calculated
          3. Tests that incorrect depth files raise suitable exceptions
        """

        #
        # 1. Tests the constructor with good and bad calls

        with self.assertRaises(
                TypeError, msg="Non-postcode instance should raise TypeError"):
            Risk(None)

        #
        # 2. Tests that the expected values for floods are correctly calculated

        self.assertAlmostEqual(
            self.risk.calculate_expected_damage(
                self.flood_event, self.vulnerability_curve),
            10,
            msg="Expected damage for this calculation should be 10")

        #
        # 3. Tests that incorrect depth files raise suitable exceptions

        # Test bad curve value
        with self.assertRaises(
                TypeError,
                msg="Non-vulnerability curve argument should raise TypeError"):
            self.risk.calculate_expected_damage(self.flood_event, "bar")

        # Test bad flood event value
        with self.assertRaises(
                TypeError,
                msg="Non-vulnerability curve argument should raise TypeError"):
            self.risk.calculate_expected_damage(
                "foo", self.vulnerability_curve)

        # Test non-matching flood event and risk postcodes
        with self.assertRaises(
                ValueError,
                msg="Postcode of Risk does not match postcode of flood event"):
            postcode2 = PostCode("AA2 2AA", "Bar", 10)
            risk2 = Risk(postcode2)
            risk2.calculate_expected_damage(
                self.flood_event, self.vulnerability_curve)

        # Test incorrect header in depths file
        with self.assertRaises(
                IOError,
                msg="Incorrect header for depths file should raise IOError"):
            self.risk.calculate_expected_damage(
                self.bad_flood_event_1, self.vulnerability_curve)

        # Test out of range value in depths file
        with self.assertRaises(
                ValueError,
                msg="Out-of-range depth values should raise ValueError"):
            self.risk.calculate_expected_damage(
                self.bad_flood_event_2, self.vulnerability_curve)
Beispiel #3
0
class TestFloodDamage(unittest.TestCase):
    """Unit tests for the Flood Damage package"""

    def setUp(self):
        """Sets up shared test data files and shared instances"""

        # Test data directory
        self.test_dir = "{}/test_data/".format(os.path.dirname(__file__))

        # Vulnerability curves
        self.good_curve = "{}/good_curve.tsv".format(self.test_dir)
        self.good_curve_2 = "{}/good_curve_2.tsv".format(self.test_dir)
        self.bad_curve_1 = "{}/bad_curve_1.tsv".format(self.test_dir)
        self.bad_curve_2 = "{}/bad_curve_2.tsv".format(self.test_dir)

        # Depth files
        self.good_depths = "{}/good_depths.tsv".format(self.test_dir)
        self.bad_depths_1 = "{}/bad_depths_1.tsv".format(self.test_dir)
        self.bad_depths_2 = "{}/bad_depths_2.tsv".format(self.test_dir)

        # Test instances
        self.vulnerability_curve = VulnerabilityCurve(self.good_curve)
        self.vulnerability_curve_2 = VulnerabilityCurve(
            self.good_curve_2, max_depth=12, bin_width=2)

        self.postcode = PostCode("AA1 1AA", "Foo", 10)
        self.flood_event = FloodEvent(self.good_depths, self.postcode)
        self.risk = Risk(self.postcode)

        self.bad_flood_event_1 = FloodEvent(self.bad_depths_1, self.postcode)
        self.bad_flood_event_2 = FloodEvent(self.bad_depths_2, self.postcode)

    def test_postcode(self):
        """Tests the PostCode class

        :return:
        """

        #
        # Test constructor with good and bad values

        self.assertIsInstance(
            self.flood_event, FloodEvent, msg="Expected FloodEvent object")

        with self.assertRaises(
                ValueError, msg="Invalid postcode should raise value error"):
            self.postcode = PostCode("Foo", "Bar", 10)

        with self.assertRaises(
                ValueError, msg="Invalid postcode should raise value error"):
            self.postcode = PostCode(1, "Bar", 10)

        with self.assertRaises(
                TypeError, msg="Non-string town should raise type error"):
            self.postcode = PostCode("AA1 1AA", None, 10)

        with self.assertRaises(
                TypeError, msg="Non-int town should raise type error"):
            self.postcode = PostCode("AA1 1AA", "Foo", "Bar")

    def test_curve(self):
        """Tests the Vulnerability Curve classes and methods

        Tests are as follows:

          1. Tests that damage_from_depth function returns correct output
          2. Test exceptions raised by damage_from_depth function
          3. Tests suitable exceptions are raised with an invalid curve file
        """

        #
        # 1. Test Damage outputs from a valid curve

        self.assertEqual(
            self.vulnerability_curve.damage_from_depth(0), 0,
            "Depth zero should return zero damage")

        self.assertEqual(
            self.vulnerability_curve.damage_from_depth(0.1), 10,
            "Depth 0.1 should return damage = 10 with the 'good' test curve")

        self.assertEqual(
            self.vulnerability_curve.damage_from_depth(4), 40,
            "Depth 4 should return damage = 40 with the 'good' test curve")

        # Test non-standard vulnerability curve (max_depth=12, bin_width=2)
        self.assertEqual(
            self.vulnerability_curve_2.damage_from_depth(11.0), 120,
            "Depth 11 should return damage = 120 with the second test curve")

        #
        # 2. Test suitable exceptions are raise with out-of-range depth values

        with self.assertRaises(
                ValueError, msg="Out-of-range depth should raise ValueError"):
            self.vulnerability_curve.damage_from_depth(11)

        with self.assertRaises(
                ValueError, msg="Out-of-range depth should raise ValueError"):
            self.vulnerability_curve.damage_from_depth(-1.1)

        with self.assertRaises(
                TypeError, msg="Non-numeric value should raise TypeError"):
            self.vulnerability_curve.damage_from_depth("foo")

        with self.assertRaises(
                ValueError, msg="Out-of-range depth should raise ValueError"):
            self.vulnerability_curve.damage_from_depth(11)


        #
        # 3).  Tests suitable exceptions are raised with an invalid curve file

        # Check test file 'bad_curve_1.tsv' exists
        self.assertTrue(
            os.path.isfile(self.bad_curve_1),
            "Missing bad_curve_1.tsv test file")

        # Check exception is raised if the expected file header is not present
        with self.assertRaises(
                IOError, msg="Incorrect curve file should raise IOError"):
            VulnerabilityCurve(self.bad_curve_1)

        # Check test file 'bad_curve_2.tsv' exists
        self.assertTrue(
            os.path.isfile(self.bad_curve_2),
            "Missing bad_curve_2.tsv test file")

        # Check exception is raised if file is incorrectly formatted
        with self.assertRaises(
                IOError, msg="Incorrect curve file should raise IOError"):
            VulnerabilityCurve(self.bad_curve_2)

    def test_flood_event(self):
        """Tests the FloodEvent classes and methods

          1. Tests the constructor with good and bad calls
        """

        #
        # 1. Test Constructor

        # Test valid call
        self.assertEqual(
            type(self.flood_event), FloodEvent,
            msg="Expected FloodEvent instance")

        with self.assertRaises(
                TypeError,
                msg="Incorrect postcode should raise type error"):
            FloodEvent(self.good_depths, None)

        with self.assertRaises(
                TypeError,
                msg="Incorrect depth file input should raise type error"):
            FloodEvent(None, self.postcode)

        with self.assertRaises(
                IOError,
                msg="Non-existant depth file should raise IO error"):
            FloodEvent("foo", self.postcode)

    def test_risk(self):
        """Tests the Risk class

        Tests are as follows:

          1. Tests the constructor with good and bad calls
          2. Tests that the expected values for floods are correctly calculated
          3. Tests that incorrect depth files raise suitable exceptions
        """

        #
        # 1. Tests the constructor with good and bad calls

        with self.assertRaises(
                TypeError, msg="Non-postcode instance should raise TypeError"):
            Risk(None)

        #
        # 2. Tests that the expected values for floods are correctly calculated

        self.assertAlmostEqual(
            self.risk.calculate_expected_damage(
                self.flood_event, self.vulnerability_curve),
            10,
            msg="Expected damage for this calculation should be 10")

        #
        # 3. Tests that incorrect depth files raise suitable exceptions

        # Test bad curve value
        with self.assertRaises(
                TypeError,
                msg="Non-vulnerability curve argument should raise TypeError"):
            self.risk.calculate_expected_damage(self.flood_event, "bar")

        # Test bad flood event value
        with self.assertRaises(
                TypeError,
                msg="Non-vulnerability curve argument should raise TypeError"):
            self.risk.calculate_expected_damage(
                "foo", self.vulnerability_curve)

        # Test non-matching flood event and risk postcodes
        with self.assertRaises(
                ValueError,
                msg="Postcode of Risk does not match postcode of flood event"):
            postcode2 = PostCode("AA2 2AA", "Bar", 10)
            risk2 = Risk(postcode2)
            risk2.calculate_expected_damage(
                self.flood_event, self.vulnerability_curve)

        # Test incorrect header in depths file
        with self.assertRaises(
                IOError,
                msg="Incorrect header for depths file should raise IOError"):
            self.risk.calculate_expected_damage(
                self.bad_flood_event_1, self.vulnerability_curve)

        # Test out of range value in depths file
        with self.assertRaises(
                ValueError,
                msg="Out-of-range depth values should raise ValueError"):
            self.risk.calculate_expected_damage(
                self.bad_flood_event_2, self.vulnerability_curve)