@@ -158,8 +158,8 @@ class SpecSuite(TypedDict, total=False):
158158 'spec/helpers/section.yaml' ,
159159 'spec/helpers/unlessEquals.yaml' ,
160160 'spec/metadata.yaml' ,
161- # 'spec/partials.yaml',
162- # 'spec/picoschema.yaml',
161+ 'spec/partials.yaml' ,
162+ 'spec/picoschema.yaml' ,
163163 'spec/variables.yaml' ,
164164]
165165
@@ -185,25 +185,25 @@ class TestSpecFiles(unittest.IsolatedAsyncioTestCase):
185185
186186 def test_spec_path (self ) -> None :
187187 """Test that the spec directory exists."""
188- assert SPECS_DIR .exists ()
189- assert SPECS_DIR .is_dir ()
188+ self . assertTrue ( SPECS_DIR .exists () )
189+ self . assertTrue ( SPECS_DIR .is_dir () )
190190
191191 def test_spec_path_contains_yaml_files (self ) -> None :
192192 """Test that the spec directory contains YAML files."""
193- assert list (SPECS_DIR .glob ('**/*.yaml' ))
193+ self . assertTrue ( list (SPECS_DIR .glob ('**/*.yaml' ) ))
194194
195195 def test_spec_files_are_valid (self ) -> None :
196196 """Test that all spec files contain valid YAML."""
197197 for file in SPECS_DIR .glob ('**/*.yaml' ):
198198 with open (file ) as f :
199199 data = yaml .safe_load (f )
200- assert data is not None
200+ self . assertIsNotNone ( data )
201201
202202 async def test_specs (self ) -> None :
203203 """Discovers and runs all YAML specification tests."""
204204 for yaml_file in SPECS_DIR .glob ('**/*.yaml' ):
205205 if not is_allowed_spec_file (yaml_file ):
206- logger .debug (
206+ logger .warn (
207207 'Skipping spec file' ,
208208 file = yaml_file ,
209209 )
@@ -214,14 +214,57 @@ async def test_specs(self) -> None:
214214
215215 for suite_data_raw in suites_data :
216216 suite : SpecSuite = cast (SpecSuite , suite_data_raw )
217+ suite_name : str = suite .get ('name' , f'UnnamedSuite_in_{ yaml_file .name } ' )
217218
218- with self .subTest (suite = suite .get ('name' , 'UnnamedSuite' )):
219- for test_case_data_raw in suite .get ('tests' , []):
220- test_case : SpecTest = test_case_data_raw
219+ suite ['name' ] = suite_name
221220
222- with self .subTest (test = test_case .get ('desc' , 'UnnamedTest' )):
223- dotprompt = Dotprompt ()
224- await self .run_yaml_test (yaml_file , dotprompt , suite , test_case )
221+ with self .subTest (suite = suite_name ):
222+ for tc_raw in suite .get ('tests' , []):
223+ tc : SpecTest = tc_raw
224+ tc_name = tc .get ('desc' , f'UnnamedTest_in_{ suite_name } ' )
225+ tc ['desc' ] = tc_name
226+
227+ with self .subTest (test = tc_name ):
228+ # TODO: Doing this per test case is safer for
229+ # test sandboxing but we could perhaps do this
230+ # per suite as well.
231+ dotprompt = self .make_dotprompt (suite )
232+ await self .run_yaml_test (yaml_file , dotprompt , suite , tc )
233+
234+ def make_dotprompt (self , suite : SpecSuite ) -> Dotprompt :
235+ """Constructs and sets up a Dotprompt instance for the given suite.
236+
237+ Args:
238+ suite: The suite to set up the Dotprompt for.
239+
240+ Returns:
241+ A Dotprompt instance configured for the given suite.
242+ """
243+ resolver_partials : dict [str , str ] = suite .get ('resolver_partials' , {})
244+
245+ def partial_resolver_fn (name : str ) -> str | None :
246+ """Resolves a partial name to a template string.
247+
248+ Args:
249+ name: The name of the partial to resolve.
250+
251+ Returns:
252+ The template string for the partial, or None if the partial is not found.
253+ """
254+ return resolver_partials .get (name )
255+
256+ dotprompt = Dotprompt (
257+ schemas = suite .get ('schemas' ),
258+ tools = suite .get ('tools' ),
259+ partial_resolver = partial_resolver_fn if resolver_partials else None ,
260+ )
261+
262+ # Define partials if they exist.
263+ partials : dict [str , str ] = suite .get ('partials' , {})
264+ for name , template in partials .items ():
265+ dotprompt .define_partial (name , template )
266+
267+ return dotprompt
225268
226269 async def run_yaml_test (
227270 self ,
@@ -241,18 +284,17 @@ async def run_yaml_test(
241284 Returns:
242285 None
243286 """
244- logger .debug (
245- 'Running spec test' ,
246- yaml_file = yaml_file ,
247- suite = suite ,
248- test = test_case ,
287+ suite_name = suite .get ('name' )
288+ test_name = test_case .get ('desc' )
289+ logger .info (
290+ f'[TEST] \033 [1m{ yaml_file .name } \033 [0m: { suite_name } > { test_name } ' ,
291+ yaml_file = yaml_file .name ,
292+ suite_name = suite_name ,
293+ test_name = test_name ,
294+ # suite=suite,
295+ # test=test_case,
249296 )
250297
251- # Define partials if they exist.
252- partials : dict [str , str ] = suite .get ('partials' , {})
253- for name , template in partials .items ():
254- dotprompt .define_partial (name , template )
255-
256298 # TODO: Render the template.
257299 # data = {**suite.get('data', {}), **test_case.get('data', {})}
258300 # result = await dotprompt.render(
@@ -267,13 +309,15 @@ async def run_yaml_test(
267309 # TODO: Render the metadata.
268310 # TODO: Compare pruned metadata to the expected output.
269311
270- logger .debug (
271- 'Finished running spec test' ,
272- yaml_file = yaml_file ,
273- suite = suite ,
274- test = test_case ,
275- # result=result,
276- )
312+ # logger.info(
313+ # f'[TEST] \033[1m{yaml_file.name}\033[0m: {suite_name} > {test_name} finished',
314+ # yaml_file=yaml_file.name,
315+ # suite_name=suite_name,
316+ # test_name=test_name,
317+ # # suite=suite,
318+ # # test=test_case,
319+ # # result=result,
320+ # )
277321
278322
279323if __name__ == '__main__' :
0 commit comments