class TestsWeapon(unittest.TestCase):
    def setUp(self):
        self.weapon = Weapon(name="The Axe of Destiny", damage=20)

    def test_eq_(self):
        with self.subTest('Returns false when damages don\'t match'):
            weapon1 = Weapon(name="The Axe of Destiny", damage=50)

            self.assertNotEqual(self.weapon, weapon1)

        with self.subTest('Returns false when names don\'t match'):
            weapon1 = Weapon(name="Sword", damage=20)

            self.assertNotEqual(self.weapon, weapon1)

        with self.subTest('Returns true when both args match'):
            weapon1 = Weapon(name="The Axe of Destiny", damage=20)

            self.assertEqual(self.weapon, weapon1)

    def test_to_json(self):
        expected = {
            'class': 'Weapon',
            'name': 'The Axe of Destiny',
            'damage': 20
        }

        self.assertDictEqual(self.weapon.to_json(), expected)

    def test_from_json(self):
        json_string = {
            'class': 'Weapon',
            'name': 'The Axe of Destiny',
            'damage': 20
        }

        self.assertEqual(Weapon.from_json(json_string), self.weapon)
class FightTests(unittest.TestCase):
    def setUp(self):
        self.spell = Spell(name="Fireball",
                           damage=5,
                           mana_cost=20,
                           cast_range=1)
        self.weapon = Weapon(name="The Axe of Destiny", damage=10)
        self.hero = Hero(name="Bron",
                         title="Dragonslayer",
                         health=100,
                         mana=100,
                         mana_regeneration_rate=2)
        self.map = [['.', '.', '#', '#', '.', 'S', '.', '.', '.', 'T'],
                    ['#', 'T', '#', '#', '.', '.', '#', '#', '#', '.'],
                    ['#', '.', '#', '#', '#', 'E', '#', '#', '#', 'E'],
                    ['#', '.', 'E', '.', '.', '.', '#', '#', '#', '.'],
                    ['#', '#', '#', 'T', '#', 'T', '#', '#', '#', 'G']]

        self.enemies = {
            "2,5": {
                "damage": 10,
                "health": 40,
                "mana": 20,
                "weapon": None,
                "spell": self.spell.to_json()
            },
            "2,9": {
                "damage": 10,
                "health": 40,
                "mana": 20,
                "weapon": self.weapon.to_json(),
                "spell": None
            },
            "3,2": {
                "damage": 10,
                "health": 40,
                "mana": 20,
                "weapon": None,
                "spell": None
            }
        }

        self.treasures = {
            "1,1": {
                "class": "Potion",
                "type": "mana",
                "amount": 50
            },
            "0,9": {
                "class": "Potion",
                "type": "health",
                "amount": 50
            },
            "4,3": {
                "class": "Weapon",
                "name": "The Axe of Destiny",
                "damage": 10
            },
            "4,5": {
                'class': "Spell",
                'name': 'Fireball',
                'damage': 5,
                'mana_cost': 20,
                'cast_range': 1
            }
        }

        self.json_data = {
            "map": self.map,
            "enemies": self.enemies,
            "treasures": self.treasures
        }

        self.dungeon = Dungeon(self.json_data)
        self.dungeon.spawn(self.hero)

        self.fight = Fight(dungeon=self.dungeon, enemy_pos=(2, 5))

    def test_init_initializing_correctly(self):
        self.assertEqual(self.fight.dungeon, self.dungeon)
        self.assertEqual(self.fight.enemy,
                         Enemy.from_json(self.enemies['2,5']))
        self.assertEqual(self.fight.enemy_pos, (2, 5))

    def test_init_raises_Assertion_error_when_there_is_no_enemy_on_the_given_pos(
            self):
        with self.assertRaises(AssertionError):
            Fight(dungeon=self.dungeon, enemy_pos=(0, 1))

    def test__range_between(self):
        self.assertEqual(self.fight._range_between(), 2)

    def test__direction_to_enemy_without_arguments(self):
        with self.subTest('Hero is up from enemy'):
            self.assertEqual(self.fight._direction_to_enemy(), (1, 0))

        with self.subTest('Hero is down from enemy'):
            self.fight.dungeon._hero_pos = (3, 5)

            self.assertEqual(self.fight._direction_to_enemy(), (-1, 0))

    def test__direction_to_enemy_with_argument(self):
        self.fight.enemy_pos = (3, 2)
        with self.subTest('Hero is left from enemy'):
            self.fight.dungeon._hero_pos = (3, 1)
            self.assertEqual(self.fight._direction_to_enemy(False), (0, 1))

        with self.subTest('Hero is right from enemy'):
            self.fight.dungeon._hero_pos = (3, 5)

            self.assertEqual(self.fight._direction_to_enemy(False), (0, -3))

    def test_hero_move_moves_hero_on_the_map_towards_enemy(self):
        self.fight.hero_move()

        self.assertEqual(self.fight.dungeon._map[1][5], self.hero)

    def test_enemy_move_moves_enemy_on_the_map_towards_hero(self):
        self.fight.enemy_move()

        self.assertEqual(self.fight.dungeon._map[1][5], self.fight.enemy)
        self.assertEqual(self.fight.enemy_pos, (1, 5))

    def test_player_makes_move_one_of_the_players_move_when_hero_has_to_move(
            self):
        self.fight.player_makes_move(self.dungeon._hero)

        self.assertEqual(self.fight.dungeon._map[1][5], self.hero)

    def test_player_makes_move_one_of_the_players_move_when_enemy_has_to_move(
            self):
        self.fight.player_makes_move(self.fight.enemy)

        self.assertEqual(self.fight.dungeon._map[1][5], self.fight.enemy)

    def test_player_makes_move_hero_attacks(self):
        self.fight.dungeon._hero.learn(self.spell)
        self.fight.enemy_move()
        self.fight.player_makes_move(self.fight.dungeon._hero)

        self.assertEqual(self.fight.enemy.get_health(), 35)

    def test_player_makes_move_enemy_attacks(self):
        self.fight.hero_move()
        self.fight.player_makes_move(self.fight.enemy)

        self.assertEqual(self.fight.dungeon._hero.get_health(), 85)

    def test_fight(self):
        spell = Spell(name="Fireball", damage=20, mana_cost=4, cast_range=1)
        self.fight.dungeon._hero.learn(spell)
        print()
        self.fight.dungeon.print_map()
        self.fight.fight()

        self.assertEqual(self.fight.dungeon._hero.get_health(), 85)
        self.assertEqual(self.fight.dungeon._hero_pos, (1, 5))
        self.assertFalse(self.fight.enemy.is_alive())

    def test_fight_hero_is_dead(self):
        self.hero._health = 10
        with self.assertRaises(HeroIsDeadError):
            self.fight.fight()
예제 #3
0
class TestsHero(unittest.TestCase):
    def setUp(self):
        self.hero1 = Hero(
            name='Toni',
            title='Pythonslayer',
            health=250,
            mana=1000,
            mana_regeneration_rate=25,
        )

        self.hero2 = Hero(name="Bron",
                          title="Dragonslayer",
                          health=100,
                          mana=100,
                          mana_regeneration_rate=2)

        self.spell = Spell(name="Fireball",
                           damage=30,
                           mana_cost=110,
                           cast_range=2)
        self.weapon = Weapon(name="The Axe of Destiny", damage=20)

    def test_init_working_correctly(self):
        with self.subTest('hero1'):
            self.assertEqual(self.hero1._name, 'Toni')
            self.assertEqual(self.hero1._title, 'Pythonslayer')
            self.assertEqual(self.hero1._health, 250)
            self.assertEqual(self.hero1._max_health, 250)
            self.assertEqual(self.hero1._mana, 1000)
            self.assertEqual(self.hero1._max_mana, 1000)
            self.assertEqual(self.hero1._mana_regeneration_rate, 25)
            self.assertEqual(self.hero1._weapon, None)
            self.assertEqual(self.hero1._spell, None)

    def test_known_as(self):
        with self.subTest('hero1'):
            self.assertEqual(self.hero1.known_as(), 'Toni the Pythonslayer')

        with self.subTest('hero2'):
            self.assertEqual(self.hero2.known_as(), 'Bron the Dragonslayer')

    def test_can_cast(self):
        with self.subTest('spell is None'):
            self.assertFalse(self.hero1.can_cast())

        with self.subTest('when mana is not enough'):
            self.hero2._spell = self.spell

            self.assertFalse(self.hero2.can_cast())

        with self.subTest('when mana is not enough'):
            self.hero1._spell = self.spell

            self.assertTrue(self.hero1.can_cast())

    def test_attack_raises_exceptions_correctly(self):
        with self.subTest('when by == weapon and hero\'s weapon is None'):
            with self.assertRaises(NotEquippedError):
                self.hero1.attack(by='weapon')

        with self.subTest('when by == spell and hero\'s spell is None'):
            with self.assertRaises(NotEquippedError):
                self.hero1.attack(by='spell')

        with self.subTest('when by is not \'weapon\' or \'spell\''):
            with self.assertRaises(TypeError):
                self.hero1.attack(by='foot')

        with self.subTest('when spell costs more then current mana'):
            with self.assertRaises(NotEnoughManaError):
                self.hero1.learn(self.spell)
                for x in range(0, 20):
                    self.hero1.attack(by='spell')

    def test_attack_returns_correct_damage(self):
        with self.subTest('\'by\' == \'spell\''):
            self.hero1._spell = self.spell
            damage = self.hero1.attack(by='spell')

            self.assertEqual(damage, 30)
            self.assertEqual(self.hero1._mana, 890)

        with self.subTest('\'by\' == \'weapon\''):
            self.hero2._weapon = self.weapon
            damage = self.hero2.attack(by='weapon')

            self.assertEqual(damage, 20)

    def test_eq_returns_false_when_hero1_super_different_than_hero2_super(
            self):
        hero3 = Hero(name="Bron",
                     title="Dragonslayer",
                     health=100,
                     mana=100,
                     mana_regeneration_rate=2)

        hero3.learn(self.spell)

        self.assertNotEqual(self.hero2, hero3)

    def test_eq_returns_false_when_hero1_has_different_attr_than_hero2_super(
            self):
        hero3 = Hero(name="Toni",
                     title="Dragonslayer",
                     health=100,
                     mana=100,
                     mana_regeneration_rate=2)

        self.assertNotEqual(self.hero2, hero3)

    def test_eq_returns_true_when_super_and_all_attrs_are_the_same(self):
        hero3 = Hero(name="Bron",
                     title="Dragonslayer",
                     health=100,
                     mana=100,
                     mana_regeneration_rate=2)

        self.assertEqual(self.hero2, hero3)

    def test_to_json(self):
        self.hero1.learn(self.spell)
        expected = {
            'name': 'Toni',
            'title': 'Pythonslayer',
            'mana_regeneration_rate': 25,
            'health': 250,
            'mana': 1000,
            'weapon': None,
            'spell': self.spell.to_json()
        }

        self.assertDictEqual(self.hero1.to_json(), expected)

    def test_from_json(self):
        self.hero1.equip(self.weapon)
        json_dict = {
            'name': 'Toni',
            'title': 'Pythonslayer',
            'mana_regeneration_rate': 25,
            'health': 250,
            'mana': 1000,
            'weapon': self.weapon.to_json(),
            'spell': None
        }

        self.assertEqual(self.hero1, Hero.from_json(json_dict))
class EnemyTests(unittest.TestCase):
    def setUp(self):
        self.e = Enemy(health=100, mana=100, damage=50)
        self.w = Weapon(name='The Axe of Destiny', damage=20)
        self.s = Spell(name='Fireball', damage=30, mana_cost=60, cast_range=2)

        self.e.equip(self.w)
        self.e.learn(self.s)

    def test_can_cast(self):
        self.assertTrue(self.e.can_cast())
        self.e._mana = 29
        self.assertFalse(self.e.can_cast())

    def test_attack(self):
        self.assertEqual(self.e.attack(by='weapon'), 70)
        self.assertEqual(self.e.attack(by='spell'), 80)
        with self.assertRaises(NotEnoughManaError):
            self.e.attack(by='spell')

    def test_take_mana(self):
        self.assertFalse(self.e.take_mana())

    def test_eq_returns_false_when_enemy1_super_different_than_enemy2_super(self):
        enemy1 = Enemy(health=100, mana=100, damage=50)
        enemy2 = Enemy(health=200, mana=100, damage=50)

        self.assertNotEqual(enemy1, enemy2)

    def test_eq_returns_false_when_enemy1_damage_different_than_enemy2_damage(self):
        enemy1 = Enemy(health=100, mana=100, damage=50)
        enemy2 = Enemy(health=100, mana=100, damage=75)

        self.assertNotEqual(enemy1, enemy2)

    def test_eq_returns_true_when_supers_are_equal_and_damages_are_equal(self):
        enemy1 = Enemy(health=100, mana=100, damage=50)
        enemy2 = Enemy(health=100, mana=100, damage=50)

        self.assertEqual(enemy1, enemy2)

    def test_to_json(self):
        expected = {
            'damage': 50,
            'health': 100,
            'mana': 100,
            'weapon': self.w.to_json(),
            'spell': self.s.to_json()
        }

        self.assertDictEqual(self.e.to_json(), expected)

    def test_from_json(self):
        json_dict = {
            'damage': 50,
            'health': 100,
            'mana': 100,
            'weapon': self.w.to_json(),
            'spell': self.s.to_json()
        }

        self.assertEqual(self.e, Enemy.from_json(json_dict))
예제 #5
0
class TestsDungeon(unittest.TestCase):
    def setUp(self):
        self.spell = Spell(name="Fireball",
                           damage=5,
                           mana_cost=20,
                           cast_range=1)
        self.weapon = Weapon(name="The Axe of Destiny", damage=10)
        self.hero = Hero(name="Bron",
                         title="Dragonslayer",
                         health=100,
                         mana=100,
                         mana_regeneration_rate=2)
        self.map = [['S', '.', '#', '#', '.', '.', '.', '.', '.', 'T'],
                    ['#', 'T', '#', '#', '.', '.', '#', '#', '#', '.'],
                    ['#', '.', '#', '#', '#', 'E', '#', '#', '#', 'E'],
                    ['#', '.', 'E', '.', '.', '.', '#', '#', '#', '.'],
                    ['#', '#', '#', 'T', '#', 'T', '#', '#', '#', 'G']]

        self.enemies = {
            "2,5": {
                "damage": 10,
                "health": 40,
                "mana": 20,
                "weapon": None,
                "spell": self.spell.to_json()
            },
            "2,9": {
                "damage": 10,
                "health": 40,
                "mana": 20,
                "weapon": self.weapon.to_json(),
                "spell": None
            },
            "3,2": {
                "damage": 10,
                "health": 40,
                "mana": 20,
                "weapon": None,
                "spell": None
            }
        }

        self.enemy1 = Enemy.from_json(self.enemies['2,5'])
        self.enemy2 = Enemy.from_json(self.enemies['2,9'])
        self.enemy3 = Enemy.from_json(self.enemies['3,2'])

        self.treasures = {
            "1,1": {
                "class": "Potion",
                "type": "mana",
                "amount": 50
            },
            "0,9": {
                "class": "Potion",
                "type": "health",
                "amount": 50
            },
            "4,3": {
                "class": "Weapon",
                "name": "The Axe of Destiny",
                "damage": 10
            },
            "4,5": {
                'class': "Spell",
                'name': 'Fireball',
                'damage': 5,
                'mana_cost': 20,
                'cast_range': 1
            }
        }

        self.tr1 = self.treasures['0,9']
        self.tr2 = self.treasures['1,1']
        self.tr3 = Weapon.from_json(self.treasures['4,3'])
        self.tr4 = Spell.from_json(self.treasures['4,5'])

        self.json_data = {
            "map": [
                "S.##.....T", "#T##..###.", "#.###E###E", "#.E...###.",
                "###T#T###G"
            ],
            "enemies":
            self.enemies,
            "treasures":
            self.treasures
        }

        self.dungeon = Dungeon(self.json_data)

    def test_init_adds_everything_on_the_map(self):
        expected_map = [
            ['S', '.', '#', '#', '.', '.', '.', '.', '.', self.tr1],
            ['#', self.tr2, '#', '#', '.', '.', '#', '#', '#', '.'],
            ['#', '.', '#', '#', '#', self.enemy1, '#', '#', '#', self.enemy2],
            ['#', '.', self.enemy3, '.', '.', '.', '#', '#', '#', '.'],
            ['#', '#', '#', self.tr3, '#', self.tr4, '#', '#', '#', 'G']
        ]

        self.assertEqual(self.dungeon._map, expected_map)
        self.assertEqual(self.dungeon._hero, None)
        self.assertEqual(self.dungeon._hero_pos, None)

    def test_get_map(self):
        expected = 'S.##.....T\n'\
                   '#T##..###.\n'\
                   '#.###E###E\n'\
                   '#.E...###.\n'\
                   '###T#T###G\n'
        self.dungeon._map = self.map

        self.assertEqual(self.dungeon.get_map(), expected)

    def test_extract_pos_raises_TypeError(self):
        self.dungeon._map = self.map
        with self.subTest(
                'When given string\'s format is not "digits,digits"'):
            with self.assertRaises(TypeError):
                self.dungeon.extract_pos('abc')

        with self.subTest('When the given coordinates are outsite the map!'):
            with self.assertRaises(TypeError):
                self.dungeon.extract_pos('-1,5')
            with self.assertRaises(TypeError):
                self.dungeon.extract_pos('1,-5')
            with self.assertRaises(TypeError):
                self.dungeon.extract_pos('10,1')
            with self.assertRaises(TypeError):
                self.dungeon.extract_pos('1,15')

    def test_extract_pos_returns_correct_pos(self):
        self.dungeon._map = self.map

        self.assertEqual(self.dungeon.extract_pos('1,1'), (1, 1))
        self.assertEqual(self.dungeon.extract_pos('0,0'), (0, 0))
        self.assertEqual(self.dungeon.extract_pos('4,9'), (4, 9))
        self.assertEqual(self.dungeon.extract_pos('2,3'), (2, 3))

    def test_add_enemies_raises_exception(self):
        self.dungeon._map = self.map

        with self.subTest('When pos of an enemy is invalid!'):
            enemies = {
                "abc": {
                    "deamage": 10,
                    "health": 40,
                    "mana": 20,
                    "weapon": None,
                    "spell": None
                }
            }

            with self.assertRaises(TypeError):
                self.dungeon.add_enemies(enemies)

        with self.subTest('When pos is not marked with \"E\" on the map!'):
            enemies = {
                "0,1": {
                    "damage": 10,
                    "health": 40,
                    "mana": 20,
                    "weapon": None,
                    "spell": None
                }
            }

            with self.assertRaises(Exception):
                self.dungeon.add_enemies(enemies)

        with self.subTest(
                'When an error occurs parsing an enemy! (Enemy with no damage)'
        ):
            enemies = {
                "2,5": {
                    "health": 40,
                    "mana": 20,
                    "weapon": None,
                    "spell": None
                }
            }

            with self.assertRaises(ValueError):
                self.dungeon.add_enemies(enemies)

    def test_add_enemies_adds_enemies_correctly(self):
        self.dungeon._map = self.map
        self.dungeon.add_enemies(self.enemies)

        expected = [['S', '.', '#', '#', '.', '.', '.', '.', '.', 'T'],
                    ['#', 'T', '#', '#', '.', '.', '#', '#', '#', '.'],
                    [
                        '#', '.', '#', '#', '#', self.enemy1, '#', '#', '#',
                        self.enemy2
                    ],
                    ['#', '.', self.enemy3, '.', '.', '.', '#', '#', '#', '.'],
                    ['#', '#', '#', 'T', '#', 'T', '#', '#', '#', 'G']]

        self.assertEqual(self.dungeon._map, expected)

    def test_extract_treasure_returns_correct_object(self):
        with self.subTest('With weapon'):
            w_dict = {
                "class": "Weapon",
                "name": "The Axe of Destiny",
                "damage": 10
            }

            self.assertEqual(self.dungeon.extract_treasure(w_dict),
                             self.weapon)

        with self.subTest('With spell'):
            s_dict = {
                "class": "Spell",
                "name": "Fireball",
                "damage": 5,
                "mana_cost": 20,
                "cast_range": 1
            }

            self.assertEqual(self.dungeon.extract_treasure(s_dict), self.spell)

        with self.subTest('With health or mana potion'):
            health_potion = {"class": "Potion", "type": "mana", "amount": 50}

            self.assertEqual(self.dungeon.extract_treasure(health_potion),
                             health_potion)

            mana_potion = {"class": "Potion", "type": "mana", "amount": 50}

            self.assertEqual(self.dungeon.extract_treasure(mana_potion),
                             mana_potion)

    def test_extract_treasure_raises_exception_on_invalid_class(self):
        invalid_class_dict = {'class': 'Computer'}

        with self.assertRaises(Exception):
            self.dungeon.extract_treasure(invalid_class_dict)

    def test_add_treasures_raises_exception(self):
        self.dungeon._map = self.map
        with self.subTest('When the pos of a treasure is invalid!'):
            treasures = {
                "20,20": {
                    "class": "Potion",
                    "type": "mana",
                    "amount": 50
                }
            }
            with self.assertRaises(TypeError):
                self.dungeon.add_treasures(treasures)

        with self.subTest(
                'When the pos of a treasure is not marked on the map with T!'):
            treasures = {
                "0,0": {
                    "class": "Potion",
                    "type": "mana",
                    "amount": 50
                }
            }
            with self.assertRaises(Exception):
                self.dungeon.add_treasures(treasures)

        with self.subTest('When an error occurs parsing the treasure!'):
            treasures = {
                "1,1": {
                    "class": "Chest",
                    "type": "mana",
                    "amount": 1000
                }
            }
            with self.assertRaises(Exception):
                self.dungeon.add_treasures(treasures)

    def test_add_treasures_adds_treasures_correctly(self):
        self.dungeon._map = self.map

        expected_map = [
            ['S', '.', '#', '#', '.', '.', '.', '.', '.', self.tr1],
            ['#', self.tr2, '#', '#', '.', '.', '#', '#', '#', '.'],
            ['#', '.', '#', '#', '#', 'E', '#', '#', '#', 'E'],
            ['#', '.', 'E', '.', '.', '.', '#', '#', '#', '.'],
            ['#', '#', '#', self.tr3, '#', self.tr4, '#', '#', '#', 'G']
        ]

        self.dungeon.add_treasures(self.treasures)

        self.assertEqual(self.dungeon._map, expected_map)

    def test_spawn_returns_False_when_there_is_no_spawning_point_on_the_map(
            self):
        self.dungeon._map[0][0] = '.'

        self.assertFalse(self.dungeon.spawn(self.hero))

    def test_spawn_spawns_hero_on_the_first_pos_marked_with_S(self):
        self.dungeon.spawn(self.hero)

        self.assertEqual(self.dungeon._map[0][0], self.hero)
        self.assertEqual(self.dungeon._hero, self.hero)
        self.assertEqual(self.dungeon._hero_pos, (0, 0))

    def test_move_hero_with_is_Fight_True_and_enemy_on_the_new_position(self):
        self.dungeon._map[1][5] = self.hero
        self.dungeon._hero = self.hero
        self.dungeon._hero_pos = (1, 5)
        self.dungeon.move_hero('down', True)

        self.assertEqual(self.dungeon._hero_pos, (2, 5))

    def test_move_hero_returns_False(self):
        self.dungeon.spawn(self.hero)

        with self.subTest('When trying to move outside the map!'):
            self.assertEqual(self.dungeon.move_hero('up'), False)

        with self.subTest('When trying to move in a wall!'):
            self.assertFalse(self.dungeon.move_hero('down'))

    def test_move_hero_returns_True_and_moves_hero_when_the_field_he_moves_on_is_free(
            self):
        self.dungeon.spawn(self.hero)

        self.assertTrue(self.dungeon.move_hero('right'))
        self.assertEqual(self.dungeon._map[0][0], '.')

    def test_move_hero_on_fied_with_treasure_opens_treasure(self):
        self.dungeon._hero = self.hero
        self.dungeon._hero_pos = (0, 8)
        self.dungeon._map[0][8] = self.hero
        self.dungeon._hero.take_damage(50)

        self.assertTrue(self.dungeon.move_hero('right'))
        self.assertEqual(self.dungeon._hero.get_health(), 100)
        self.assertEqual(self.dungeon._map[0][8], '.')
        self.assertEqual(self.dungeon._hero_pos, (0, 9))

    def test_move_hero_to_pos_raises_exception_on_invalid_pos(self):
        self.dungeon.spawn(self.hero)
        with self.assertRaises(Exception):
            self.dungeon._move_hero_to_pos(-1, 1)

    def test_move_hero_to_pos_moves_hero_to_given_pos(self):
        self.dungeon.spawn(self.hero)
        self.dungeon._move_hero_to_pos(1, 1)
        self.assertEqual(self.dungeon._map[0][0], '.')
        self.assertEqual(self.dungeon._hero_pos, (1, 1))

    def test_enemy_move_throws_exception(self):
        with self.subTest('When there is no enemy on the given position'):
            with self.assertRaises(AssertionError):
                self.dungeon.enemy_move((1, 1), 'left')

        with self.subTest('When the enemy will move outside the map'):
            with self.assertRaises(Exception):
                self.dungeon.enemy_move((2, 9), 'right')

        with self.subTest('When the enemy will move in a wall'):
            with self.assertRaises(Exception):
                self.dungeon.enemy_move((2, 9), 'left')

    def test_enemy_move_moves_enemy(self):
        new_pos_of_enemy = self.dungeon.enemy_move((2, 9), 'up')

        self.assertEqual(new_pos_of_enemy, (1, 9))
        self.assertEqual(self.dungeon._map[2][9], '.')

    def test_hero_open_treasure(self):
        self.dungeon.spawn(self.hero)

        with self.subTest('When treasure is a health potion'):
            self.dungeon._hero.take_damage(50)
            self.assertEqual(self.dungeon._hero.get_health(), 50)
            self.dungeon.hero_open_treasure((0, 9))
            self.assertEqual(self.dungeon._hero.get_mana(), 100)

        with self.subTest('When treasure is a mana potion'):
            self.dungeon._hero.learn(self.spell)
            self.dungeon._hero.attack(by='spell')

            self.assertEqual(self.dungeon._hero.get_mana(), 80)
            self.dungeon.hero_open_treasure((1, 1))
            self.assertEqual(self.dungeon._hero.get_mana(), 100)

        with self.subTest('When treasure is a weapon'):
            self.dungeon.hero_open_treasure((4, 3))
            self.assertEqual(self.dungeon._hero.weapon, self.weapon)

        with self.subTest('When treasure is a spell'):
            self.dungeon.hero_open_treasure((4, 5))
            self.assertEqual(self.dungeon._hero.spell, self.spell)

    def test_attack_from_distance(self):
        self.dungeon._hero = self.hero
        self.dungeon._hero_pos = (3, 1)
        self.dungeon._map[3][1] = self.hero
        self.dungeon._hero.learn(self.spell)

        with self.subTest('attack empty space'):
            self.assertFalse(self.dungeon.attack_from_distance('up'))

        with self.subTest('attack a wall'):
            with self.assertRaises(Exception):
                self.dungeon.attack_from_distance('left')

            with self.assertRaises(Exception):
                self.dungeon.attack_from_distance('down')

        with self.subTest('attack an enemy'):
            self.dungeon._hero.equip(self.weapon)
            self.assertTrue(self.dungeon.attack_from_distance('right'))

    def test_is_pos_on_the_map_returns_false(self):
        self.assertFalse(self.dungeon.is_pos_on_the_map(-1, -1))
        self.assertFalse(self.dungeon.is_pos_on_the_map(10, 1))

    def test_is_pos_on_the_map_returns_true(self):
        self.assertTrue(self.dungeon.is_pos_on_the_map(0, 0))
        self.assertTrue(self.dungeon.is_pos_on_the_map(4, 9))

    def test_inspect_pos_raises_Exception_when_given_pos_is_not_valid(self):
        with self.assertRaises(Exception):
            self.dungeon.inspect_pos(-1, 1)

    def test_inspect_pos_working_correctly(self):
        self.dungeon.spawn(self.hero)
        self.assertEqual(self.dungeon.inspect_pos(0, 0), self.hero)
        self.assertEqual(self.dungeon.inspect_pos(1, 0), '#')
        self.assertEqual(self.dungeon.inspect_pos(1, 1), self.tr2)
        self.assertEqual(self.dungeon.inspect_pos(2, 5), self.enemy1)
        self.assertEqual(self.dungeon.inspect_pos(0, 1), '.')