Coverage for tests/test_turtlesc.py: 100%

914 statements  

« prev     ^ index     » next       coverage.py v7.7.0, created at 2025-04-01 13:58 -0400

1import pytest 

2from turtle import * 

3from turtlesc import * 

4from random import * 

5 

6seed(42) # Keep at 42 for reproducible tests (dependent on which tests are run and in what order, anyway) 

7tracer(10000, 0) 

8 

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 

17 

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') 

27 

28 assert sc('f 1, f -1') == 2 

29 

30def test_in_radians_mode(): 

31 radians() 

32 assert in_radians_mode() 

33 degrees() 

34 assert not in_radians_mode() 

35 

36 

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. 

43 

44 

45def test_forward(): 

46 turtle.reset() 

47 

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 

55 

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) 

66 

67 

68def test_backward(): 

69 turtle.reset() 

70 

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 

78 

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) 

89 

90 

91def test_right(): 

92 turtle.reset() 

93 

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 

101 

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 

112 

113 

114def test_left(): 

115 turtle.reset() 

116 

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 

124 

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 

135 

136 

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 

145 

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 

156 

157 

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 

162 

163 assert sc(f'{name}') == 1 

164 assert pos() == (0, 0) 

165 assert heading() == 0 

166 

167 

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 

172 

173 assert sc(f'{name}') == 1 

174 

175 

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') 

188 

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) 

199 

200 

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') 

213 

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) 

224 

225 

226def test_setx(): 

227 for name in ('x', 'setx', 'X', 'SETX', 'sEtX'): 

228 reset() 

229 

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 

236 

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) 

245 

246 sety(10) 

247 assert sc(f'{name} 1') == 1 

248 assert pos() == (1, 10) 

249 

250 

251def test_sety(): 

252 for name in ('y', 'sety', 'Y', 'SETY', 'sEtY'): 

253 reset() 

254 

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 

261 

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) 

270 

271 setx(10) 

272 assert sc(f'{name} 1') == 1 

273 assert pos() == (10, 1) 

274 

275 

276 

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 

281 

282 penup() 

283 assert sc(f'{name}') == 1 

284 assert isdown() 

285 

286 

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 

291 

292 pendown() 

293 assert sc(f'{name}') == 1 

294 assert not isdown() 

295 

296 

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 

305 

306 assert sc(f'{name} 10') == 1 

307 assert pensize() == 10 

308 

309 assert sc(f'{name} 1.5') == 1 

310 assert pensize() == 1.5 

311 

312 pensize(1) 

313 

314 

315def test_stamp(): 

316 for name in ('st', 'stamp', 'ST', 'STAMP', 'sTaMp'): 

317 reset() 

318 

319 with pytest.raises(TurtleShortcutException): 

320 sc(f'{name} 1') # Too many arguments 

321 

322 assert sc(f'{name}') == 1 

323 

324 

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 

334 

335 with pytest.raises(TurtleShortcutException): 

336 sc(f'{name}') # Missing argument 

337 

338 with pytest.raises(TurtleShortcutException): 

339 sc(f'{name} 1 2') # Too many arguments 

340 

341 with pytest.raises(TurtleShortcutException): 

342 sc(f'{name} FF0000') # Missing the leading # for hex colors 

343 

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 

350 

351 

352 colormode(1.0) # Set to 1.0 for testing 

353 

354 function_to_test('black') # Reset to black 

355 assert sc(f'{name} red') == 1 

356 assert function_to_test() == 'red' 

357 

358 function_to_test('black') # Reset to black 

359 assert sc(f'{name} red') == 1 

360 assert function_to_test() == 'red' 

361 

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) 

365 

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) 

369 

370 with pytest.raises(TurtleShortcutException): 

371 sc(f'{name} 255 0 0') 

372 

373 colormode(1.0) 

374 assert function_to_test() != (0, 255, 0) # Make sure it's not returning a 255 mode value. 

375 

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 # Set the color 

380 assert function_to_test() == color_name # Test that the color was set 

381 

382 colormode(255) 

383 assert sc(f'{name} #FF0000') == 1 

384 assert function_to_test() == (255, 0, 0.0) 

385 

386 colormode(1) 

387 assert sc(f'{name} #FF0000') == 1 

388 assert function_to_test() == (1, 0, 0.0) 

389 

390 with pytest.raises(TurtleShortcutException): 

391 sc(f'{name} xxyyzz') # Invalid color name 

392 

393 

394 

395def test_circle(): 

396 for name in ('cir', 'circle', 'CIR', 'CIRCLE', 'cIrClE'): 

397 reset() 

398 

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 

405 

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). 

408 

409 assert sc(f'{name} 1') == 1 

410 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

411 

412 assert sc(f'{name} 10') == 1 

413 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

414 

415 assert sc(f'{name} 10.5') == 1 

416 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

417 

418 assert sc(f'{name} -1') == 1 

419 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

420 

421 assert sc(f'{name} -10') == 1 

422 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

423 

424 assert sc(f'{name} -10.5') == 1 

425 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

426 

427 assert sc(f'{name} 0') == 1 

428 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

429 

430 

431def test_undo(): 

432 for name in ('undo', 'UNDO', 'uNdO'): 

433 reset() 

434 

435 with pytest.raises(TurtleShortcutException): 

436 sc(f'{name} 1') # Too many arguments 

437 

438 assert sc(f'{name}') == 1 

439 

440 

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 

445 

446 assert sc(f'{name}') == 1 

447 end_fill() 

448 

449 

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 

454 

455 begin_fill() 

456 assert sc(f'{name}') == 1 

457 

458 

459def test_reset(): 

460 for name in ('reset', 'RESET', 'rEsEt'): 

461 with pytest.raises(TurtleShortcutException): 

462 sc(f'{name} 1') # Too many arguments 

463 

464 assert sc(f'{name}') == 1 

465 

466 

467def test_sleep_sc(): 

468 for name in ('sleep', 'SLEEP', 'sLeEp'): 

469 with pytest.raises(TurtleShortcutException): 

470 sc(f'{name}') 

471 

472 

473 

474 

475def test_move_turn(): 

476 # Test the move and turn commands: 

477 

478 # Test home/h: 

479 goto(1, 0) 

480 assert sc('h') == 1 

481 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

482 

483 goto(1, 0) 

484 assert sc('home') == 1 

485 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

486 

487 with pytest.raises(TurtleShortcutException): 

488 sc('h 1') 

489 

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) 

493 

494 assert sc('forward 1') == 1 

495 assert (int(pos()[0]), int(pos()[1])) == (2, 0) 

496 

497 assert sc('b 1') == 1 

498 assert (int(pos()[0]), int(pos()[1])) == (1, 0) 

499 

500 assert sc('backward 1') == 1 

501 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

502 

503 assert sc('l 90') == 1 

504 assert heading() == 90 

505 

506 assert sc('left 90') == 1 

507 assert heading() == 180 

508 

509 assert sc('r 90') == 1 

510 assert heading() == 90 

511 

512 assert sc('right 90') == 1 

513 assert heading() == 0 

514 

515 assert sc('sh 42') == 1 

516 assert heading() == 42 

517 assert sc('sh 0') == 1 

518 assert heading() == 0 

519 

520 assert sc('f -1') == 1 

521 assert (int(pos()[0]), int(pos()[1])) == (-1, 0) 

522 

523 assert sc('b -1') == 1 

524 assert (int(pos()[0]), int(pos()[1])) == (0, 0) 

525 

526 assert sc('l -90') == 1 

527 assert heading() == 270 

528 

529 assert sc('r -90') == 1 

530 assert heading() == 0 

531 

532 assert sc('r 0') == 1 

533 assert heading() == 0 

534 

535 assert sc('r 360') == 1 

536 assert heading() == 0 

537 

538 assert sc('r 720') == 1 

539 assert heading() == 0 

540 

541 assert sc('r -360') == 1 

542 assert heading() == 0 

543 

544 assert sc('r -720') == 1 

545 assert heading() == 0 

546 

547 assert sc('l 0') == 1 

548 assert heading() == 0 

549 

550 assert sc('l 360') == 1 

551 assert heading() == 0 

552 

553 assert sc('l 720') == 1 

554 assert heading() == 0 

555 

556 assert sc('l -360') == 1 

557 assert heading() == 0 

558 

559 assert sc('l -720') == 1 

560 assert heading() == 0 

561 

562 assert sc('c') == 1 

563 assert sc('clear') == 1 

564 

565 # Test g and goto: 

566 assert sc('g 10 20') == 1 

567 assert (int(pos()[0]), int(pos()[1])) == (10, 20) 

568 

569 assert sc('goto -30 -40') == 1 

570 assert (int(pos()[0]), int(pos()[1])) == (-30, -40) 

571 

572 with pytest.raises(TurtleShortcutException): 

573 sc('goto 10') 

574 

575 with pytest.raises(TurtleShortcutException): 

576 sc('goto 10 invalid') 

577 

578 with pytest.raises(TurtleShortcutException): 

579 sc('goto invalid 20') 

580 

581 with pytest.raises(TurtleShortcutException): 

582 sc('goto invalid invalid') 

583 

584 with pytest.raises(TurtleShortcutException): 

585 sc('g') 

586 

587 assert sc('x 100') == 1 

588 assert (int(pos()[0]), int(pos()[1])) == (100, -40) 

589 

590 assert sc('y 200') == 1 

591 assert (int(pos()[0]), int(pos()[1])) == (100, 200) 

592 

593 assert sc('setx 300') == 1 

594 assert (int(pos()[0]), int(pos()[1])) == (300, 200) 

595 

596 assert sc('sety 400') == 1 

597 assert (int(pos()[0]), int(pos()[1])) == (300, 400) 

598 

599 with pytest.raises(TurtleShortcutException): 

600 sc('setx invalid') 

601 

602 with pytest.raises(TurtleShortcutException): 

603 sc('sety invalid') 

604 

605 with pytest.raises(TurtleShortcutException): 

606 sc('x invalid') 

607 

608 with pytest.raises(TurtleShortcutException): 

609 sc('y invalid') 

610 

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() 

618 

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) 

628 

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) 

634 

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) 

640 

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) 

646 

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) 

652 

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) 

658 

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) 

664 

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) 

670 

671 

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 

679 

680 assert sc('sleep 1') == 1 

681 assert sc('sleep 0.1') == 1 

682 

683def test_tracer_update(): 

684 orig_tracer = tracer() 

685 orig_delay = delay() 

686 

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') 

696 

697 assert sc(f'{name} 123 1') == 1 

698 assert tracer() == 123 

699 assert delay() == 1 

700 

701 for name in ('u', 'U', 'update', 'UPDATE', 'uPdAtE'): 

702 with pytest.raises(TurtleShortcutException): 

703 sc('{name} 1') # Too many arguments 

704 

705 assert sc(f'{name}') == 1 

706 

707 tracer(orig_tracer, orig_delay) 

708 

709 

710def test_show_hide(): 

711 for name in ('show', 'SHOW', 'sHoW'): 

712 with pytest.raises(TurtleShortcutException): 

713 sc(f'{name} 1') # Too many arguments 

714 

715 assert sc(f'{name}') == 1 

716 assert isvisible() 

717 

718 for name in ('hide', 'HIDE', 'hIdE'): 

719 with pytest.raises(TurtleShortcutException): 

720 sc(f'{name} 1') # Too many arguments 

721 

722 assert sc(f'{name}') == 1 

723 assert not isvisible() 

724 

725 

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 

736 

737 

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 

742 

743 

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 

752 

753 stamp_id = stamp() 

754 assert sc(f'{name} {stamp_id}') == 1 

755 

756 

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 

763 

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 

768 

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 

777 

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 

786 

787 tracer(10000, 0) # Restore the original tracer settings for other tests. 

788 

789 

790def test_scs(): 

791 assert scs('f 100') == 'forward(100)' 

792 assert scs('b 100') == 'backward(100)' 

793 assert scs('l 90') == 'left(90)' 

794 assert scs('r 90') == 'right(90)' 

795 assert scs('g 100 200') == 'goto(100, 200)' 

796 assert scs('sh 90') == 'setheading(90)' 

797 assert scs('pu') == 'penup()' 

798 assert scs('pd') == 'pendown()' 

799 assert scs('ps 10') == 'pensize(10)' 

800 assert scs('bf') == 'begin_fill()' 

801 assert scs('ef') == 'end_fill()' 

802 assert scs('reset') == 'reset()' 

803 assert scs('sleep 1') == 'sleep(1)' 

804 assert scs('t 100 0') == 'tracer(100, 0)' 

805 assert scs('u') == 'update()' 

806 assert scs('show') == 'showturtle()' 

807 assert scs('hide') == 'hideturtle()' 

808 assert scs('dot 10') == 'dot(10)' 

809 assert scs('cs 1') == 'clearstamp(1)' 

810 assert scs('css') == 'clearstamps()' 

811 assert scs('css 1') == 'clearstamps(1)' 

812 assert scs('st') == 'stamp()' 

813 assert scs('speed 1') == 'speed(1)' 

814 assert scs('home') == 'home()' 

815 assert scs('x 100') == 'setx(100)' 

816 assert scs('y 100') == 'sety(100)' 

817 assert scs('setx 100') == 'setx(100)' 

818 assert scs('sety 100') == 'sety(100)' 

819 assert scs('c') == 'clear()' 

820 assert scs('undo') == 'undo()' 

821 assert scs('cir 100') == 'circle(100)' 

822 assert scs('g 100 200') == 'goto(100, 200)' 

823 assert scs('tele 100 200') == 'teleport(100, 200)' 

824 

825 assert scs('pc red') == "pencolor('red')" 

826 assert scs('fc red') == "fillcolor('red')" 

827 assert scs('bc red') == "bgcolor('red')" 

828 

829 colormode(255) 

830 assert scs('pc red') == "pencolor('red')" 

831 assert scs('pc 255 0 0') == 'pencolor((255, 0, 0))' 

832 assert scs('fc 255 0 0') == 'fillcolor((255, 0, 0))' 

833 assert scs('bc 255 0 0') == 'bgcolor((255, 0, 0))' 

834 

835 colormode(1.0) 

836 assert scs('pc red') == "pencolor('red')" 

837 with pytest.raises(TurtleShortcutException): 

838 scs('pc 255 0 0') 

839 with pytest.raises(TurtleShortcutException): 

840 scs('fc 255 0 0') 

841 with pytest.raises(TurtleShortcutException): 

842 scs('bc 255 0 0') 

843 

844 assert scs('pc 1.0 0.0 0.0') == 'pencolor((1.0, 0.0, 0.0))' 

845 assert scs('fc 1.0 0.0 0.0') == 'fillcolor((1.0, 0.0, 0.0))' 

846 assert scs('bc 1.0 0.0 0.0') == 'bgcolor((1.0, 0.0, 0.0))' 

847 

848 degrees() 

849 assert scs('n 100') == 'setheading(90)\nforward(100)' 

850 assert scs('s 100') == 'setheading(270)\nforward(100)' 

851 assert scs('e 100') == 'setheading(0)\nforward(100)' 

852 assert scs('w 100') == 'setheading(180)\nforward(100)' 

853 assert scs('nw 100') == 'setheading(135)\nforward(100)' 

854 assert scs('ne 100') == 'setheading(45)\nforward(100)' 

855 assert scs('sw 100') == 'setheading(225)\nforward(100)' 

856 assert scs('se 100') == 'setheading(315)\nforward(100)' 

857 assert scs('north 100') == 'setheading(90)\nforward(100)' 

858 assert scs('south 100') == 'setheading(270)\nforward(100)' 

859 assert scs('east 100') == 'setheading(0)\nforward(100)' 

860 assert scs('west 100') == 'setheading(180)\nforward(100)' 

861 assert scs('northwest 100') == 'setheading(135)\nforward(100)' 

862 assert scs('northeast 100') == 'setheading(45)\nforward(100)' 

863 assert scs('southwest 100') == 'setheading(225)\nforward(100)' 

864 assert scs('southeast 100') == 'setheading(315)\nforward(100)' 

865 assert scs('N 100') == 'setheading(90)\nforward(100)' 

866 assert scs('S 100') == 'setheading(270)\nforward(100)' 

867 assert scs('E 100') == 'setheading(0)\nforward(100)' 

868 assert scs('W 100') == 'setheading(180)\nforward(100)' 

869 assert scs('NW 100') == 'setheading(135)\nforward(100)' 

870 assert scs('NE 100') == 'setheading(45)\nforward(100)' 

871 assert scs('SW 100') == 'setheading(225)\nforward(100)' 

872 assert scs('SE 100') == 'setheading(315)\nforward(100)' 

873 assert scs('NORTH 100') == 'setheading(90)\nforward(100)' 

874 assert scs('SOUTH 100') == 'setheading(270)\nforward(100)' 

875 assert scs('EAST 100') == 'setheading(0)\nforward(100)' 

876 assert scs('WEST 100') == 'setheading(180)\nforward(100)' 

877 assert scs('NORTHWEST 100') == 'setheading(135)\nforward(100)' 

878 assert scs('NORTHEAST 100') == 'setheading(45)\nforward(100)' 

879 assert scs('SOUTHWEST 100') == 'setheading(225)\nforward(100)' 

880 assert scs('SOUTHEAST 100') == 'setheading(315)\nforward(100)' 

881 assert scs('n 100, f 100') == 'setheading(90)\nforward(100)\nforward(100)' 

882 assert scs('n 100, f 100, f 100') == 'setheading(90)\nforward(100)\nforward(100)\nforward(100)' 

883 

884 radians() 

885 assert scs('n 100') == 'degrees()\nsetheading(90)\nforward(100)\nradians()' 

886 assert scs('s 100') == 'degrees()\nsetheading(270)\nforward(100)\nradians()' 

887 assert scs('e 100') == 'degrees()\nsetheading(0)\nforward(100)\nradians()' 

888 assert scs('w 100') == 'degrees()\nsetheading(180)\nforward(100)\nradians()' 

889 assert scs('nw 100') == 'degrees()\nsetheading(135)\nforward(100)\nradians()' 

890 assert scs('ne 100') == 'degrees()\nsetheading(45)\nforward(100)\nradians()' 

891 assert scs('sw 100') == 'degrees()\nsetheading(225)\nforward(100)\nradians()' 

892 assert scs('se 100') == 'degrees()\nsetheading(315)\nforward(100)\nradians()' 

893 

894 degrees() 

895 

896 

897def test_psc(capsys): 

898 psc('f 100') 

899 assert capsys.readouterr().out == 'forward(100)\n' 

900 psc('b 100') 

901 assert capsys.readouterr().out == 'backward(100)\n' 

902 psc('l 90') 

903 assert capsys.readouterr().out == 'left(90)\n' 

904 psc('r 90') 

905 assert capsys.readouterr().out == 'right(90)\n' 

906 psc('g 100 200') 

907 assert capsys.readouterr().out == 'goto(100, 200)\n' 

908 psc('sh 90') 

909 assert capsys.readouterr().out == 'setheading(90)\n' 

910 psc('pu') 

911 assert capsys.readouterr().out == 'penup()\n' 

912 psc('pd') 

913 assert capsys.readouterr().out == 'pendown()\n' 

914 psc('ps 10') 

915 assert capsys.readouterr().out == 'pensize(10)\n' 

916 psc('bf') 

917 assert capsys.readouterr().out == 'begin_fill()\n' 

918 psc('ef') 

919 assert capsys.readouterr().out == 'end_fill()\n' 

920 psc('reset') 

921 assert capsys.readouterr().out == 'reset()\n' 

922 psc('sleep 1') 

923 assert capsys.readouterr().out == 'sleep(1)\n' 

924 psc('t 100 0') 

925 assert capsys.readouterr().out == 'tracer(100, 0)\n' 

926 psc('u') 

927 assert capsys.readouterr().out == 'update()\n' 

928 psc('show') 

929 assert capsys.readouterr().out == 'showturtle()\n' 

930 psc('hide') 

931 assert capsys.readouterr().out == 'hideturtle()\n' 

932 psc('dot 10') 

933 assert capsys.readouterr().out == 'dot(10)\n' 

934 psc('cs 1') 

935 assert capsys.readouterr().out == 'clearstamp(1)\n' 

936 psc('css') 

937 assert capsys.readouterr().out == 'clearstamps()\n' 

938 psc('css 1') 

939 assert capsys.readouterr().out == 'clearstamps(1)\n' 

940 psc('st') 

941 assert capsys.readouterr().out == 'stamp()\n' 

942 psc('speed 1') 

943 assert capsys.readouterr().out == 'speed(1)\n' 

944 psc('home') 

945 assert capsys.readouterr().out == 'home()\n' 

946 psc('x 100') 

947 assert capsys.readouterr().out == 'setx(100)\n' 

948 psc('y 100') 

949 assert capsys.readouterr().out == 'sety(100)\n' 

950 psc('setx 100') 

951 assert capsys.readouterr().out == 'setx(100)\n' 

952 psc('sety 100') 

953 assert capsys.readouterr().out == 'sety(100)\n' 

954 psc('c') 

955 assert capsys.readouterr().out == 'clear()\n' 

956 psc('undo') 

957 assert capsys.readouterr().out == 'undo()\n' 

958 psc('cir 100') 

959 assert capsys.readouterr().out == 'circle(100)\n' 

960 psc('g 100 200') 

961 assert capsys.readouterr().out == 'goto(100, 200)\n' 

962 psc('tele 100 200') 

963 assert capsys.readouterr().out == 'teleport(100, 200)\n' 

964 

965 psc('pc red') 

966 assert capsys.readouterr().out == "pencolor('red')\n" 

967 psc('fc red') 

968 assert capsys.readouterr().out == "fillcolor('red')\n" 

969 psc('bc red') 

970 assert capsys.readouterr().out == "bgcolor('red')\n" 

971 

972 colormode(255) 

973 psc('pc red') 

974 assert capsys.readouterr().out == "pencolor('red')\n" 

975 psc('pc 255 0 0') 

976 assert capsys.readouterr().out == 'pencolor((255, 0, 0))\n' 

977 psc('fc 255 0 0') 

978 assert capsys.readouterr().out == 'fillcolor((255, 0, 0))\n' 

979 psc('bc 255 0 0') 

980 assert capsys.readouterr().out == 'bgcolor((255, 0, 0))\n' 

981 

982 colormode(1.0) 

983 psc('pc red') 

984 assert capsys.readouterr().out == "pencolor('red')\n" 

985 with pytest.raises(TurtleShortcutException): 

986 psc('pc 255 0 0') 

987 with pytest.raises(TurtleShortcutException): 

988 psc('fc 255 0 0') 

989 with pytest.raises(TurtleShortcutException): 

990 psc('bc 255 0 0') 

991 

992 psc('pc 1.0 0.0 0.0') 

993 assert capsys.readouterr().out == 'pencolor((1.0, 0.0, 0.0))\n' 

994 psc('fc 1.0 0.0 0.0') 

995 assert capsys.readouterr().out == 'fillcolor((1.0, 0.0, 0.0))\n' 

996 psc('bc 1.0 0.0 0.0') 

997 assert capsys.readouterr().out == 'bgcolor((1.0, 0.0, 0.0))\n' 

998 

999 degrees() 

1000 psc('n 100') 

1001 assert capsys.readouterr().out == 'setheading(90)\nforward(100)\n' 

1002 psc('s 100') 

1003 assert capsys.readouterr().out == 'setheading(270)\nforward(100)\n' 

1004 psc('e 100') 

1005 assert capsys.readouterr().out == 'setheading(0)\nforward(100)\n' 

1006 psc('w 100') 

1007 assert capsys.readouterr().out == 'setheading(180)\nforward(100)\n' 

1008 psc('nw 100') 

1009 assert capsys.readouterr().out == 'setheading(135)\nforward(100)\n' 

1010 psc('ne 100') 

1011 assert capsys.readouterr().out == 'setheading(45)\nforward(100)\n' 

1012 psc('sw 100') 

1013 assert capsys.readouterr().out == 'setheading(225)\nforward(100)\n' 

1014 psc('se 100') 

1015 assert capsys.readouterr().out == 'setheading(315)\nforward(100)\n' 

1016 psc('north 100') 

1017 assert capsys.readouterr().out == 'setheading(90)\nforward(100)\n' 

1018 psc('south 100') 

1019 assert capsys.readouterr().out == 'setheading(270)\nforward(100)\n' 

1020 psc('east 100') 

1021 assert capsys.readouterr().out == 'setheading(0)\nforward(100)\n' 

1022 psc('west 100') 

1023 assert capsys.readouterr().out == 'setheading(180)\nforward(100)\n' 

1024 psc('northwest 100') 

1025 assert capsys.readouterr().out == 'setheading(135)\nforward(100)\n' 

1026 psc('northeast 100') 

1027 assert capsys.readouterr().out == 'setheading(45)\nforward(100)\n' 

1028 psc('southwest 100') 

1029 assert capsys.readouterr().out == 'setheading(225)\nforward(100)\n' 

1030 psc('southeast 100') 

1031 assert capsys.readouterr().out == 'setheading(315)\nforward(100)\n' 

1032 psc('N 100') 

1033 assert capsys.readouterr().out == 'setheading(90)\nforward(100)\n' 

1034 psc('S 100') 

1035 assert capsys.readouterr().out == 'setheading(270)\nforward(100)\n' 

1036 psc('E 100') 

1037 assert capsys.readouterr().out == 'setheading(0)\nforward(100)\n' 

1038 psc('W 100') 

1039 assert capsys.readouterr().out == 'setheading(180)\nforward(100)\n' 

1040 psc('NW 100') 

1041 assert capsys.readouterr().out == 'setheading(135)\nforward(100)\n' 

1042 psc('NE 100') 

1043 assert capsys.readouterr().out == 'setheading(45)\nforward(100)\n' 

1044 psc('SW 100') 

1045 assert capsys.readouterr().out == 'setheading(225)\nforward(100)\n' 

1046 psc('SE 100') 

1047 assert capsys.readouterr().out == 'setheading(315)\nforward(100)\n' 

1048 psc('NORTH 100') 

1049 assert capsys.readouterr().out == 'setheading(90)\nforward(100)\n' 

1050 psc('SOUTH 100') 

1051 assert capsys.readouterr().out == 'setheading(270)\nforward(100)\n' 

1052 psc('EAST 100') 

1053 assert capsys.readouterr().out == 'setheading(0)\nforward(100)\n' 

1054 psc('WEST 100') 

1055 assert capsys.readouterr().out == 'setheading(180)\nforward(100)\n' 

1056 psc('NORTHWEST 100') 

1057 assert capsys.readouterr().out == 'setheading(135)\nforward(100)\n' 

1058 psc('NORTHEAST 100') 

1059 assert capsys.readouterr().out == 'setheading(45)\nforward(100)\n' 

1060 psc('SOUTHWEST 100') 

1061 assert capsys.readouterr().out == 'setheading(225)\nforward(100)\n' 

1062 psc('SOUTHEAST 100') 

1063 assert capsys.readouterr().out == 'setheading(315)\nforward(100)\n' 

1064 psc('n 100, f 100') 

1065 assert capsys.readouterr().out == 'setheading(90)\nforward(100)\nforward(100)\n' 

1066 psc('n 100, f 100, f 100') 

1067 assert capsys.readouterr().out == 'setheading(90)\nforward(100)\nforward(100)\nforward(100)\n' 

1068 

1069 radians() 

1070 psc('n 100') 

1071 assert capsys.readouterr().out == 'degrees()\nsetheading(90)\nforward(100)\nradians()\n' 

1072 psc('s 100') 

1073 assert capsys.readouterr().out == 'degrees()\nsetheading(270)\nforward(100)\nradians()\n' 

1074 psc('e 100') 

1075 assert capsys.readouterr().out == 'degrees()\nsetheading(0)\nforward(100)\nradians()\n' 

1076 psc('w 100') 

1077 assert capsys.readouterr().out == 'degrees()\nsetheading(180)\nforward(100)\nradians()\n' 

1078 psc('nw 100') 

1079 assert capsys.readouterr().out == 'degrees()\nsetheading(135)\nforward(100)\nradians()\n' 

1080 psc('ne 100') 

1081 assert capsys.readouterr().out == 'degrees()\nsetheading(45)\nforward(100)\nradians()\n' 

1082 psc('sw 100') 

1083 assert capsys.readouterr().out == 'degrees()\nsetheading(225)\nforward(100)\nradians()\n' 

1084 psc('se 100') 

1085 assert capsys.readouterr().out == 'degrees()\nsetheading(315)\nforward(100)\nradians()\n' 

1086 

1087 degrees() 

1088 

1089 

1090def test_skip(capsys): 

1091 turtle.home() 

1092 assert sc('f 100', skip=True) == 0 

1093 assert turtle.pos() == (0, 0) 

1094 assert sc('f 100', skip=True, _return_turtle_code=True) == () 

1095 

1096 

1097def test_comment(): 

1098 assert sc('# ignore 123 abc') == 0 

1099 assert sc('f 100, # ignore this') == 1 

1100 assert sc('f 100, # ignore this, b 100') == 2 

1101 assert sc('f 100, # ignore this, b 100, # ignore this') == 2 

1102 assert sc('f 100, # ignore this, b 100, # ignore this, f 100') == 3 

1103 

1104 

1105def test_recording(): 

1106 begin_recording() 

1107 assert RECORDED_SHORTCUTS == [] 

1108 assert sc('f 100, l 90, f 100, l 90, # foobar, f 100') == 5 

1109 assert end_recording() == ['f 100', ' l 90', ' f 100', ' l 90', ' # foobar', ' f 100'] 

1110 begin_recording() 

1111 assert RECORDED_SHORTCUTS == [] 

1112 

1113 

1114 

1115# EXAMPLE PROGRAMS: 

1116 

1117def test_colorful_squares(): 

1118 colormode(1.0) 

1119 sc('t 1000 0, ps 4') 

1120 

1121 for i in range(100): # Draw 100 squares. 

1122 # Move to a random place: 

1123 sc(f'pu,g {randint(-400, 200)} {randint(-400, 200)},pd,fc {random()} {random()} {random()}, pc {random()} {random()} {random()}') 

1124 line_length = randint(20, 200) 

1125 

1126 # Draw the filled-in square: 

1127 sc('bf') 

1128 for j in range(4): 

1129 sc(f'f {line_length}, l 90') 

1130 sc('ef') 

1131 

1132 sc('u,reset') 

1133 

1134 

1135def test_draw_circles(): 

1136 sc('t 1000 0, ps 1') 

1137 

1138 # Draw circle in the top half of the window: 

1139 sc('sh 0') # Face right. 

1140 for i in range(20): 

1141 sc(f'cir {i * 10}') 

1142 

1143 # Draw circles in the bottom half of the window: 

1144 sc('sh 180') # Face left. 

1145 for i in range(20): 

1146 sc(f'cir {i * 10}') 

1147 sc('u,reset') 

1148 

1149 

1150def test_curve_path_filled(): 

1151 sc('t 1000 0, ps 1') 

1152 colormode(1.0) 

1153 for i in range(50): 

1154 sc(f'fc {random()} {random()} {random()}') 

1155 

1156 # Set a random heading and draw several short lines with changing direction: 

1157 sc(f'sh {randint(0, 360)}, bf') 

1158 

1159 for j in range(randint(200, 600)): 

1160 sc(f'f 1,l {randint(-4, 4)}') 

1161 sc(f'h, ef') 

1162 sc('u,reset') 

1163 

1164 

1165if __name__ == '__main__': 

1166 pytest.main()