Coverage for tests/test_turtlesc.py: 100%
712 statements
« prev ^ index » next coverage.py v7.7.0, created at 2025-03-19 14:21 -0400
« prev ^ index » next coverage.py v7.7.0, created at 2025-03-19 14:21 -0400
1import pytest
2from turtle import *
3from turtlesc import *
4from random import *
6seed(42) # Keep at 42 for reproducible tests (dependent on which tests are run and in what order, anyway)
7tracer(10000, 0)
9def test_basic_sc_calls():
10 # Blanks are no-ops and fine:
11 assert sc('') == 0
12 assert sc('', '') == 0
13 assert sc(' ') == 0
14 assert sc(' ', ' ') == 0
15 assert sc('f 1, ') == 1
16 assert sc('f -1, ', '\n', ' ') == 1
18 # Invalid commands raise exceptions:
19 with pytest.raises(TurtleShortcutException):
20 sc('invalid')
21 with pytest.raises(TurtleShortcutException):
22 sc('f')
23 with pytest.raises(TurtleShortcutException):
24 sc('f 1 2')
25 with pytest.raises(TurtleShortcutException):
26 sc('f invalid')
28 assert sc('f 1, f -1') == 2
30def test_in_radians_mode():
31 radians()
32 assert in_radians_mode()
33 degrees()
34 assert not in_radians_mode()
37def test_in_degrees_mode():
38 degrees()
39 assert in_degrees_mode()
40 radians()
41 assert not in_degrees_mode()
42 degrees() # These tests always use degrees mode.
45def test_forward():
46 turtle.reset()
48 for name in ('f', 'forward', 'F', 'FORWARD', 'fOrWaRd'):
49 with pytest.raises(TurtleShortcutException):
50 sc(f'{name}') # Missing argument
51 with pytest.raises(TurtleShortcutException):
52 sc(f'{name} 1 2') # Too many arguments
53 with pytest.raises(TurtleShortcutException):
54 sc(f'{name} invalid') # Invalid argument
56 assert sc(f'{name} 1') == 1
57 assert pos() == (1, 0)
58 assert sc(f'{name} -1') == 1
59 assert pos() == (0, 0)
60 assert sc(f'{name} 0') == 1
61 assert pos() == (0, 0)
62 assert sc(f'{name} 0.5') == 1
63 assert pos() == (0.5, 0)
64 assert sc(f'{name} -0.5') == 1
65 assert pos() == (0, 0)
68def test_backward():
69 turtle.reset()
71 for name in ('b', 'backward', 'B', 'BACKWARD', 'bAcKwArD'):
72 with pytest.raises(TurtleShortcutException):
73 sc(f'{name}') # Missing argument
74 with pytest.raises(TurtleShortcutException):
75 sc(f'{name} 1 2') # Too many arguments
76 with pytest.raises(TurtleShortcutException):
77 sc(f'{name} invalid') # Invalid argument
79 assert sc(f'{name} 1') == 1
80 assert pos() == (-1, 0)
81 assert sc(f'{name} -1') == 1
82 assert pos() == (0, 0)
83 assert sc(f'{name} 0') == 1
84 assert pos() == (0, 0)
85 assert sc(f'{name} 0.5') == 1
86 assert pos() == (-0.5, 0)
87 assert sc(f'{name} -0.5') == 1
88 assert pos() == (0, 0)
91def test_right():
92 turtle.reset()
94 for name in ('r', 'right', 'R', 'RIGHT', 'rIgHt'):
95 with pytest.raises(TurtleShortcutException):
96 sc(f'{name}') # Missing argument
97 with pytest.raises(TurtleShortcutException):
98 sc(f'{name} 1 2') # Too many arguments
99 with pytest.raises(TurtleShortcutException):
100 sc(f'{name} invalid') # Invalid argument
102 assert sc(f'{name} 1') == 1
103 assert heading() == 359
104 assert sc(f'{name} -1') == 1
105 assert heading() == 0
106 assert sc(f'{name} 0') == 1
107 assert heading() == 0
108 assert sc(f'{name} 0.5') == 1
109 assert heading() == 359.5
110 assert sc(f'{name} -0.5') == 1
111 assert heading() == 0
114def test_left():
115 turtle.reset()
117 for name in ('l', 'left', 'L', 'LEFT', 'lEfT'):
118 with pytest.raises(TurtleShortcutException):
119 sc(f'{name}') # Missing argument
120 with pytest.raises(TurtleShortcutException):
121 sc(f'{name} 1 2') # Too many arguments
122 with pytest.raises(TurtleShortcutException):
123 sc(f'{name} invalid') # Invalid argument
125 assert sc(f'{name} 1') == 1
126 assert heading() == 1
127 assert sc(f'{name} -1') == 1
128 assert heading() == 0
129 assert sc(f'{name} 0') == 1
130 assert heading() == 0
131 assert sc(f'{name} 0.5') == 1
132 assert heading() == 0.5
133 assert sc(f'{name} -0.5') == 1
134 assert heading() == 0
137def test_setheading():
138 for name in ('sh', 'setheading', 'SH', 'SETHEADING', 'sEtHeAdInG'):
139 with pytest.raises(TurtleShortcutException):
140 sc(f'{name}') # Missing argument
141 with pytest.raises(TurtleShortcutException):
142 sc(f'{name} 1 2') # Too many arguments
143 with pytest.raises(TurtleShortcutException):
144 sc(f'{name} invalid') # Invalid argument
146 assert sc(f'{name} 1') == 1
147 assert heading() == 1
148 assert sc(f'{name} 0') == 1
149 assert heading() == 0
150 assert sc(f'{name} 360') == 1
151 assert heading() == 0
152 assert sc(f'{name} 720') == 1
153 assert heading() == 0
154 assert sc(f'{name} -360') == 1
155 assert heading() == 0
158def test_home():
159 for name in ('h', 'home', 'H', 'HOME', 'hOmE'):
160 with pytest.raises(TurtleShortcutException):
161 sc(f'{name} 1') # Too many arguments
163 assert sc(f'{name}') == 1
164 assert pos() == (0, 0)
165 assert heading() == 0
168def test_clear():
169 for name in ('c', 'clear', 'C', 'CLEAR', 'cLeAr'):
170 with pytest.raises(TurtleShortcutException):
171 sc(f'{name} 1') # Too many arguments
173 assert sc(f'{name}') == 1
176def test_goto():
177 for name in ('g', 'goto', 'G', 'GOTO', 'gOtO'):
178 with pytest.raises(TurtleShortcutException):
179 sc(f'{name}') # Missing argument
180 with pytest.raises(TurtleShortcutException):
181 sc(f'{name} 1') # Missing second argument
182 with pytest.raises(TurtleShortcutException):
183 sc(f'{name} 1 2 3') # Too many arguments
184 with pytest.raises(TurtleShortcutException):
185 sc(f'{name} 1 invalid')
186 with pytest.raises(TurtleShortcutException):
187 sc(f'{name} invalid 2')
189 assert sc(f'{name} 1 2') == 1
190 assert pos() == (1, 2)
191 assert sc(f'{name} -3 -4') == 1
192 assert pos() == (-3, -4)
193 assert sc(f'{name} 0 0') == 1
194 assert pos() == (0, 0)
195 assert sc(f'{name} 0.5 0.5') == 1
196 assert pos() == (0.5, 0.5)
197 assert sc(f'{name} -0.5 -0.5') == 1
198 assert pos() == (-0.5, -0.5)
201def test_tele():
202 for name in ('tele', 'TELE', 'tElE', 'teleport', 'TELEPORT', 'tElEpOrT'):
203 with pytest.raises(TurtleShortcutException):
204 sc(f'{name}') # Missing argument
205 with pytest.raises(TurtleShortcutException):
206 sc(f'{name} 1') # Missing second argument
207 with pytest.raises(TurtleShortcutException):
208 sc(f'{name} 1 2 3') # Too many arguments
209 with pytest.raises(TurtleShortcutException):
210 sc(f'{name} 1 invalid')
211 with pytest.raises(TurtleShortcutException):
212 sc(f'{name} invalid 2')
214 assert sc(f'{name} 1 2') == 1
215 assert pos() == (1, 2)
216 assert sc(f'{name} -3 -4') == 1
217 assert pos() == (-3, -4)
218 assert sc(f'{name} 0 0') == 1
219 assert pos() == (0, 0)
220 assert sc(f'{name} 0.5 0.5') == 1
221 assert pos() == (0.5, 0.5)
222 assert sc(f'{name} -0.5 -0.5') == 1
223 assert pos() == (-0.5, -0.5)
226def test_setx():
227 for name in ('x', 'setx', 'X', 'SETX', 'sEtX'):
228 reset()
230 with pytest.raises(TurtleShortcutException):
231 sc(f'{name}') # Missing argument
232 with pytest.raises(TurtleShortcutException):
233 sc(f'{name} 1 2') # Too many arguments
234 with pytest.raises(TurtleShortcutException):
235 sc(f'{name} invalid') # Invalid argument
237 assert sc(f'{name} 1') == 1
238 assert pos() == (1, 0)
239 assert sc(f'{name} -2') == 1
240 assert pos() == (-2, 0)
241 assert sc(f'{name} 0.5') == 1
242 assert pos() == (0.5, 0)
243 assert sc(f'{name} -0.5') == 1
244 assert pos() == (-0.5, 0)
246 sety(10)
247 assert sc(f'{name} 1') == 1
248 assert pos() == (1, 10)
251def test_sety():
252 for name in ('y', 'sety', 'Y', 'SETY', 'sEtY'):
253 reset()
255 with pytest.raises(TurtleShortcutException):
256 sc(f'{name}') # Missing argument
257 with pytest.raises(TurtleShortcutException):
258 sc(f'{name} 1 2') # Too many arguments
259 with pytest.raises(TurtleShortcutException):
260 sc(f'{name} invalid') # Invalid argument
262 assert sc(f'{name} 1') == 1
263 assert pos() == (0, 1)
264 assert sc(f'{name} -2') == 1
265 assert pos() == (0, -2)
266 assert sc(f'{name} 0.5') == 1
267 assert pos() == (0, 0.5)
268 assert sc(f'{name} -0.5') == 1
269 assert pos() == (0, -0.5)
271 setx(10)
272 assert sc(f'{name} 1') == 1
273 assert pos() == (10, 1)
277def test_pendown():
278 for name in ('pd', 'pendown', 'PD', 'PENDOWN', 'pEnDoWn'):
279 with pytest.raises(TurtleShortcutException):
280 sc(f'{name} 1') # Too many arguments
282 penup()
283 assert sc(f'{name}') == 1
284 assert isdown()
287def test_penup():
288 for name in ('pu', 'penup', 'PU', 'PENUP', 'pEnUp'):
289 with pytest.raises(TurtleShortcutException):
290 sc(f'{name} 1') # Too many arguments
292 pendown()
293 assert sc(f'{name}') == 1
294 assert not isdown()
297def test_pensize():
298 for name in ('ps', 'pensize', 'PS', 'PENSIZE', 'pEnSiZe'):
299 with pytest.raises(TurtleShortcutException):
300 sc(f'{name}') # Missing argument
301 with pytest.raises(TurtleShortcutException):
302 sc(f'{name} 1 2') # Too many arguments
303 with pytest.raises(TurtleShortcutException):
304 sc(f'{name} invalid') # Invalid argument
306 assert sc(f'{name} 10') == 1
307 assert pensize() == 10
309 assert sc(f'{name} 1.5') == 1
310 assert pensize() == 1.5
312 pensize(1)
315def test_stamp():
316 for name in ('st', 'stamp', 'ST', 'STAMP', 'sTaMp'):
317 reset()
319 with pytest.raises(TurtleShortcutException):
320 sc(f'{name} 1') # Too many arguments
322 assert sc(f'{name}') == 1
325def test_pencolor_fillcolor_bgcolor():
326 for name in ('pc', 'pencolor', 'PC', 'PENCOLOR', 'pEnCoLoR', 'fc', 'fillcolor', 'FC', 'FILLCOLOR', 'fIlLcOlOr', 'bc', 'bgcolor', 'BC', 'BGCOLOR', 'bGcOlOr'):
327 function_to_test = None
328 if name.lower().startswith('p'):
329 function_to_test = pencolor
330 elif name.lower().startswith('f'):
331 function_to_test = fillcolor
332 elif name.lower().startswith('b'):
333 function_to_test = bgcolor
335 with pytest.raises(TurtleShortcutException):
336 sc(f'{name}') # Missing argument
338 with pytest.raises(TurtleShortcutException):
339 sc(f'{name} 1 2') # Too many arguments
341 with pytest.raises(TurtleShortcutException):
342 sc(f'{name} FF0000') # Missing the leading # for hex colors
344 with pytest.raises(TurtleShortcutException):
345 sc(f'{name} invalid 0 0') # Invalid argument
346 with pytest.raises(TurtleShortcutException):
347 sc(f'{name} 0 invalid 0') # Invalid argument
348 with pytest.raises(TurtleShortcutException):
349 sc(f'{name} 0 0 invalid') # Invalid argument
352 colormode(1.0) # Set to 1.0 for testing
354 function_to_test('black') # Reset to black
355 assert sc(f'{name} red') == 1
356 assert function_to_test() == 'red'
358 function_to_test('black') # Reset to black
359 assert sc(f'{name} red') == 1
360 assert function_to_test() == 'red'
362 function_to_test('black') # Reset to black
363 assert sc(f'{name} 1 0 0') == 1
364 assert function_to_test() == (1.0, 0.0, 0.0)
366 function_to_test('black') # Reset to black
367 assert sc(f'{name} 1.0 0.0 0.0') == 1
368 assert function_to_test() == (1.0, 0.0, 0.0)
370 with pytest.raises(TurtleShortcutException):
371 sc(f'{name} 255 0 0')
373 colormode(1.0)
374 assert function_to_test() != (0, 255, 0) # Make sure it's not returning a 255 mode value.
376 for color_mode_setting in (255, 1.0):
377 colormode(color_mode_setting)
378 for color_name in 'black blue brown orange gray grey green purple violet pink yellow white red magenta cyan'.split():
379 assert sc(f'{name} {color_name}') == 1
380 assert function_to_test() == color_name
382 colormode(255)
383 assert sc(f'{name} #FF0000') == 1
384 assert function_to_test() == (255, 0, 0.0)
386 colormode(1)
387 assert sc(f'{name} #FF0000') == 1
388 assert function_to_test() == (1, 0, 0.0)
390 with pytest.raises(TurtleShortcutException):
391 sc(f'{name} xxyyzz') # Invalid color name
395def test_circle():
396 for name in ('cir', 'circle', 'CIR', 'CIRCLE', 'cIrClE'):
397 reset()
399 with pytest.raises(TurtleShortcutException):
400 sc(f'{name}') # Missing argument
401 with pytest.raises(TurtleShortcutException):
402 sc(f'{name} 1 2') # Too many arguments
403 with pytest.raises(TurtleShortcutException):
404 sc(f'{name} invalid') # Invalid argument
406 # The (int(pos()[0]), int(pos()[1])) stuff is because Vec2D objects
407 # returned from pos() consider (-0.00, -0.00) as not equal to (0, 0).
409 assert sc(f'{name} 1') == 1
410 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
412 assert sc(f'{name} 10') == 1
413 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
415 assert sc(f'{name} 10.5') == 1
416 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
418 assert sc(f'{name} -1') == 1
419 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
421 assert sc(f'{name} -10') == 1
422 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
424 assert sc(f'{name} -10.5') == 1
425 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
427 assert sc(f'{name} 0') == 1
428 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
431def test_undo():
432 for name in ('undo', 'UNDO', 'uNdO'):
433 reset()
435 with pytest.raises(TurtleShortcutException):
436 sc(f'{name} 1') # Too many arguments
438 assert sc(f'{name}') == 1
441def test_begin_fill_end():
442 for name in ('bf', 'begin_fill', 'BF', 'BEGIN_FILL', 'bEgIn_FiLl'):
443 with pytest.raises(TurtleShortcutException):
444 sc(f'{name} 1') # Too many arguments
446 assert sc(f'{name}') == 1
447 end_fill()
450def test_end_fill():
451 for name in ('ef', 'end_fill', 'EF', 'END_FILL', 'eNd_FiLl'):
452 with pytest.raises(TurtleShortcutException):
453 sc(f'{name} 1') # Too many arguments
455 begin_fill()
456 assert sc(f'{name}') == 1
459def test_reset():
460 for name in ('reset', 'RESET', 'rEsEt'):
461 with pytest.raises(TurtleShortcutException):
462 sc(f'{name} 1') # Too many arguments
464 assert sc(f'{name}') == 1
467def test_sleep_sc():
468 for name in ('sleep', 'SLEEP', 'sLeEp'):
469 with pytest.raises(TurtleShortcutException):
470 sc(f'{name}')
475def test_move_turn():
476 # Test the move and turn commands:
478 # Test home/h:
479 goto(1, 0)
480 assert sc('h') == 1
481 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
483 goto(1, 0)
484 assert sc('home') == 1
485 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
487 with pytest.raises(TurtleShortcutException):
488 sc('h 1')
490 # Test f/b forward/backward l/r left/right:
491 assert sc('f 1') == 1
492 assert (int(pos()[0]), int(pos()[1])) == (1, 0)
494 assert sc('forward 1') == 1
495 assert (int(pos()[0]), int(pos()[1])) == (2, 0)
497 assert sc('b 1') == 1
498 assert (int(pos()[0]), int(pos()[1])) == (1, 0)
500 assert sc('backward 1') == 1
501 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
503 assert sc('l 90') == 1
504 assert heading() == 90
506 assert sc('left 90') == 1
507 assert heading() == 180
509 assert sc('r 90') == 1
510 assert heading() == 90
512 assert sc('right 90') == 1
513 assert heading() == 0
515 assert sc('sh 42') == 1
516 assert heading() == 42
517 assert sc('sh 0') == 1
518 assert heading() == 0
520 assert sc('f -1') == 1
521 assert (int(pos()[0]), int(pos()[1])) == (-1, 0)
523 assert sc('b -1') == 1
524 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
526 assert sc('l -90') == 1
527 assert heading() == 270
529 assert sc('r -90') == 1
530 assert heading() == 0
532 assert sc('r 0') == 1
533 assert heading() == 0
535 assert sc('r 360') == 1
536 assert heading() == 0
538 assert sc('r 720') == 1
539 assert heading() == 0
541 assert sc('r -360') == 1
542 assert heading() == 0
544 assert sc('r -720') == 1
545 assert heading() == 0
547 assert sc('l 0') == 1
548 assert heading() == 0
550 assert sc('l 360') == 1
551 assert heading() == 0
553 assert sc('l 720') == 1
554 assert heading() == 0
556 assert sc('l -360') == 1
557 assert heading() == 0
559 assert sc('l -720') == 1
560 assert heading() == 0
562 assert sc('c') == 1
563 assert sc('clear') == 1
565 # Test g and goto:
566 assert sc('g 10 20') == 1
567 assert (int(pos()[0]), int(pos()[1])) == (10, 20)
569 assert sc('goto -30 -40') == 1
570 assert (int(pos()[0]), int(pos()[1])) == (-30, -40)
572 with pytest.raises(TurtleShortcutException):
573 sc('goto 10')
575 with pytest.raises(TurtleShortcutException):
576 sc('goto 10 invalid')
578 with pytest.raises(TurtleShortcutException):
579 sc('goto invalid 20')
581 with pytest.raises(TurtleShortcutException):
582 sc('goto invalid invalid')
584 with pytest.raises(TurtleShortcutException):
585 sc('g')
587 assert sc('x 100') == 1
588 assert (int(pos()[0]), int(pos()[1])) == (100, -40)
590 assert sc('y 200') == 1
591 assert (int(pos()[0]), int(pos()[1])) == (100, 200)
593 assert sc('setx 300') == 1
594 assert (int(pos()[0]), int(pos()[1])) == (300, 200)
596 assert sc('sety 400') == 1
597 assert (int(pos()[0]), int(pos()[1])) == (300, 400)
599 with pytest.raises(TurtleShortcutException):
600 sc('setx invalid')
602 with pytest.raises(TurtleShortcutException):
603 sc('sety invalid')
605 with pytest.raises(TurtleShortcutException):
606 sc('x invalid')
608 with pytest.raises(TurtleShortcutException):
609 sc('y invalid')
611def test_cardinal_directions_nsew():
612 # Test calling a function while in radians mode:
613 reset()
614 radians()
615 assert sc(f'n 100') == 1
616 assert (int(pos()[0]), int(pos()[1])) == (0, 100)
617 degrees()
619 for n, s, e, w, nw, ne, sw, se in ('n s e w nw ne sw se'.split(),
620 'north south east west northwest northeast southwest southeast'.split(),
621 'N S E W NW NE SW SE'.split(),
622 'NORTH SOUTH EAST WEST NORTHWEST NORTHEAST SOUTHWEST SOUTHEAST'.split()):
623 reset()
624 assert sc(f'{n} 100') == 1
625 assert (int(pos()[0]), int(pos()[1])) == (0, 100)
626 assert sc(f'{n} -100') == 1
627 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
629 reset()
630 assert sc(f'{s} 100') == 1
631 assert (int(pos()[0]), int(pos()[1])) == (0, -100)
632 assert sc(f'{s} -100') == 1
633 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
635 reset()
636 assert sc(f'{e} 100') == 1
637 assert (int(pos()[0]), int(pos()[1])) == (100, 0)
638 assert sc(f'{e} -100') == 1
639 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
641 reset()
642 assert sc(f'{w} 100') == 1
643 assert (int(pos()[0]), int(pos()[1])) == (-100, 0)
644 assert sc(f'{w} -100') == 1
645 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
647 reset()
648 assert sc(f'{nw} 100') == 1
649 assert (int(pos()[0]), int(pos()[1])) == (-70, 70)
650 assert sc(f'{nw} -100') == 1
651 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
653 reset()
654 assert sc(f'{ne} 100') == 1
655 assert (int(pos()[0]), int(pos()[1])) == (70, 70)
656 assert sc(f'{ne} -100') == 1
657 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
659 reset()
660 assert sc(f'{sw} 100') == 1
661 assert (int(pos()[0]), int(pos()[1])) == (-70, -70)
662 assert sc(f'{sw} -100') == 1
663 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
665 reset()
666 assert sc(f'{se} 100') == 1
667 assert (int(pos()[0]), int(pos()[1])) == (70, -70)
668 assert sc(f'{se} -100') == 1
669 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
672def test_sleep():
673 with pytest.raises(TurtleShortcutException):
674 sc('sleep') # Missing argument
675 with pytest.raises(TurtleShortcutException):
676 sc('sleep 1 2') # Too many arguments
677 with pytest.raises(TurtleShortcutException):
678 sc('sleep invalid') # Invalid argument
680 assert sc('sleep 1') == 1
681 assert sc('sleep 0.1') == 1
683def test_tracer_update():
684 orig_tracer = tracer()
685 orig_delay = delay()
687 for name in ('t', 'T', 'tracer', 'TRACER', 'tRaCeR'):
688 with pytest.raises(TurtleShortcutException):
689 sc('{name}') # Missing argument
690 with pytest.raises(TurtleShortcutException):
691 sc('{name} 1 2 3') # Too many arguments
692 with pytest.raises(TurtleShortcutException):
693 sc('{name} invalid 0')
694 with pytest.raises(TurtleShortcutException):
695 sc('{name} 0 invalid')
697 assert sc(f'{name} 123 1') == 1
698 assert tracer() == 123
699 assert delay() == 1
701 for name in ('u', 'U', 'update', 'UPDATE', 'uPdAtE'):
702 with pytest.raises(TurtleShortcutException):
703 sc('{name} 1') # Too many arguments
705 assert sc(f'{name}') == 1
707 tracer(orig_tracer, orig_delay)
710def test_show_hide():
711 for name in ('show', 'SHOW', 'sHoW'):
712 with pytest.raises(TurtleShortcutException):
713 sc(f'{name} 1') # Too many arguments
715 assert sc(f'{name}') == 1
716 assert isvisible()
718 for name in ('hide', 'HIDE', 'hIdE'):
719 with pytest.raises(TurtleShortcutException):
720 sc(f'{name} 1') # Too many arguments
722 assert sc(f'{name}') == 1
723 assert not isvisible()
726def test_dot():
727 for name in ('dot', 'DOT', 'dOt'):
728 with pytest.raises(TurtleShortcutException):
729 sc(f'{name}') # Missing argument
730 with pytest.raises(TurtleShortcutException):
731 sc(f'{name} 1 2') # Too many arguments
732 with pytest.raises(TurtleShortcutException):
733 sc(f'{name} invalid') # Invalid argument
734 with pytest.raises(TurtleShortcutException):
735 sc(f'{name} -1') # Invalid argument
738 assert sc(f'{name} 1') == 1
739 assert sc(f'{name} 10') == 1
740 assert sc(f'{name} 10.5') == 1
741 assert sc(f'{name} 0') == 1
744def test_clearstamp():
745 for name in ('cs', 'clearstamp', 'CS', 'CLEARSTAMP', 'cLeArStAmP'):
746 with pytest.raises(TurtleShortcutException):
747 sc(f'{name} 1 2') # Too many arguments
748 with pytest.raises(TurtleShortcutException):
749 sc(f'{name}') # Missing argument
750 with pytest.raises(TurtleShortcutException):
751 sc(f'{name} invalid') # Invalid argument
753 stamp_id = stamp()
754 assert sc(f'{name} {stamp_id}') == 1
757def test_clearstamps():
758 for name in ('css', 'clearstamps', 'CSS', 'CLEARSTAMPS', 'cLeArStAmPs'):
759 with pytest.raises(TurtleShortcutException):
760 sc(f'{name} 1 2') # Too many arguments
761 with pytest.raises(TurtleShortcutException):
762 sc(f'{name} invalid') # Invalid argument
764 assert sc(f'{name} 0') == 1
765 assert sc(f'{name} 2') == 1
766 assert sc(f'{name} -2') == 1
767 assert sc(f'{name}') == 1
769def test_speed():
770 for name in ('speed', 'SPEED', 'sPeEd'):
771 with pytest.raises(TurtleShortcutException):
772 sc(f'{name}') # Missing argument
773 with pytest.raises(TurtleShortcutException):
774 sc(f'{name} 1 2') # Too many arguments
775 with pytest.raises(TurtleShortcutException):
776 sc(f'{name} invalid') # Invalid argument
778 # Test numeric settings 0 to 10:
779 for speed_setting in tuple(range(11)):
780 assert sc(f'{name} {speed_setting}') == 1
781 assert speed() == speed_setting
782 # Test string settings:
783 for speed_setting, numeric_equivalent in {'fastest': 0, 'fast': 10, 'normal': 6, 'slow': 3, 'slowest': 1, 'FASTEST': 0, 'FAST': 10, 'NORMAL': 6, 'SLOW': 3, 'SLOWEST': 1}.items():
784 assert sc(f'{name} {speed_setting}') == 1
785 assert speed() == numeric_equivalent
787 tracer(10000, 0) # Restore the original tracer settings for other tests.
790def test_get_turtle_code():
791 assert get_turtle_code('f 100') == ('forward(100)',)
792 assert get_turtle_code('b 100') == ('backward(100)',)
793 assert get_turtle_code('l 90') == ('left(90)',)
794 assert get_turtle_code('r 90') == ('right(90)',)
795 assert get_turtle_code('g 100 200') == ('goto(100, 200)',)
796 assert get_turtle_code('sh 90') == ('setheading(90)',)
797 assert get_turtle_code('pu') == ('penup()',)
798 assert get_turtle_code('pd') == ('pendown()',)
799 assert get_turtle_code('ps 10') == ('pensize(10)',)
800 assert get_turtle_code('bf') == ('begin_fill()',)
801 assert get_turtle_code('ef') == ('end_fill()',)
802 assert get_turtle_code('reset') == ('reset()',)
803 assert get_turtle_code('sleep 1') == ('sleep(1)',)
804 assert get_turtle_code('t 100 0') == ('tracer(100, 0)',)
805 assert get_turtle_code('u') == ('update()',)
806 assert get_turtle_code('show') == ('showturtle()',)
807 assert get_turtle_code('hide') == ('hideturtle()',)
808 assert get_turtle_code('dot 10') == ('dot(10)',)
809 assert get_turtle_code('cs 1') == ('clearstamp(1)',)
810 assert get_turtle_code('css') == ('clearstamps()',)
811 assert get_turtle_code('css 1') == ('clearstamps(1)',)
812 assert get_turtle_code('st') == ('stamp()',)
813 assert get_turtle_code('speed 1') == ('speed(1)',)
814 assert get_turtle_code('home') == ('home()',)
815 assert get_turtle_code('x 100') == ('setx(100)',)
816 assert get_turtle_code('y 100') == ('sety(100)',)
817 assert get_turtle_code('setx 100') == ('setx(100)',)
818 assert get_turtle_code('sety 100') == ('sety(100)',)
819 assert get_turtle_code('c') == ('clear()',)
820 assert get_turtle_code('undo') == ('undo()',)
821 assert get_turtle_code('cir 100') == ('circle(100)',)
822 assert get_turtle_code('g 100 200') == ('goto(100, 200)',)
823 assert get_turtle_code('tele 100 200') == ('teleport(100, 200)',)
825 assert get_turtle_code('pc red') == ("pencolor('red')",)
826 assert get_turtle_code('fc red') == ("fillcolor('red')",)
827 assert get_turtle_code('bc red') == ("bgcolor('red')",)
829 colormode(255)
830 assert get_turtle_code('pc red') == ("pencolor('red')",)
831 assert get_turtle_code('pc 255 0 0') == ('pencolor((255, 0, 0))',)
832 assert get_turtle_code('fc 255 0 0') == ('fillcolor((255, 0, 0))',)
833 assert get_turtle_code('bc 255 0 0') == ('bgcolor((255, 0, 0))',)
835 colormode(1.0)
836 assert get_turtle_code('pc red') == ("pencolor('red')",)
837 with pytest.raises(TurtleShortcutException):
838 get_turtle_code('pc 255 0 0')
839 with pytest.raises(TurtleShortcutException):
840 get_turtle_code('fc 255 0 0')
841 with pytest.raises(TurtleShortcutException):
842 get_turtle_code('bc 255 0 0')
844 assert get_turtle_code('pc 1.0 0.0 0.0') == ('pencolor((1.0, 0.0, 0.0))',)
845 assert get_turtle_code('fc 1.0 0.0 0.0') == ('fillcolor((1.0, 0.0, 0.0))',)
846 assert get_turtle_code('bc 1.0 0.0 0.0') == ('bgcolor((1.0, 0.0, 0.0))',)
850 degrees()
851 assert get_turtle_code('n 100') == ('setheading(90)', 'forward(100)')
852 assert get_turtle_code('s 100') == ('setheading(270)', 'forward(100)')
853 assert get_turtle_code('e 100') == ('setheading(0)', 'forward(100)')
854 assert get_turtle_code('w 100') == ('setheading(180)', 'forward(100)')
855 assert get_turtle_code('nw 100') == ('setheading(135)', 'forward(100)')
856 assert get_turtle_code('ne 100') == ('setheading(45)', 'forward(100)')
857 assert get_turtle_code('sw 100') == ('setheading(225)', 'forward(100)')
858 assert get_turtle_code('se 100') == ('setheading(315)', 'forward(100)')
859 assert get_turtle_code('north 100') == ('setheading(90)', 'forward(100)')
860 assert get_turtle_code('south 100') == ('setheading(270)', 'forward(100)')
861 assert get_turtle_code('east 100') == ('setheading(0)', 'forward(100)')
862 assert get_turtle_code('west 100') == ('setheading(180)', 'forward(100)')
863 assert get_turtle_code('northwest 100') == ('setheading(135)', 'forward(100)')
864 assert get_turtle_code('northeast 100') == ('setheading(45)', 'forward(100)')
865 assert get_turtle_code('southwest 100') == ('setheading(225)', 'forward(100)')
866 assert get_turtle_code('southeast 100') == ('setheading(315)', 'forward(100)')
867 assert get_turtle_code('N 100') == ('setheading(90)', 'forward(100)')
868 assert get_turtle_code('S 100') == ('setheading(270)', 'forward(100)')
869 assert get_turtle_code('E 100') == ('setheading(0)', 'forward(100)')
870 assert get_turtle_code('W 100') == ('setheading(180)', 'forward(100)')
871 assert get_turtle_code('NW 100') == ('setheading(135)', 'forward(100)')
872 assert get_turtle_code('NE 100') == ('setheading(45)', 'forward(100)')
873 assert get_turtle_code('SW 100') == ('setheading(225)', 'forward(100)')
874 assert get_turtle_code('SE 100') == ('setheading(315)', 'forward(100)')
875 assert get_turtle_code('NORTH 100') == ('setheading(90)', 'forward(100)')
876 assert get_turtle_code('SOUTH 100') == ('setheading(270)', 'forward(100)')
877 assert get_turtle_code('EAST 100') == ('setheading(0)', 'forward(100)')
878 assert get_turtle_code('WEST 100') == ('setheading(180)', 'forward(100)')
879 assert get_turtle_code('NORTHWEST 100') == ('setheading(135)', 'forward(100)')
880 assert get_turtle_code('NORTHEAST 100') == ('setheading(45)', 'forward(100)')
881 assert get_turtle_code('SOUTHWEST 100') == ('setheading(225)', 'forward(100)')
882 assert get_turtle_code('SOUTHEAST 100') == ('setheading(315)', 'forward(100)')
883 assert get_turtle_code('n 100, f 100') == ('setheading(90)', 'forward(100)', 'forward(100)')
884 assert get_turtle_code('n 100, f 100, f 100') == ('setheading(90)', 'forward(100)', 'forward(100)', 'forward(100)')
886 radians()
887 assert get_turtle_code('n 100') == ('degrees()', 'setheading(90)', 'forward(100)', 'radians()')
888 assert get_turtle_code('s 100') == ('degrees()', 'setheading(270)', 'forward(100)', 'radians()')
889 assert get_turtle_code('e 100') == ('degrees()', 'setheading(0)', 'forward(100)', 'radians()')
890 assert get_turtle_code('w 100') == ('degrees()', 'setheading(180)', 'forward(100)', 'radians()')
891 assert get_turtle_code('nw 100') == ('degrees()', 'setheading(135)', 'forward(100)', 'radians()')
892 assert get_turtle_code('ne 100') == ('degrees()', 'setheading(45)', 'forward(100)', 'radians()')
893 assert get_turtle_code('sw 100') == ('degrees()', 'setheading(225)', 'forward(100)', 'radians()')
894 assert get_turtle_code('se 100') == ('degrees()', 'setheading(315)', 'forward(100)', 'radians()')
896 degrees()
904# EXAMPLE PROGRAMS:
906def test_colorful_squares():
907 colormode(1.0)
908 sc('t 1000 0, ps 4')
910 for i in range(100): # Draw 100 squares.
911 # Move to a random place:
912 sc(f'pu,g {randint(-400, 200)} {randint(-400, 200)},pd,fc {random()} {random()} {random()}, pc {random()} {random()} {random()}')
913 line_length = randint(20, 200)
915 # Draw the filled-in square:
916 sc('bf')
917 for j in range(4):
918 sc(f'f {line_length}, l 90')
919 sc('ef')
921 sc('u,reset')
924def test_draw_circles():
925 sc('t 1000 0, ps 1')
927 # Draw circle in the top half of the window:
928 sc('sh 0') # Face right.
929 for i in range(20):
930 sc(f'cir {i * 10}')
932 # Draw circles in the bottom half of the window:
933 sc('sh 180') # Face left.
934 for i in range(20):
935 sc(f'cir {i * 10}')
936 sc('u,reset')
939def test_curve_path_filled():
940 sc('t 1000 0, ps 1')
941 colormode(1.0)
942 for i in range(50):
943 sc(f'fc {random()} {random()} {random()}')
945 # Set a random heading and draw several short lines with changing direction:
946 sc(f'sh {randint(0, 360)}, bf')
948 for j in range(randint(200, 600)):
949 sc(f'f 1,l {randint(-4, 4)}')
950 sc(f'h, ef')
951 sc('u,reset')
954if __name__ == '__main__':
955 pytest.main()