test_rover.py
5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import os.path
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()
position = '{} {} {}'.format(self.rover.coordinates[0],
self.rover.coordinates[1],
self.rover.heading)
self.assertEqual(position, self.rover_output['result'])
class CatawikiRoversTestCase(unittest.TestCase):
"""
This is a weird testcase in Python terms, as it parses the catawiki input
file to generate the appropriate output. The SingleRoverTestCase above
does an actual unittest.
"""
def setUp(self):
self.assertTrue(os.path.exists('input.txt'), msg='Inputfile "input.txt"'
' does not exist')
self.instructions = []
self.rovers = []
with open('input.txt', 'r') as f:
self.boundaries = f.readline()
for line in f:
line = line.strip()
if line:
self.instructions.append(line)
it = iter(self.instructions)
for start, route in zip(it, it):
self.rovers.append(Rover(start=start, route=route,
boundaries=self.boundaries))
def test_instructions(self):
# There should be instructions
self.assertNotEqual(len(self.instructions), 0, msg='No instructions '
'found')
# The number of instructions should be even (i.e. every Rover should
# have a starting position and some movement instructions)
self.assertEqual(len(self.instructions) % 2, 0, msg='Missing some '
'instructions')
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(SingleRoverTestCase)
unittest.TextTestRunner(verbosity=2).run(suite)