[Python-checkins] cpython (merge 3.5 -> default): Issue #21916: Added tests for the turtle module.

serhiy.storchaka python-checkins at python.org
Sat Jun 4 16:31:36 EDT 2016


https://hg.python.org/cpython/rev/3d1a23984a6e
changeset:   101718:3d1a23984a6e
parent:      101712:f5d243646fd4
parent:      101717:3b9e96440a70
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Sat Jun 04 23:28:40 2016 +0300
summary:
  Issue #21916: Added tests for the turtle module.
Patch by ingrid, Gregory Loyse and Jelle Zijlstra.

files:
  Lib/test/test_turtle.py |  400 ++++++++++++++++++++++++++++
  Misc/NEWS               |    3 +
  2 files changed, 403 insertions(+), 0 deletions(-)


diff --git a/Lib/test/test_turtle.py b/Lib/test/test_turtle.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/test_turtle.py
@@ -0,0 +1,400 @@
+import unittest
+from test import support
+
+turtle = support.import_module('turtle')
+Vec2D = turtle.Vec2D
+
+test_config = """\
+width = 0.75
+height = 0.8
+canvwidth = 500
+canvheight = 200
+leftright = 100
+topbottom = 100
+mode = world
+colormode = 255
+delay = 100
+undobuffersize = 10000
+shape = circle
+pencolor  = red
+fillcolor  = blue
+resizemode  = auto
+visible  = None
+language = english
+exampleturtle = turtle
+examplescreen = screen
+title = Python Turtle Graphics
+using_IDLE = ''
+"""
+
+test_config_two = """\
+# Comments!
+# Testing comments!
+pencolor  = red
+fillcolor  = blue
+visible  = False
+language = english
+# Some more
+# comments
+using_IDLE = False
+"""
+
+invalid_test_config = """
+pencolor = red
+fillcolor: blue
+visible = False
+"""
+
+
+class TurtleConfigTest(unittest.TestCase):
+
+    def get_cfg_file(self, cfg_str):
+        self.addCleanup(support.unlink, support.TESTFN)
+        with open(support.TESTFN, 'w') as f:
+            f.write(cfg_str)
+        return support.TESTFN
+
+    def test_config_dict(self):
+
+        cfg_name = self.get_cfg_file(test_config)
+        parsed_cfg = turtle.config_dict(cfg_name)
+
+        expected = {
+            'width' : 0.75,
+            'height' : 0.8,
+            'canvwidth' : 500,
+            'canvheight': 200,
+            'leftright': 100,
+            'topbottom': 100,
+            'mode': 'world',
+            'colormode': 255,
+            'delay': 100,
+            'undobuffersize': 10000,
+            'shape': 'circle',
+            'pencolor' : 'red',
+            'fillcolor' : 'blue',
+            'resizemode' : 'auto',
+            'visible' : None,
+            'language': 'english',
+            'exampleturtle': 'turtle',
+            'examplescreen': 'screen',
+            'title': 'Python Turtle Graphics',
+            'using_IDLE': '',
+        }
+
+        self.assertEqual(parsed_cfg, expected)
+
+    def test_partial_config_dict_with_commments(self):
+
+        cfg_name = self.get_cfg_file(test_config_two)
+        parsed_cfg = turtle.config_dict(cfg_name)
+
+        expected = {
+            'pencolor': 'red',
+            'fillcolor': 'blue',
+            'visible': False,
+            'language': 'english',
+            'using_IDLE': False,
+        }
+
+        self.assertEqual(parsed_cfg, expected)
+
+    def test_config_dict_invalid(self):
+
+        cfg_name = self.get_cfg_file(invalid_test_config)
+
+        with support.captured_stdout() as stdout:
+            parsed_cfg = turtle.config_dict(cfg_name)
+
+        err_msg = stdout.getvalue()
+
+        self.assertIn('Bad line in config-file ', err_msg)
+        self.assertIn('fillcolor: blue', err_msg)
+
+        self.assertEqual(parsed_cfg, {
+            'pencolor': 'red',
+            'visible': False,
+        })
+
+
+class VectorComparisonMixin:
+
+    def assertVectorsAlmostEqual(self, vec1, vec2):
+        if len(vec1) != len(vec2):
+            self.fail("Tuples are not of equal size")
+        for idx, (i, j) in enumerate(zip(vec1, vec2)):
+            self.assertAlmostEqual(
+                i, j, msg='values at index {} do not match'.format(idx))
+
+
+class TestVec2D(VectorComparisonMixin, unittest.TestCase):
+
+    def _assert_arithmetic_cases(self, test_cases, lambda_operator):
+        for test_case in test_cases:
+            with self.subTest(case=test_case):
+
+                ((first, second), expected) = test_case
+
+                op1 = Vec2D(*first)
+                op2 = Vec2D(*second)
+
+                result = lambda_operator(op1, op2)
+
+                expected = Vec2D(*expected)
+
+                self.assertVectorsAlmostEqual(result, expected)
+
+    def test_vector_addition(self):
+
+        test_cases = [
+            (((0, 0), (1, 1)), (1.0, 1.0)),
+            (((-1, 0), (2, 2)), (1, 2)),
+            (((1.5, 0), (1, 1)), (2.5, 1)),
+        ]
+
+        self._assert_arithmetic_cases(test_cases, lambda x, y: x + y)
+
+    def test_vector_subtraction(self):
+
+        test_cases = [
+            (((0, 0), (1, 1)), (-1, -1)),
+            (((10.625, 0.125), (10, 0)), (0.625, 0.125)),
+        ]
+
+        self._assert_arithmetic_cases(test_cases, lambda x, y: x - y)
+
+    def test_vector_multiply(self):
+
+        vec1 = Vec2D(10, 10)
+        vec2 = Vec2D(0.5, 3)
+        answer = vec1 * vec2
+        expected = 35
+        self.assertAlmostEqual(answer, expected)
+
+        vec = Vec2D(0.5, 3)
+        answer = vec * 10
+        expected = Vec2D(5, 30)
+        self.assertVectorsAlmostEqual(answer, expected)
+
+    def test_vector_negative(self):
+        vec = Vec2D(10, -10)
+        expected = (-10, 10)
+        self.assertVectorsAlmostEqual(-vec, expected)
+
+    def test_distance(self):
+        vec = Vec2D(6, 8)
+        expected = 10
+        self.assertEqual(abs(vec), expected)
+
+        vec = Vec2D(0, 0)
+        expected = 0
+        self.assertEqual(abs(vec), expected)
+
+        vec = Vec2D(2.5, 6)
+        expected = 6.5
+        self.assertEqual(abs(vec), expected)
+
+    def test_rotate(self):
+
+        cases = [
+            (((0, 0), 0), (0, 0)),
+            (((0, 1), 90), (-1, 0)),
+            (((0, 1), -90), (1, 0)),
+            (((1, 0), 180), (-1, 0)),
+            (((1, 0), 360), (1, 0)),
+        ]
+
+        for case in cases:
+            with self.subTest(case=case):
+                (vec, rot), expected = case
+                vec = Vec2D(*vec)
+                got = vec.rotate(rot)
+                self.assertVectorsAlmostEqual(got, expected)
+
+
+class TestTNavigator(VectorComparisonMixin, unittest.TestCase):
+
+    def setUp(self):
+        self.nav = turtle.TNavigator()
+
+    def test_goto(self):
+        self.nav.goto(100, -100)
+        self.assertAlmostEqual(self.nav.xcor(), 100)
+        self.assertAlmostEqual(self.nav.ycor(), -100)
+
+    def test_pos(self):
+        self.assertEqual(self.nav.pos(), self.nav._position)
+        self.nav.goto(100, -100)
+        self.assertEqual(self.nav.pos(), self.nav._position)
+
+    def test_left(self):
+        self.assertEqual(self.nav._orient, (1.0, 0))
+        self.nav.left(90)
+        self.assertVectorsAlmostEqual(self.nav._orient, (0.0, 1.0))
+
+    def test_right(self):
+        self.assertEqual(self.nav._orient, (1.0, 0))
+        self.nav.right(90)
+        self.assertVectorsAlmostEqual(self.nav._orient, (0, -1.0))
+
+    def test_reset(self):
+        self.nav.goto(100, -100)
+        self.assertAlmostEqual(self.nav.xcor(), 100)
+        self.assertAlmostEqual(self.nav.ycor(), -100)
+        self.nav.reset()
+        self.assertAlmostEqual(self.nav.xcor(), 0)
+        self.assertAlmostEqual(self.nav.ycor(), 0)
+
+    def test_forward(self):
+        self.nav.forward(150)
+        expected = Vec2D(150, 0)
+        self.assertVectorsAlmostEqual(self.nav.position(), expected)
+
+        self.nav.reset()
+        self.nav.left(90)
+        self.nav.forward(150)
+        expected = Vec2D(0, 150)
+        self.assertVectorsAlmostEqual(self.nav.position(), expected)
+
+        self.assertRaises(TypeError, self.nav.forward, 'skldjfldsk')
+
+    def test_backwards(self):
+        self.nav.back(200)
+        expected = Vec2D(-200, 0)
+        self.assertVectorsAlmostEqual(self.nav.position(), expected)
+
+        self.nav.reset()
+        self.nav.right(90)
+        self.nav.back(200)
+        expected = Vec2D(0, 200)
+        self.assertVectorsAlmostEqual(self.nav.position(), expected)
+
+    def test_distance(self):
+        self.nav.forward(100)
+        expected = 100
+        self.assertAlmostEqual(self.nav.distance(Vec2D(0,0)), expected)
+
+    def test_radians_and_degrees(self):
+        self.nav.left(90)
+        self.assertAlmostEqual(self.nav.heading(), 90)
+        self.nav.radians()
+        self.assertAlmostEqual(self.nav.heading(), 1.57079633)
+        self.nav.degrees()
+        self.assertAlmostEqual(self.nav.heading(), 90)
+
+    def test_towards(self):
+
+        coordinates = [
+            # coordinates, expected
+            ((100, 0), 0.0),
+            ((100, 100), 45.0),
+            ((0, 100), 90.0),
+            ((-100, 100), 135.0),
+            ((-100, 0), 180.0),
+            ((-100, -100), 225.0),
+            ((0, -100), 270.0),
+            ((100, -100), 315.0),
+        ]
+
+        for (x, y), expected in coordinates:
+            self.assertEqual(self.nav.towards(x, y), expected)
+            self.assertEqual(self.nav.towards((x, y)), expected)
+            self.assertEqual(self.nav.towards(Vec2D(x, y)), expected)
+
+    def test_heading(self):
+
+        self.nav.left(90)
+        self.assertAlmostEqual(self.nav.heading(), 90)
+        self.nav.left(45)
+        self.assertAlmostEqual(self.nav.heading(), 135)
+        self.nav.right(1.6)
+        self.assertAlmostEqual(self.nav.heading(), 133.4)
+        self.assertRaises(TypeError, self.nav.right, 'sdkfjdsf')
+        self.nav.reset()
+
+        rotations = [10, 20, 170, 300]
+        result = sum(rotations) % 360
+        for num in rotations:
+            self.nav.left(num)
+        self.assertEqual(self.nav.heading(), result)
+        self.nav.reset()
+
+        result = (360-sum(rotations)) % 360
+        for num in rotations:
+            self.nav.right(num)
+        self.assertEqual(self.nav.heading(), result)
+        self.nav.reset()
+
+        rotations = [10, 20, -170, 300, -210, 34.3, -50.2, -10, -29.98, 500]
+        sum_so_far = 0
+        for num in rotations:
+            if num < 0:
+                self.nav.right(abs(num))
+            else:
+                self.nav.left(num)
+            sum_so_far += num
+            self.assertAlmostEqual(self.nav.heading(), sum_so_far % 360)
+
+    def test_setheading(self):
+        self.nav.setheading(102.32)
+        self.assertAlmostEqual(self.nav.heading(), 102.32)
+        self.nav.setheading(-123.23)
+        self.assertAlmostEqual(self.nav.heading(), (-123.23) % 360)
+        self.nav.setheading(-1000.34)
+        self.assertAlmostEqual(self.nav.heading(), (-1000.34) % 360)
+        self.nav.setheading(300000)
+        self.assertAlmostEqual(self.nav.heading(), 300000%360)
+
+    def test_positions(self):
+        self.nav.forward(100)
+        self.nav.left(90)
+        self.nav.forward(-200)
+        self.assertVectorsAlmostEqual(self.nav.pos(), (100.0, -200.0))
+
+    def test_setx_and_sety(self):
+        self.nav.setx(-1023.2334)
+        self.nav.sety(193323.234)
+        self.assertVectorsAlmostEqual(self.nav.pos(), (-1023.2334, 193323.234))
+
+    def test_home(self):
+        self.nav.left(30)
+        self.nav.forward(-100000)
+        self.nav.home()
+        self.assertVectorsAlmostEqual(self.nav.pos(), (0,0))
+        self.assertAlmostEqual(self.nav.heading(), 0)
+
+    def test_distance_method(self):
+        self.assertAlmostEqual(self.nav.distance(30, 40), 50)
+        vec = Vec2D(0.22, .001)
+        self.assertAlmostEqual(self.nav.distance(vec), 0.22000227271553355)
+        another_turtle = turtle.TNavigator()
+        another_turtle.left(90)
+        another_turtle.forward(10000)
+        self.assertAlmostEqual(self.nav.distance(another_turtle), 10000)
+
+
+class TestTPen(unittest.TestCase):
+
+    def test_pendown_and_penup(self):
+
+        tpen = turtle.TPen()
+
+        self.assertTrue(tpen.isdown())
+        tpen.penup()
+        self.assertFalse(tpen.isdown())
+        tpen.pendown()
+        self.assertTrue(tpen.isdown())
+
+    def test_showturtle_hideturtle_and_isvisible(self):
+
+        tpen = turtle.TPen()
+
+        self.assertTrue(tpen.isvisible())
+        tpen.hideturtle()
+        self.assertFalse(tpen.isvisible())
+        tpen.showturtle()
+        self.assertTrue(tpen.isvisible())
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -1238,6 +1238,9 @@
 Tests
 -----
 
+- Issue #21916: Added tests for the turtle module.  Patch by ingrid,
+  Gregory Loyse and Jelle Zijlstra.
+
 - Issue #26295: When using "python3 -m test --testdir=TESTDIR", regrtest
   doesn't add "test." prefix to test module names.
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list