Coverage for tests/test_turtlesc.py: 100%
783 statements
« prev ^ index » next coverage.py v7.7.0, created at 2025-03-18 22:46 -0400
« prev ^ index » next coverage.py v7.7.0, created at 2025-03-18 22:46 -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():
326 for name in ('pc', 'pencolor', 'PC', 'PENCOLOR', 'pEnCoLoR'):
327 with pytest.raises(TurtleShortcutException):
328 sc(f'{name}') # Missing argument
330 with pytest.raises(TurtleShortcutException):
331 sc(f'{name} 1 2') # Missing argument
333 with pytest.raises(TurtleShortcutException):
334 sc(f'{name} invalid 0 0') # Invalid argument
335 with pytest.raises(TurtleShortcutException):
336 sc(f'{name} 0 invalid 0') # Invalid argument
337 with pytest.raises(TurtleShortcutException):
338 sc(f'{name} 0 0 invalid') # Invalid argument
341 colormode(1.0) # Set to 1.0 for testing
343 pencolor('black') # Reset to black
344 assert sc(f'{name} red') == 1
345 assert pencolor() == 'red'
347 pencolor('black') # Reset to black
348 assert sc(f'{name} red') == 1
349 assert pencolor() == 'red'
351 pencolor('black') # Reset to black
352 assert sc(f'{name} 1 0 0') == 1
353 assert pencolor() == (1.0, 0.0, 0.0)
355 pencolor('black') # Reset to black
356 assert sc(f'{name} 1.0 0.0 0.0') == 1
357 assert pencolor() == (1.0, 0.0, 0.0)
359 pencolor('black') # Reset to black
360 assert sc(f'{name} 255 0 0') == 1 # Test that temporarily setting colormode to 255 works.
361 assert pencolor() == (1.0, 0.0, 0.0)
363 colormode(255) # Test that temporarily setting colormode to 1 works.
364 assert sc(f'{name} 0 1.0 0') == 1
365 colormode(1.0)
366 assert pencolor() == (0, 1, 0)
368 for color_name in 'black blue brown orange gray grey green purple violet pink yellow white red magenta cyan'.split():
369 assert sc(f'{name} {color_name}') == 1
370 assert pencolor() == color_name
372 colormode(255)
373 assert sc(f'{name} FF0000') == 1
374 assert pencolor() == (255, 0, 0.0)
376 colormode(1)
377 assert sc(f'{name} FF0000') == 1
378 assert pencolor() == (1, 0, 0.0)
380 with pytest.raises(TurtleShortcutException):
381 sc(f'{name} xxyyzz') # Invalid color name
384def test_fillcolor():
385 for name in ('fc', 'fillcolor', 'FC', 'FILLCOLOR', 'fIlLcOlOr'):
386 with pytest.raises(TurtleShortcutException):
387 sc(f'{name}') # Missing argument
389 with pytest.raises(TurtleShortcutException):
390 sc(f'{name} 1 2') # Missing argument
392 with pytest.raises(TurtleShortcutException):
393 sc(f'{name} invalid 0 0') # Invalid argument
394 with pytest.raises(TurtleShortcutException):
395 sc(f'{name} 0 invalid 0') # Invalid argument
396 with pytest.raises(TurtleShortcutException):
397 sc(f'{name} 0 0 invalid') # Invalid argument
400 colormode(1.0) # Set to 1.0 for testing
402 fillcolor('black') # Reset to black
403 assert sc(f'{name} red') == 1
404 assert fillcolor() == 'red'
406 fillcolor('black') # Reset to black
407 assert sc(f'{name} red') == 1
408 assert fillcolor() == 'red'
410 fillcolor('black') # Reset to black
411 assert sc(f'{name} 1 0 0') == 1
412 assert fillcolor() == (1.0, 0.0, 0.0)
414 fillcolor('black') # Reset to black
415 assert sc(f'{name} 1.0 0.0 0.0') == 1
416 assert fillcolor() == (1.0, 0.0, 0.0)
418 pencolor('black') # Reset to black
419 assert sc(f'{name} 255 0 0') == 1 # Test that temporarily setting colormode to 255 works.
420 assert fillcolor() == (1.0, 0.0, 0.0)
422 colormode(255) # Test that temporarily setting colormode to 1 works.
423 assert sc(f'{name} 0 1.0 0') == 1
424 colormode(1.0)
425 assert fillcolor() == (0, 1, 0)
427 for color_name in 'black blue brown orange gray grey green purple violet pink yellow white red magenta cyan'.split():
428 assert sc(f'{name} {color_name}') == 1
429 assert fillcolor() == color_name
431 colormode(255)
432 assert sc(f'{name} FF0000') == 1
433 assert fillcolor() == (255, 0, 0.0)
435 with pytest.raises(TurtleShortcutException):
436 sc(f'{name} xxyyzz') # Invalid color name
439def test_bgcolor():
440 for name in ('bc', 'bgcolor', 'BC', 'BGCOLOR', 'bGcOlOr'):
441 with pytest.raises(TurtleShortcutException):
442 sc(f'{name}') # Missing argument
444 with pytest.raises(TurtleShortcutException):
445 sc(f'{name} 1 2') # Missing argument
447 with pytest.raises(TurtleShortcutException):
448 sc(f'{name} invalid 0 0') # Invalid argument
449 with pytest.raises(TurtleShortcutException):
450 sc(f'{name} 0 invalid 0') # Invalid argument
451 with pytest.raises(TurtleShortcutException):
452 sc(f'{name} 0 0 invalid') # Invalid argument
455 colormode(1.0) # Set to 1.0 for testing
457 bgcolor('black') # Reset to black
458 assert sc(f'{name} red') == 1
459 assert bgcolor() == 'red'
461 bgcolor('black') # Reset to black
462 assert sc(f'{name} red') == 1
463 assert bgcolor() == 'red'
465 bgcolor('black') # Reset to black
466 assert sc(f'{name} 1 0 0') == 1
467 assert bgcolor() == (1.0, 0.0, 0.0)
469 bgcolor('black') # Reset to black
470 assert sc(f'{name} 1.0 0.0 0.0') == 1
471 assert bgcolor() == (1.0, 0.0, 0.0)
473 bgcolor('black') # Reset to black
474 assert sc(f'{name} 255 0 0') == 1 # Test that temporarily setting colormode to 255 works.
475 assert bgcolor() == (1.0, 0.0, 0.0)
477 colormode(255) # Test that temporarily setting colormode to 1 works.
478 assert sc(f'{name} 0 1.0 0') == 1
479 colormode(1.0)
480 assert bgcolor() == (0, 1, 0)
482 for color_name in 'black blue brown orange gray grey green purple violet pink yellow white red magenta cyan'.split():
483 assert sc(f'{name} {color_name}') == 1
484 assert bgcolor() == color_name
486 colormode(255)
487 assert sc(f'{name} FF0000') == 1
488 assert bgcolor() == (255, 0, 0.0)
490 with pytest.raises(TurtleShortcutException):
491 sc(f'{name} xxyyzz') # Invalid color name
494def test_circle():
495 for name in ('cir', 'circle', 'CIR', 'CIRCLE', 'cIrClE'):
496 reset()
498 with pytest.raises(TurtleShortcutException):
499 sc(f'{name}') # Missing argument
500 with pytest.raises(TurtleShortcutException):
501 sc(f'{name} 1 2') # Too many arguments
502 with pytest.raises(TurtleShortcutException):
503 sc(f'{name} invalid') # Invalid argument
505 # The (int(pos()[0]), int(pos()[1])) stuff is because Vec2D objects
506 # returned from pos() consider (-0.00, -0.00) as not equal to (0, 0).
508 assert sc(f'{name} 1') == 1
509 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
511 assert sc(f'{name} 10') == 1
512 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
514 assert sc(f'{name} 10.5') == 1
515 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
517 assert sc(f'{name} -1') == 1
518 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
520 assert sc(f'{name} -10') == 1
521 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
523 assert sc(f'{name} -10.5') == 1
524 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
526 assert sc(f'{name} 0') == 1
527 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
530def test_undo():
531 for name in ('undo', 'UNDO', 'uNdO'):
532 reset()
534 with pytest.raises(TurtleShortcutException):
535 sc(f'{name} 1') # Too many arguments
537 assert sc(f'{name}') == 1
540def test_begin_fill_end():
541 for name in ('bf', 'begin_fill', 'BF', 'BEGIN_FILL', 'bEgIn_FiLl'):
542 with pytest.raises(TurtleShortcutException):
543 sc(f'{name} 1') # Too many arguments
545 assert sc(f'{name}') == 1
546 end_fill()
549def test_end_fill():
550 for name in ('ef', 'end_fill', 'EF', 'END_FILL', 'eNd_FiLl'):
551 with pytest.raises(TurtleShortcutException):
552 sc(f'{name} 1') # Too many arguments
554 begin_fill()
555 assert sc(f'{name}') == 1
558def test_reset():
559 for name in ('reset', 'RESET', 'rEsEt'):
560 with pytest.raises(TurtleShortcutException):
561 sc(f'{name} 1') # Too many arguments
563 assert sc(f'{name}') == 1
566def test_sleep_sc():
567 for name in ('sleep', 'SLEEP', 'sLeEp'):
568 with pytest.raises(TurtleShortcutException):
569 sc(f'{name}')
574def test_move_turn():
575 # Test the move and turn commands:
577 # Test home/h:
578 goto(1, 0)
579 assert sc('h') == 1
580 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
582 goto(1, 0)
583 assert sc('home') == 1
584 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
586 with pytest.raises(TurtleShortcutException):
587 sc('h 1')
589 # Test f/b forward/backward l/r left/right:
590 assert sc('f 1') == 1
591 assert (int(pos()[0]), int(pos()[1])) == (1, 0)
593 assert sc('forward 1') == 1
594 assert (int(pos()[0]), int(pos()[1])) == (2, 0)
596 assert sc('b 1') == 1
597 assert (int(pos()[0]), int(pos()[1])) == (1, 0)
599 assert sc('backward 1') == 1
600 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
602 assert sc('l 90') == 1
603 assert heading() == 90
605 assert sc('left 90') == 1
606 assert heading() == 180
608 assert sc('r 90') == 1
609 assert heading() == 90
611 assert sc('right 90') == 1
612 assert heading() == 0
614 assert sc('sh 42') == 1
615 assert heading() == 42
616 assert sc('sh 0') == 1
617 assert heading() == 0
619 assert sc('f -1') == 1
620 assert (int(pos()[0]), int(pos()[1])) == (-1, 0)
622 assert sc('b -1') == 1
623 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
625 assert sc('l -90') == 1
626 assert heading() == 270
628 assert sc('r -90') == 1
629 assert heading() == 0
631 assert sc('r 0') == 1
632 assert heading() == 0
634 assert sc('r 360') == 1
635 assert heading() == 0
637 assert sc('r 720') == 1
638 assert heading() == 0
640 assert sc('r -360') == 1
641 assert heading() == 0
643 assert sc('r -720') == 1
644 assert heading() == 0
646 assert sc('l 0') == 1
647 assert heading() == 0
649 assert sc('l 360') == 1
650 assert heading() == 0
652 assert sc('l 720') == 1
653 assert heading() == 0
655 assert sc('l -360') == 1
656 assert heading() == 0
658 assert sc('l -720') == 1
659 assert heading() == 0
661 assert sc('c') == 1
662 assert sc('clear') == 1
664 # Test g and goto:
665 assert sc('g 10 20') == 1
666 assert (int(pos()[0]), int(pos()[1])) == (10, 20)
668 assert sc('goto -30 -40') == 1
669 assert (int(pos()[0]), int(pos()[1])) == (-30, -40)
671 with pytest.raises(TurtleShortcutException):
672 sc('goto 10')
674 with pytest.raises(TurtleShortcutException):
675 sc('goto 10 invalid')
677 with pytest.raises(TurtleShortcutException):
678 sc('goto invalid 20')
680 with pytest.raises(TurtleShortcutException):
681 sc('goto invalid invalid')
683 with pytest.raises(TurtleShortcutException):
684 sc('g')
686 assert sc('x 100') == 1
687 assert (int(pos()[0]), int(pos()[1])) == (100, -40)
689 assert sc('y 200') == 1
690 assert (int(pos()[0]), int(pos()[1])) == (100, 200)
692 assert sc('setx 300') == 1
693 assert (int(pos()[0]), int(pos()[1])) == (300, 200)
695 assert sc('sety 400') == 1
696 assert (int(pos()[0]), int(pos()[1])) == (300, 400)
698 with pytest.raises(TurtleShortcutException):
699 sc('setx invalid')
701 with pytest.raises(TurtleShortcutException):
702 sc('sety invalid')
704 with pytest.raises(TurtleShortcutException):
705 sc('x invalid')
707 with pytest.raises(TurtleShortcutException):
708 sc('y invalid')
710def test_cardinal_directions_nsew():
711 # Test calling a function while in radians mode:
712 reset()
713 radians()
714 assert sc(f'n 100') == 1
715 assert (int(pos()[0]), int(pos()[1])) == (0, 100)
716 degrees()
718 for n, s, e, w, nw, ne, sw, se in ('n s e w nw ne sw se'.split(),
719 'north south east west northwest northeast southwest southeast'.split(),
720 'N S E W NW NE SW SE'.split(),
721 'NORTH SOUTH EAST WEST NORTHWEST NORTHEAST SOUTHWEST SOUTHEAST'.split()):
722 reset()
723 assert sc(f'{n} 100') == 1
724 assert (int(pos()[0]), int(pos()[1])) == (0, 100)
725 assert sc(f'{n} -100') == 1
726 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
728 reset()
729 assert sc(f'{s} 100') == 1
730 assert (int(pos()[0]), int(pos()[1])) == (0, -100)
731 assert sc(f'{s} -100') == 1
732 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
734 reset()
735 assert sc(f'{e} 100') == 1
736 assert (int(pos()[0]), int(pos()[1])) == (100, 0)
737 assert sc(f'{e} -100') == 1
738 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
740 reset()
741 assert sc(f'{w} 100') == 1
742 assert (int(pos()[0]), int(pos()[1])) == (-100, 0)
743 assert sc(f'{w} -100') == 1
744 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
746 reset()
747 assert sc(f'{nw} 100') == 1
748 assert (int(pos()[0]), int(pos()[1])) == (-70, 70)
749 assert sc(f'{nw} -100') == 1
750 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
752 reset()
753 assert sc(f'{ne} 100') == 1
754 assert (int(pos()[0]), int(pos()[1])) == (70, 70)
755 assert sc(f'{ne} -100') == 1
756 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
758 reset()
759 assert sc(f'{sw} 100') == 1
760 assert (int(pos()[0]), int(pos()[1])) == (-70, -70)
761 assert sc(f'{sw} -100') == 1
762 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
764 reset()
765 assert sc(f'{se} 100') == 1
766 assert (int(pos()[0]), int(pos()[1])) == (70, -70)
767 assert sc(f'{se} -100') == 1
768 assert (int(pos()[0]), int(pos()[1])) == (0, 0)
771def test_sleep():
772 with pytest.raises(TurtleShortcutException):
773 sc('sleep') # Missing argument
774 with pytest.raises(TurtleShortcutException):
775 sc('sleep 1 2') # Too many arguments
776 with pytest.raises(TurtleShortcutException):
777 sc('sleep invalid') # Invalid argument
779 assert sc('sleep 1') == 1
780 assert sc('sleep 0.1') == 1
782def test_tracer_update():
783 orig_tracer = tracer()
784 orig_delay = delay()
786 for name in ('t', 'T', 'tracer', 'TRACER', 'tRaCeR'):
787 with pytest.raises(TurtleShortcutException):
788 sc('{name}') # Missing argument
789 with pytest.raises(TurtleShortcutException):
790 sc('{name} 1 2 3') # Too many arguments
791 with pytest.raises(TurtleShortcutException):
792 sc('{name} invalid 0')
793 with pytest.raises(TurtleShortcutException):
794 sc('{name} 0 invalid')
796 assert sc(f'{name} 123 1') == 1
797 assert tracer() == 123
798 assert delay() == 1
800 for name in ('u', 'U', 'update', 'UPDATE', 'uPdAtE'):
801 with pytest.raises(TurtleShortcutException):
802 sc('{name} 1') # Too many arguments
804 assert sc(f'{name}') == 1
806 tracer(orig_tracer, orig_delay)
809def test_show_hide():
810 for name in ('show', 'SHOW', 'sHoW'):
811 with pytest.raises(TurtleShortcutException):
812 sc(f'{name} 1') # Too many arguments
814 assert sc(f'{name}') == 1
815 assert isvisible()
817 for name in ('hide', 'HIDE', 'hIdE'):
818 with pytest.raises(TurtleShortcutException):
819 sc(f'{name} 1') # Too many arguments
821 assert sc(f'{name}') == 1
822 assert not isvisible()
825def test_dot():
826 for name in ('dot', 'DOT', 'dOt'):
827 with pytest.raises(TurtleShortcutException):
828 sc(f'{name}') # Missing argument
829 with pytest.raises(TurtleShortcutException):
830 sc(f'{name} 1 2') # Too many arguments
831 with pytest.raises(TurtleShortcutException):
832 sc(f'{name} invalid') # Invalid argument
833 with pytest.raises(TurtleShortcutException):
834 sc(f'{name} -1') # Invalid argument
837 assert sc(f'{name} 1') == 1
838 assert sc(f'{name} 10') == 1
839 assert sc(f'{name} 10.5') == 1
840 assert sc(f'{name} 0') == 1
843def test_clearstamp():
844 for name in ('cs', 'clearstamp', 'CS', 'CLEARSTAMP', 'cLeArStAmP'):
845 with pytest.raises(TurtleShortcutException):
846 sc(f'{name} 1 2') # Too many arguments
847 with pytest.raises(TurtleShortcutException):
848 sc(f'{name}') # Missing argument
849 with pytest.raises(TurtleShortcutException):
850 sc(f'{name} invalid') # Invalid argument
852 stamp_id = stamp()
853 assert sc(f'{name} {stamp_id}') == 1
856def test_clearstamps():
857 for name in ('css', 'clearstamps', 'CSS', 'CLEARSTAMPS', 'cLeArStAmPs'):
858 with pytest.raises(TurtleShortcutException):
859 sc(f'{name} 1 2') # Too many arguments
860 with pytest.raises(TurtleShortcutException):
861 sc(f'{name} invalid') # Invalid argument
863 assert sc(f'{name} 0') == 1
864 assert sc(f'{name} 2') == 1
865 assert sc(f'{name} -2') == 1
866 assert sc(f'{name}') == 1
868def test_speed():
869 for name in ('speed', 'SPEED', 'sPeEd'):
870 with pytest.raises(TurtleShortcutException):
871 sc(f'{name}') # Missing argument
872 with pytest.raises(TurtleShortcutException):
873 sc(f'{name} 1 2') # Too many arguments
874 with pytest.raises(TurtleShortcutException):
875 sc(f'{name} invalid') # Invalid argument
877 # Test numeric settings 0 to 10:
878 for speed_setting in tuple(range(11)):
879 assert sc(f'{name} {speed_setting}') == 1
880 assert speed() == speed_setting
881 # Test string settings:
882 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():
883 assert sc(f'{name} {speed_setting}') == 1
884 assert speed() == numeric_equivalent
886 tracer(10000, 0) # Restore the original tracer settings for other tests.
889def test_get_turtle_code():
890 assert get_turtle_code('f 100') == ('forward(100)',)
891 assert get_turtle_code('b 100') == ('backward(100)',)
892 assert get_turtle_code('l 90') == ('left(90)',)
893 assert get_turtle_code('r 90') == ('right(90)',)
894 assert get_turtle_code('g 100 200') == ('goto(100, 200)',)
895 assert get_turtle_code('sh 90') == ('setheading(90)',)
896 assert get_turtle_code('pu') == ('penup()',)
897 assert get_turtle_code('pd') == ('pendown()',)
898 assert get_turtle_code('ps 10') == ('pensize(10)',)
899 assert get_turtle_code('bf') == ('begin_fill()',)
900 assert get_turtle_code('ef') == ('end_fill()',)
901 assert get_turtle_code('reset') == ('reset()',)
902 assert get_turtle_code('sleep 1') == ('sleep(1)',)
903 assert get_turtle_code('t 100 0') == ('tracer(100, 0)',)
904 assert get_turtle_code('u') == ('update()',)
905 assert get_turtle_code('show') == ('showturtle()',)
906 assert get_turtle_code('hide') == ('hideturtle()',)
907 assert get_turtle_code('dot 10') == ('dot(10)',)
908 assert get_turtle_code('cs 1') == ('clearstamp(1)',)
909 assert get_turtle_code('css') == ('clearstamps()',)
910 assert get_turtle_code('css 1') == ('clearstamps(1)',)
911 assert get_turtle_code('st') == ('stamp()',)
912 assert get_turtle_code('speed 1') == ('speed(1)',)
913 assert get_turtle_code('home') == ('home()',)
914 assert get_turtle_code('x 100') == ('setx(100)',)
915 assert get_turtle_code('y 100') == ('sety(100)',)
916 assert get_turtle_code('setx 100') == ('setx(100)',)
917 assert get_turtle_code('sety 100') == ('sety(100)',)
918 assert get_turtle_code('c') == ('clear()',)
919 assert get_turtle_code('undo') == ('undo()',)
920 assert get_turtle_code('cir 100') == ('circle(100)',)
921 assert get_turtle_code('g 100 200') == ('goto(100, 200)',)
922 assert get_turtle_code('tele 100 200') == ('teleport(100, 200)',)
924 assert get_turtle_code('pc red') == ("pencolor('red')",)
925 assert get_turtle_code('fc red') == ("fillcolor('red')",)
926 assert get_turtle_code('bc red') == ("bgcolor('red')",)
928 colormode(255)
929 assert get_turtle_code('pc red') == ("pencolor('red')",)
930 assert get_turtle_code('pc 255 0 0') == ('pencolor((255.0, 0.0, 0.0))',)
931 assert get_turtle_code('fc 255 0 0') == ('fillcolor((255.0, 0.0, 0.0))',)
932 assert get_turtle_code('bc 255 0 0') == ('bgcolor((255.0, 0.0, 0.0))',)
934 assert get_turtle_code('pc 1.0 0.0 0.0') == ('colormode(1.0)', 'pencolor((1.0, 0.0, 0.0))', 'colormode(255)')
935 assert get_turtle_code('fc 1.0 0.0 0.0') == ('colormode(1.0)', 'fillcolor((1.0, 0.0, 0.0))', 'colormode(255)')
936 assert get_turtle_code('bc 1.0 0.0 0.0') == ('colormode(1.0)', 'bgcolor((1.0, 0.0, 0.0))', 'colormode(255)')
938 colormode(1.0)
939 assert get_turtle_code('pc red') == ("pencolor('red')",)
940 assert get_turtle_code('pc 255 0 0') == ('colormode(255)', 'pencolor((255, 0, 0))', 'colormode(1.0)')
941 assert get_turtle_code('fc 255 0 0') == ('colormode(255)', 'fillcolor((255, 0, 0))', 'colormode(1.0)')
942 assert get_turtle_code('bc 255 0 0') == ('colormode(255)', 'bgcolor((255, 0, 0))', 'colormode(1.0)')
944 assert get_turtle_code('pc 1.0 0.0 0.0') == ('pencolor((1.0, 0.0, 0.0))',)
945 assert get_turtle_code('fc 1.0 0.0 0.0') == ('fillcolor((1.0, 0.0, 0.0))',)
946 assert get_turtle_code('bc 1.0 0.0 0.0') == ('bgcolor((1.0, 0.0, 0.0))',)
950 degrees()
951 assert get_turtle_code('n 100') == ('setheading(90)', 'forward(100)')
952 assert get_turtle_code('s 100') == ('setheading(270)', 'forward(100)')
953 assert get_turtle_code('e 100') == ('setheading(0)', 'forward(100)')
954 assert get_turtle_code('w 100') == ('setheading(180)', 'forward(100)')
955 assert get_turtle_code('nw 100') == ('setheading(135)', 'forward(100)')
956 assert get_turtle_code('ne 100') == ('setheading(45)', 'forward(100)')
957 assert get_turtle_code('sw 100') == ('setheading(225)', 'forward(100)')
958 assert get_turtle_code('se 100') == ('setheading(315)', 'forward(100)')
959 assert get_turtle_code('north 100') == ('setheading(90)', 'forward(100)')
960 assert get_turtle_code('south 100') == ('setheading(270)', 'forward(100)')
961 assert get_turtle_code('east 100') == ('setheading(0)', 'forward(100)')
962 assert get_turtle_code('west 100') == ('setheading(180)', 'forward(100)')
963 assert get_turtle_code('northwest 100') == ('setheading(135)', 'forward(100)')
964 assert get_turtle_code('northeast 100') == ('setheading(45)', 'forward(100)')
965 assert get_turtle_code('southwest 100') == ('setheading(225)', 'forward(100)')
966 assert get_turtle_code('southeast 100') == ('setheading(315)', 'forward(100)')
967 assert get_turtle_code('N 100') == ('setheading(90)', 'forward(100)')
968 assert get_turtle_code('S 100') == ('setheading(270)', 'forward(100)')
969 assert get_turtle_code('E 100') == ('setheading(0)', 'forward(100)')
970 assert get_turtle_code('W 100') == ('setheading(180)', 'forward(100)')
971 assert get_turtle_code('NW 100') == ('setheading(135)', 'forward(100)')
972 assert get_turtle_code('NE 100') == ('setheading(45)', 'forward(100)')
973 assert get_turtle_code('SW 100') == ('setheading(225)', 'forward(100)')
974 assert get_turtle_code('SE 100') == ('setheading(315)', 'forward(100)')
975 assert get_turtle_code('NORTH 100') == ('setheading(90)', 'forward(100)')
976 assert get_turtle_code('SOUTH 100') == ('setheading(270)', 'forward(100)')
977 assert get_turtle_code('EAST 100') == ('setheading(0)', 'forward(100)')
978 assert get_turtle_code('WEST 100') == ('setheading(180)', 'forward(100)')
979 assert get_turtle_code('NORTHWEST 100') == ('setheading(135)', 'forward(100)')
980 assert get_turtle_code('NORTHEAST 100') == ('setheading(45)', 'forward(100)')
981 assert get_turtle_code('SOUTHWEST 100') == ('setheading(225)', 'forward(100)')
982 assert get_turtle_code('SOUTHEAST 100') == ('setheading(315)', 'forward(100)')
983 assert get_turtle_code('n 100, f 100') == ('setheading(90)', 'forward(100)', 'forward(100)')
984 assert get_turtle_code('n 100, f 100, f 100') == ('setheading(90)', 'forward(100)', 'forward(100)', 'forward(100)')
986 radians()
987 assert get_turtle_code('n 100') == ('degrees()', 'setheading(90)', 'forward(100)', 'radians()')
988 assert get_turtle_code('s 100') == ('degrees()', 'setheading(270)', 'forward(100)', 'radians()')
989 assert get_turtle_code('e 100') == ('degrees()', 'setheading(0)', 'forward(100)', 'radians()')
990 assert get_turtle_code('w 100') == ('degrees()', 'setheading(180)', 'forward(100)', 'radians()')
991 assert get_turtle_code('nw 100') == ('degrees()', 'setheading(135)', 'forward(100)', 'radians()')
992 assert get_turtle_code('ne 100') == ('degrees()', 'setheading(45)', 'forward(100)', 'radians()')
993 assert get_turtle_code('sw 100') == ('degrees()', 'setheading(225)', 'forward(100)', 'radians()')
994 assert get_turtle_code('se 100') == ('degrees()', 'setheading(315)', 'forward(100)', 'radians()')
996 degrees()
1004# EXAMPLE PROGRAMS:
1006def test_colorful_squares():
1007 sc('t 1000 0, ps 4')
1009 for i in range(100): # Draw 100 squares.
1010 # Move to a random place:
1011 sc(f'pu,g {randint(-400, 200)} {randint(-400, 200)},pd,fc {random()} {random()} {random()}, pc {random()} {random()} {random()}')
1012 line_length = randint(20, 200)
1014 # Draw the filled-in square:
1015 sc('bf')
1016 for j in range(4):
1017 sc(f'f {line_length}, l 90')
1018 sc('ef')
1020 sc('u')
1021 sc('reset')
1024def test_draw_circles():
1025 # Draw circle in the top half of the window:
1026 sc('sh 0') # Face right.
1027 for i in range(20):
1028 sc(f'cir {i * 10}')
1030 # Draw circles in the bottom half of the window:
1031 sc('sh 180') # Face left.
1032 for i in range(20):
1033 sc(f'cir {i * 10}')
1034 sc('u')
1035 sc('reset')
1038def test_curve_path_filled():
1039 for i in range(50):
1040 sc(f'fc {random()} {random()} {random()}')
1042 # Set a random heading and draw several short lines with changing direction:
1043 sc(f'sh {randint(0, 360)}, bf')
1045 for j in range(randint(200, 600)):
1046 sc(f'f 1,l {randint(-4, 4)}')
1047 sc(f'h, ef')
1048 sc('u')
1049 sc('reset')
1052if __name__ == '__main__':
1053 pytest.main()