PageRenderTime 45ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/Lib/test/test_turtle.py

https://github.com/albertz/CPython
Python | 436 lines | 434 code | 2 blank | 0 comment | 0 complexity | 584a9ffa3f1b0b752e307508561d8288 MD5 | raw file
  1. import pickle
  2. import unittest
  3. from test import support
  4. turtle = support.import_module('turtle')
  5. Vec2D = turtle.Vec2D
  6. test_config = """\
  7. width = 0.75
  8. height = 0.8
  9. canvwidth = 500
  10. canvheight = 200
  11. leftright = 100
  12. topbottom = 100
  13. mode = world
  14. colormode = 255
  15. delay = 100
  16. undobuffersize = 10000
  17. shape = circle
  18. pencolor = red
  19. fillcolor = blue
  20. resizemode = auto
  21. visible = None
  22. language = english
  23. exampleturtle = turtle
  24. examplescreen = screen
  25. title = Python Turtle Graphics
  26. using_IDLE = ''
  27. """
  28. test_config_two = """\
  29. # Comments!
  30. # Testing comments!
  31. pencolor = red
  32. fillcolor = blue
  33. visible = False
  34. language = english
  35. # Some more
  36. # comments
  37. using_IDLE = False
  38. """
  39. invalid_test_config = """
  40. pencolor = red
  41. fillcolor: blue
  42. visible = False
  43. """
  44. class TurtleConfigTest(unittest.TestCase):
  45. def get_cfg_file(self, cfg_str):
  46. self.addCleanup(support.unlink, support.TESTFN)
  47. with open(support.TESTFN, 'w') as f:
  48. f.write(cfg_str)
  49. return support.TESTFN
  50. def test_config_dict(self):
  51. cfg_name = self.get_cfg_file(test_config)
  52. parsed_cfg = turtle.config_dict(cfg_name)
  53. expected = {
  54. 'width' : 0.75,
  55. 'height' : 0.8,
  56. 'canvwidth' : 500,
  57. 'canvheight': 200,
  58. 'leftright': 100,
  59. 'topbottom': 100,
  60. 'mode': 'world',
  61. 'colormode': 255,
  62. 'delay': 100,
  63. 'undobuffersize': 10000,
  64. 'shape': 'circle',
  65. 'pencolor' : 'red',
  66. 'fillcolor' : 'blue',
  67. 'resizemode' : 'auto',
  68. 'visible' : None,
  69. 'language': 'english',
  70. 'exampleturtle': 'turtle',
  71. 'examplescreen': 'screen',
  72. 'title': 'Python Turtle Graphics',
  73. 'using_IDLE': '',
  74. }
  75. self.assertEqual(parsed_cfg, expected)
  76. def test_partial_config_dict_with_commments(self):
  77. cfg_name = self.get_cfg_file(test_config_two)
  78. parsed_cfg = turtle.config_dict(cfg_name)
  79. expected = {
  80. 'pencolor': 'red',
  81. 'fillcolor': 'blue',
  82. 'visible': False,
  83. 'language': 'english',
  84. 'using_IDLE': False,
  85. }
  86. self.assertEqual(parsed_cfg, expected)
  87. def test_config_dict_invalid(self):
  88. cfg_name = self.get_cfg_file(invalid_test_config)
  89. with support.captured_stdout() as stdout:
  90. parsed_cfg = turtle.config_dict(cfg_name)
  91. err_msg = stdout.getvalue()
  92. self.assertIn('Bad line in config-file ', err_msg)
  93. self.assertIn('fillcolor: blue', err_msg)
  94. self.assertEqual(parsed_cfg, {
  95. 'pencolor': 'red',
  96. 'visible': False,
  97. })
  98. class VectorComparisonMixin:
  99. def assertVectorsAlmostEqual(self, vec1, vec2):
  100. if len(vec1) != len(vec2):
  101. self.fail("Tuples are not of equal size")
  102. for idx, (i, j) in enumerate(zip(vec1, vec2)):
  103. self.assertAlmostEqual(
  104. i, j, msg='values at index {} do not match'.format(idx))
  105. class TestVec2D(VectorComparisonMixin, unittest.TestCase):
  106. def test_constructor(self):
  107. vec = Vec2D(0.5, 2)
  108. self.assertEqual(vec[0], 0.5)
  109. self.assertEqual(vec[1], 2)
  110. self.assertIsInstance(vec, Vec2D)
  111. self.assertRaises(TypeError, Vec2D)
  112. self.assertRaises(TypeError, Vec2D, 0)
  113. self.assertRaises(TypeError, Vec2D, (0, 1))
  114. self.assertRaises(TypeError, Vec2D, vec)
  115. self.assertRaises(TypeError, Vec2D, 0, 1, 2)
  116. def test_repr(self):
  117. vec = Vec2D(0.567, 1.234)
  118. self.assertEqual(repr(vec), '(0.57,1.23)')
  119. def test_equality(self):
  120. vec1 = Vec2D(0, 1)
  121. vec2 = Vec2D(0.0, 1)
  122. vec3 = Vec2D(42, 1)
  123. self.assertEqual(vec1, vec2)
  124. self.assertEqual(vec1, tuple(vec1))
  125. self.assertEqual(tuple(vec1), vec1)
  126. self.assertNotEqual(vec1, vec3)
  127. self.assertNotEqual(vec2, vec3)
  128. def test_pickling(self):
  129. vec = Vec2D(0.5, 2)
  130. for proto in range(pickle.HIGHEST_PROTOCOL + 1):
  131. with self.subTest(proto=proto):
  132. pickled = pickle.dumps(vec, protocol=proto)
  133. unpickled = pickle.loads(pickled)
  134. self.assertEqual(unpickled, vec)
  135. self.assertIsInstance(unpickled, Vec2D)
  136. def _assert_arithmetic_cases(self, test_cases, lambda_operator):
  137. for test_case in test_cases:
  138. with self.subTest(case=test_case):
  139. ((first, second), expected) = test_case
  140. op1 = Vec2D(*first)
  141. op2 = Vec2D(*second)
  142. result = lambda_operator(op1, op2)
  143. expected = Vec2D(*expected)
  144. self.assertVectorsAlmostEqual(result, expected)
  145. def test_vector_addition(self):
  146. test_cases = [
  147. (((0, 0), (1, 1)), (1.0, 1.0)),
  148. (((-1, 0), (2, 2)), (1, 2)),
  149. (((1.5, 0), (1, 1)), (2.5, 1)),
  150. ]
  151. self._assert_arithmetic_cases(test_cases, lambda x, y: x + y)
  152. def test_vector_subtraction(self):
  153. test_cases = [
  154. (((0, 0), (1, 1)), (-1, -1)),
  155. (((10.625, 0.125), (10, 0)), (0.625, 0.125)),
  156. ]
  157. self._assert_arithmetic_cases(test_cases, lambda x, y: x - y)
  158. def test_vector_multiply(self):
  159. vec1 = Vec2D(10, 10)
  160. vec2 = Vec2D(0.5, 3)
  161. answer = vec1 * vec2
  162. expected = 35
  163. self.assertAlmostEqual(answer, expected)
  164. vec = Vec2D(0.5, 3)
  165. answer = vec * 10
  166. expected = Vec2D(5, 30)
  167. self.assertVectorsAlmostEqual(answer, expected)
  168. def test_vector_negative(self):
  169. vec = Vec2D(10, -10)
  170. expected = (-10, 10)
  171. self.assertVectorsAlmostEqual(-vec, expected)
  172. def test_distance(self):
  173. vec = Vec2D(6, 8)
  174. expected = 10
  175. self.assertEqual(abs(vec), expected)
  176. vec = Vec2D(0, 0)
  177. expected = 0
  178. self.assertEqual(abs(vec), expected)
  179. vec = Vec2D(2.5, 6)
  180. expected = 6.5
  181. self.assertEqual(abs(vec), expected)
  182. def test_rotate(self):
  183. cases = [
  184. (((0, 0), 0), (0, 0)),
  185. (((0, 1), 90), (-1, 0)),
  186. (((0, 1), -90), (1, 0)),
  187. (((1, 0), 180), (-1, 0)),
  188. (((1, 0), 360), (1, 0)),
  189. ]
  190. for case in cases:
  191. with self.subTest(case=case):
  192. (vec, rot), expected = case
  193. vec = Vec2D(*vec)
  194. got = vec.rotate(rot)
  195. self.assertVectorsAlmostEqual(got, expected)
  196. class TestTNavigator(VectorComparisonMixin, unittest.TestCase):
  197. def setUp(self):
  198. self.nav = turtle.TNavigator()
  199. def test_goto(self):
  200. self.nav.goto(100, -100)
  201. self.assertAlmostEqual(self.nav.xcor(), 100)
  202. self.assertAlmostEqual(self.nav.ycor(), -100)
  203. def test_pos(self):
  204. self.assertEqual(self.nav.pos(), self.nav._position)
  205. self.nav.goto(100, -100)
  206. self.assertEqual(self.nav.pos(), self.nav._position)
  207. def test_left(self):
  208. self.assertEqual(self.nav._orient, (1.0, 0))
  209. self.nav.left(90)
  210. self.assertVectorsAlmostEqual(self.nav._orient, (0.0, 1.0))
  211. def test_right(self):
  212. self.assertEqual(self.nav._orient, (1.0, 0))
  213. self.nav.right(90)
  214. self.assertVectorsAlmostEqual(self.nav._orient, (0, -1.0))
  215. def test_reset(self):
  216. self.nav.goto(100, -100)
  217. self.assertAlmostEqual(self.nav.xcor(), 100)
  218. self.assertAlmostEqual(self.nav.ycor(), -100)
  219. self.nav.reset()
  220. self.assertAlmostEqual(self.nav.xcor(), 0)
  221. self.assertAlmostEqual(self.nav.ycor(), 0)
  222. def test_forward(self):
  223. self.nav.forward(150)
  224. expected = Vec2D(150, 0)
  225. self.assertVectorsAlmostEqual(self.nav.position(), expected)
  226. self.nav.reset()
  227. self.nav.left(90)
  228. self.nav.forward(150)
  229. expected = Vec2D(0, 150)
  230. self.assertVectorsAlmostEqual(self.nav.position(), expected)
  231. self.assertRaises(TypeError, self.nav.forward, 'skldjfldsk')
  232. def test_backwards(self):
  233. self.nav.back(200)
  234. expected = Vec2D(-200, 0)
  235. self.assertVectorsAlmostEqual(self.nav.position(), expected)
  236. self.nav.reset()
  237. self.nav.right(90)
  238. self.nav.back(200)
  239. expected = Vec2D(0, 200)
  240. self.assertVectorsAlmostEqual(self.nav.position(), expected)
  241. def test_distance(self):
  242. self.nav.forward(100)
  243. expected = 100
  244. self.assertAlmostEqual(self.nav.distance(Vec2D(0,0)), expected)
  245. def test_radians_and_degrees(self):
  246. self.nav.left(90)
  247. self.assertAlmostEqual(self.nav.heading(), 90)
  248. self.nav.radians()
  249. self.assertAlmostEqual(self.nav.heading(), 1.57079633)
  250. self.nav.degrees()
  251. self.assertAlmostEqual(self.nav.heading(), 90)
  252. def test_towards(self):
  253. coordinates = [
  254. # coordinates, expected
  255. ((100, 0), 0.0),
  256. ((100, 100), 45.0),
  257. ((0, 100), 90.0),
  258. ((-100, 100), 135.0),
  259. ((-100, 0), 180.0),
  260. ((-100, -100), 225.0),
  261. ((0, -100), 270.0),
  262. ((100, -100), 315.0),
  263. ]
  264. for (x, y), expected in coordinates:
  265. self.assertEqual(self.nav.towards(x, y), expected)
  266. self.assertEqual(self.nav.towards((x, y)), expected)
  267. self.assertEqual(self.nav.towards(Vec2D(x, y)), expected)
  268. def test_heading(self):
  269. self.nav.left(90)
  270. self.assertAlmostEqual(self.nav.heading(), 90)
  271. self.nav.left(45)
  272. self.assertAlmostEqual(self.nav.heading(), 135)
  273. self.nav.right(1.6)
  274. self.assertAlmostEqual(self.nav.heading(), 133.4)
  275. self.assertRaises(TypeError, self.nav.right, 'sdkfjdsf')
  276. self.nav.reset()
  277. rotations = [10, 20, 170, 300]
  278. result = sum(rotations) % 360
  279. for num in rotations:
  280. self.nav.left(num)
  281. self.assertEqual(self.nav.heading(), result)
  282. self.nav.reset()
  283. result = (360-sum(rotations)) % 360
  284. for num in rotations:
  285. self.nav.right(num)
  286. self.assertEqual(self.nav.heading(), result)
  287. self.nav.reset()
  288. rotations = [10, 20, -170, 300, -210, 34.3, -50.2, -10, -29.98, 500]
  289. sum_so_far = 0
  290. for num in rotations:
  291. if num < 0:
  292. self.nav.right(abs(num))
  293. else:
  294. self.nav.left(num)
  295. sum_so_far += num
  296. self.assertAlmostEqual(self.nav.heading(), sum_so_far % 360)
  297. def test_setheading(self):
  298. self.nav.setheading(102.32)
  299. self.assertAlmostEqual(self.nav.heading(), 102.32)
  300. self.nav.setheading(-123.23)
  301. self.assertAlmostEqual(self.nav.heading(), (-123.23) % 360)
  302. self.nav.setheading(-1000.34)
  303. self.assertAlmostEqual(self.nav.heading(), (-1000.34) % 360)
  304. self.nav.setheading(300000)
  305. self.assertAlmostEqual(self.nav.heading(), 300000%360)
  306. def test_positions(self):
  307. self.nav.forward(100)
  308. self.nav.left(90)
  309. self.nav.forward(-200)
  310. self.assertVectorsAlmostEqual(self.nav.pos(), (100.0, -200.0))
  311. def test_setx_and_sety(self):
  312. self.nav.setx(-1023.2334)
  313. self.nav.sety(193323.234)
  314. self.assertVectorsAlmostEqual(self.nav.pos(), (-1023.2334, 193323.234))
  315. def test_home(self):
  316. self.nav.left(30)
  317. self.nav.forward(-100000)
  318. self.nav.home()
  319. self.assertVectorsAlmostEqual(self.nav.pos(), (0,0))
  320. self.assertAlmostEqual(self.nav.heading(), 0)
  321. def test_distance_method(self):
  322. self.assertAlmostEqual(self.nav.distance(30, 40), 50)
  323. vec = Vec2D(0.22, .001)
  324. self.assertAlmostEqual(self.nav.distance(vec), 0.22000227271553355)
  325. another_turtle = turtle.TNavigator()
  326. another_turtle.left(90)
  327. another_turtle.forward(10000)
  328. self.assertAlmostEqual(self.nav.distance(another_turtle), 10000)
  329. class TestTPen(unittest.TestCase):
  330. def test_pendown_and_penup(self):
  331. tpen = turtle.TPen()
  332. self.assertTrue(tpen.isdown())
  333. tpen.penup()
  334. self.assertFalse(tpen.isdown())
  335. tpen.pendown()
  336. self.assertTrue(tpen.isdown())
  337. def test_showturtle_hideturtle_and_isvisible(self):
  338. tpen = turtle.TPen()
  339. self.assertTrue(tpen.isvisible())
  340. tpen.hideturtle()
  341. self.assertFalse(tpen.isvisible())
  342. tpen.showturtle()
  343. self.assertTrue(tpen.isvisible())
  344. if __name__ == '__main__':
  345. unittest.main()