test_rover.py 4.01 KB
import random
import unittest

from rover import (Rover, OutOfBoundaryException, InvalidHeading,
                   MoveOutOfBounds, InvalidTurn)


class SingleRoverTestCase(unittest.TestCase):
    """
    Simple testcase for a SingleRover object, for developmental ease
    """

    def setUp(self):
        self.rover_input = {
            'start': '1 2 N',
            'route': 'LMLMLMLMM',
            'boundaries': '5 5'
        }
        self.rover_output = {
            'result': '1 3 N',
            'boundaries': [[0, 0], [5, 5]],
            'start_coordinates': [1, 2],
            'coordinates': [1, 3]
        }
        self.rover = Rover(**self.rover_input)
        self.valid_turns = {
            'L': {'N': 'W', 'W': 'S', 'S': 'E', 'E': 'N'},
            'R': {'N': 'E', 'E': 'S', 'S': 'W', 'W': 'N'}
        }

    def test_set_boundaries(self):
        self.rover.set_boundaries('9 9')
        self.assertEqual(self.rover.boundaries, [[0, 0], [9, 9]])

    def test_set_non_int_boundaries(self):
        with self.assertRaises(ValueError):
            self.rover.set_boundaries('not-integer-boundaries')

        # check that boundaries haven't changed
        self.assertEqual(self.rover.boundaries, self.rover_output['boundaries'])

    def test_set_coordinates(self):
        self.rover.set_coordinates(self.rover_output['coordinates'])
        self.assertEqual(self.rover.coordinates, self.rover_output['coordinates'])

    def test_set_out_of_boundary_coordinates(self):
        with self.assertRaises(OutOfBoundaryException):
            self.rover.set_coordinates(['12', '12'])

        # check that coordinates haven't changed
        self.assertEqual(self.rover.coordinates, self.rover_output['start_coordinates'])

    def test_set_heading(self):
        self.rover.set_heading('S')
        self.assertEqual(self.rover.heading, 'S')

    def test_set_invalid_heading(self):
        with self.assertRaises(InvalidHeading):
            self.rover.set_heading('invalid-heading')
        self.assertEqual(self.rover.heading, self.rover_input['start'][-1])

    def test_move(self):
        # starting position is "1 2 N", so if it moves a tile, the coordinates
        # should be "1 3 N"
        self.rover.move()
        self.assertEqual(self.rover.coordinates, self.rover_output['coordinates'])

    def test_out_of_bounds_move(self):
        # doing a random move would be nice
        self.rover.set_coordinates(self.rover_output['boundaries'][1])
        self.rover.set_heading('N')
        with self.assertRaises(MoveOutOfBounds):
            self.rover.move()

    def test_turning_move(self):
        # pick a random starting direction
        heading = random.choice(self.rover.headings)
        self.rover.set_heading(heading)

        # pick a random direction to turn to
        turning_direction = random.choice(self.valid_turns.keys())
        self.rover.turn(turning_direction)

        self.assertEqual(self.rover.heading, self.valid_turns[turning_direction][heading])

    def test_invalid_turning_direction(self):
        with self.assertRaises(InvalidTurn):
            self.rover.turn('G')
        self.assertEqual(self.rover.heading, self.rover_input['start'][-1])

    def test_execute_route(self):
        self.rover.execute_route(self.rover.route)
        position = '{} {} {}'.format(self.rover.coordinates[0],
                                     self.rover.coordinates[1],
                                     self.rover.heading)
        self.assertEqual(position, self.rover_output['result'])

    def test_execute_out_of_boundary_route(self):
        # This should move the rover out of bounds; the rover must have
        # malfunctioned and keeps moving north. It should stop at the edge of
        # the planet
        self.rover.execute_route('MMRMMRMRRMMMMMMMMMMMMMMMMM')
        position = '{} {} {}'.format(self.rover.coordinates[0],
                                     self.rover.coordinates[1],
                                     self.rover.heading)
        self.assertEqual(position, '3 5 N')


if __name__ == '__main__':
    unittest.main()