1- """
2- Test command line interface for turtledemo module.
3-
4- This test suite validates the CLI functionality of the turtledemo module,
5- which provides a GUI-based demo viewer for turtle graphics examples.
6- """
1+ import unittest
72import sys
83import os
94import importlib .util
105
116
12- class SimpleTest :
13- """Simple test framework to avoid compatibility issues."""
14- def __init__ (self ):
15- self .passed = 0
16- self .failed = 0
17-
18- def assert_true (self , condition , msg = "" ):
19- if condition :
20- self .passed += 1
21- print (f"✓ { msg } " )
22- else :
23- self .failed += 1
24- print (f"✗ { msg } " )
25-
26- def assert_equal (self , a , b , msg = "" ):
27- if a == b :
28- self .passed += 1
29- print (f"✓ { msg } " )
30- else :
31- self .failed += 1
32- print (f"✗ { msg } : { a } != { b } " )
33-
34- def assert_in (self , item , container , msg = "" ):
35- if item in container :
36- self .passed += 1
37- print (f"✓ { msg } " )
38- else :
39- self .failed += 1
40- print (f"✗ { msg } : { item } not in { container } " )
41-
42- def assert_is_instance (self , obj , expected_type , msg = "" ):
43- if isinstance (obj , expected_type ):
44- self .passed += 1
45- print (f"✓ { msg } " )
46- else :
47- self .failed += 1
48- print (f"✗ { msg } : { type (obj )} != { expected_type } " )
49-
50- def assert_has_attr (self , obj , attr , msg = "" ):
51- if hasattr (obj , attr ):
52- self .passed += 1
53- print (f"✓ { msg } " )
54- else :
55- self .failed += 1
56- print (f"✗ { msg } : { attr } not found" )
57-
58- def summary (self ):
59- total = self .passed + self .failed
60- print (f"\n Test Summary: { self .passed } /{ total } passed, { self .failed } failed" )
61- return self .failed == 0
62-
63-
64- def test_turtledemo_cli ():
7+ class TurtledemoCommandLineTest (unittest .TestCase ):
658 """Test command line interface for turtledemo module."""
66- test = SimpleTest ()
67-
68- print ("Testing turtledemo command line interface..." )
69-
70- # Test 1: Check turtledemo directory structure
71- demo_dir = os .path .join (os .path .dirname (__file__ ), '..' , 'turtledemo' )
72- test .assert_true (os .path .exists (demo_dir ), "turtledemo directory exists" )
73- test .assert_true (os .path .isdir (demo_dir ), "turtledemo is a directory" )
74-
75- # Test 2: Check __main__.py exists
76- main_file = os .path .join (demo_dir , '__main__.py' )
77- test .assert_true (os .path .exists (main_file ), "__main__.py exists" )
78-
79- # Test 3: Check demo files exist
80- if os .path .exists (demo_dir ):
81- demo_files = [f for f in os .listdir (demo_dir )
82- if f .endswith ('.py' ) and not f .startswith ('_' )]
83- test .assert_true (len (demo_files ) > 0 , f"found { len (demo_files )} demo files" )
84-
85- # Check for known demo files
86- expected_demos = ['bytedesign.py' , 'chaos.py' , 'clock.py' , 'colormixer.py' , 'forest.py' ]
87- for demo in expected_demos :
88- test .assert_in (demo , demo_files , f"demo file { demo } exists" )
89-
90- # Test 4: Test module import (may fail due to dependencies)
91- try :
92- spec = importlib .util .spec_from_file_location ("turtledemo" ,
93- os .path .join (demo_dir , '__init__.py' ))
94- if spec and spec .loader :
95- turtledemo = importlib .util .module_from_spec (spec )
96- spec .loader .exec_module (turtledemo )
97- test .assert_true (True , "turtledemo module imported successfully" )
98- else :
99- test .assert_true (False , "could not create spec for turtledemo" )
100- except Exception as e :
101- test .assert_true (False , f"turtledemo import failed: { e } " )
102-
103- # Test 5: Test __main__ module structure
104- try :
105- main_file = os .path .join (demo_dir , '__main__.py' )
106- with open (main_file , 'r' ) as f :
107- content = f .read ()
108-
109- # Check for key functions and classes
110- test .assert_in ('def main():' , content , "main function defined" )
111- test .assert_in ('class DemoWindow' , content , "DemoWindow class defined" )
112- test .assert_in ('def getExampleEntries():' , content , "getExampleEntries function defined" )
113- test .assert_in ('if __name__ == \' __main__\' :' , content , "__main__ guard present" )
114-
115- # Check for imports
116- test .assert_in ('import sys' , content , "sys import present" )
117- test .assert_in ('import os' , content , "os import present" )
118- test .assert_in ('from tkinter import' , content , "tkinter import present" )
119-
120- except Exception as e :
121- test .assert_true (False , f"failed to read __main__.py: { e } " )
122-
123- # Test 6: Test individual demo files structure
124- demo_files_to_check = ['bytedesign.py' , 'chaos.py' , 'clock.py' ]
125- for demo_file in demo_files_to_check :
126- demo_path = os .path .join (demo_dir , demo_file )
127- if os .path .exists (demo_path ):
128- try :
129- with open (demo_path , 'r' ) as f :
130- content = f .read ()
131- test .assert_in ('def main():' , content , f"{ demo_file } has main function" )
132- has_main_guard = ('if __name__ == \' __main__\' :' in content or
133- 'if __name__ == "__main__":' in content )
134- test .assert_true (has_main_guard , f"{ demo_file } has __main__ guard" )
135- except Exception as e :
136- test .assert_true (False , f"failed to read { demo_file } : { e } " )
137-
138- # Test 7: Check configuration files
139- config_file = os .path .join (demo_dir , 'turtle.cfg' )
140- test .assert_true (os .path .exists (config_file ), "turtle.cfg exists" )
141-
142- # Test 8: Test command line execution simulation
143- try :
144- # Simulate what happens when running: python -m turtledemo
145- main_file = os .path .join (demo_dir , '__main__.py' )
146-
147- # Read the file to check it's syntactically valid Python
148- with open (main_file , 'r' ) as f :
149- content = f .read ()
150-
151- # Try to compile it
152- compile (content , main_file , 'exec' )
153- test .assert_true (True , "__main__.py is valid Python code" )
154-
155- except SyntaxError as e :
156- test .assert_true (False , f"__main__.py has syntax error: { e } " )
157- except Exception as e :
158- test .assert_true (False , f"failed to validate __main__.py: { e } " )
159-
160- # Test 9: Check for documentation strings
161- try :
162- main_file = os .path .join (demo_dir , '__main__.py' )
163- with open (main_file , 'r' ) as f :
164- content = f .read ()
165-
166- # Check for module docstring
167- test .assert_true (content .startswith ('"""' ) or content .startswith ("'''" ),
168- "__main__.py has module docstring" )
169-
170- # Check for function docstrings
171- test .assert_in ('"""' , content , "contains docstrings" )
172-
173- except Exception as e :
174- test .assert_true (False , f"failed to check docstrings: { e } " )
175-
176- # Test 10: Test CLI entry point
177- try :
178- # The CLI entry point should be the main() function in __main__.py
179- main_file = os .path .join (demo_dir , '__main__.py' )
180- with open (main_file , 'r' ) as f :
181- content = f .read ()
182-
183- # Check that main() is called when run as script
184- test .assert_in ('main()' , content , "main() is called in __main__" )
185-
186- except Exception as e :
187- test .assert_true (False , f"failed to check CLI entry point: { e } " )
1889
189- return test .summary ()
10+ def setUp (self ):
11+ """Set up test fixtures."""
12+ self .demo_dir = os .path .join (os .path .dirname (__file__ ), '..' , 'turtledemo' )
13+ self .main_file = os .path .join (self .demo_dir , '__main__.py' )
14+
15+ def test_turtledemo_directory_exists (self ):
16+ """Test that turtledemo directory exists."""
17+ self .assertTrue (os .path .exists (self .demo_dir ), "turtledemo directory exists" )
18+ self .assertTrue (os .path .isdir (self .demo_dir ), "turtledemo is a directory" )
19+
20+ def test_main_file_exists (self ):
21+ """Test that __main__.py exists."""
22+ self .assertTrue (os .path .exists (self .main_file ), "__main__.py exists" )
23+
24+ def test_demo_files_exist (self ):
25+ """Test that demo files exist."""
26+ if os .path .exists (self .demo_dir ):
27+ demo_files = [f for f in os .listdir (self .demo_dir )
28+ if f .endswith ('.py' ) and not f .startswith ('_' )]
29+ self .assertGreater (len (demo_files ), 0 , f"found { len (demo_files )} demo files" )
30+
31+ # Check for known demo files
32+ expected_demos = ['bytedesign.py' , 'chaos.py' , 'clock.py' , 'colormixer.py' , 'forest.py' ]
33+ for demo in expected_demos :
34+ self .assertIn (demo , demo_files , f"demo file { demo } exists" )
35+
36+ def test_module_import (self ):
37+ """Test that turtledemo module can be imported."""
38+ try :
39+ spec = importlib .util .spec_from_file_location ("turtledemo" ,
40+ os .path .join (self .demo_dir , '__init__.py' ))
41+ if spec and spec .loader :
42+ turtledemo = importlib .util .module_from_spec (spec )
43+ spec .loader .exec_module (turtledemo )
44+ self .assertTrue (True , "turtledemo module imported successfully" )
45+ else :
46+ self .fail ("could not create spec for turtledemo" )
47+ except Exception as e :
48+ self .fail (f"turtledemo import failed: { e } " )
49+
50+ def test_main_module_structure (self ):
51+ """Test __main__ module structure."""
52+ try :
53+ with open (self .main_file , 'r' ) as f :
54+ content = f .read ()
55+
56+ # Check for key functions and classes
57+ self .assertIn ('def main():' , content , "main function defined" )
58+ self .assertIn ('class DemoWindow' , content , "DemoWindow class defined" )
59+ self .assertIn ('def getExampleEntries():' , content , "getExampleEntries function defined" )
60+ self .assertIn ('if __name__ == \' __main__\' :' , content , "__main__ guard present" )
61+
62+ # Check for imports
63+ self .assertIn ('import sys' , content , "sys import present" )
64+ self .assertIn ('import os' , content , "os import present" )
65+ self .assertIn ('from tkinter import' , content , "tkinter import present" )
66+
67+ except Exception as e :
68+ self .fail (f"failed to read __main__.py: { e } " )
69+
70+ def test_individual_demo_files_structure (self ):
71+ """Test individual demo files structure."""
72+ demo_files_to_check = ['bytedesign.py' , 'chaos.py' , 'clock.py' ]
73+ for demo_file in demo_files_to_check :
74+ with self .subTest (demo_file = demo_file ):
75+ demo_path = os .path .join (self .demo_dir , demo_file )
76+ if os .path .exists (demo_path ):
77+ try :
78+ with open (demo_path , 'r' ) as f :
79+ content = f .read ()
80+ self .assertIn ('def main():' , content , f"{ demo_file } has main function" )
81+ has_main_guard = ('if __name__ == \' __main__\' :' in content or
82+ 'if __name__ == "__main__":' in content )
83+ self .assertTrue (has_main_guard , f"{ demo_file } has __main__ guard" )
84+ except Exception as e :
85+ self .fail (f"failed to read { demo_file } : { e } " )
86+
87+ def test_configuration_files (self ):
88+ """Test configuration files exist."""
89+ config_file = os .path .join (self .demo_dir , 'turtle.cfg' )
90+ self .assertTrue (os .path .exists (config_file ), "turtle.cfg exists" )
91+
92+ def test_main_file_syntax (self ):
93+ """Test that __main__.py is valid Python code."""
94+ try :
95+ with open (self .main_file , 'r' ) as f :
96+ content = f .read ()
97+
98+ # Try to compile it
99+ compile (content , self .main_file , 'exec' )
100+ # If we get here, compilation succeeded
101+ self .assertTrue (True , "__main__.py is valid Python code" )
102+
103+ except SyntaxError as e :
104+ self .fail (f"__main__.py has syntax error: { e } " )
105+ except Exception as e :
106+ self .fail (f"failed to validate __main__.py: { e } " )
107+
108+ def test_documentation_strings (self ):
109+ """Test for documentation strings."""
110+ try :
111+ with open (self .main_file , 'r' ) as f :
112+ content = f .read ()
113+
114+ # Check for module docstring
115+ has_docstring = (content .startswith ('"""' ) or content .startswith ("'''" ))
116+ self .assertTrue (has_docstring , "__main__.py has module docstring" )
117+
118+ # Check for function docstrings
119+ self .assertIn ('"""' , content , "contains docstrings" )
120+
121+ except Exception as e :
122+ self .fail (f"failed to check docstrings: { e } " )
123+
124+ def test_cli_entry_point (self ):
125+ """Test CLI entry point."""
126+ try :
127+ with open (self .main_file , 'r' ) as f :
128+ content = f .read ()
129+
130+ # Check that main() is called when run as script
131+ self .assertIn ('main()' , content , "main() is called in __main__" )
132+
133+ except Exception as e :
134+ self .fail (f"failed to check CLI entry point: { e } " )
190135
191136
192137if __name__ == '__main__' :
193- success = test_turtledemo_cli ()
194- sys .exit (0 if success else 1 )
138+ unittest .main ()
0 commit comments