1212import re
1313import fnmatch
1414
15+ DEBUG = False
16+
17+ def debug (s ):
18+ if DEBUG :
19+ print (f'[TESTDEBUG] { s } ' )
20+
1521GLOBAL_CHECK_OUTPUTS = True
1622
1723GLOBAL_RECORD_ALL = False # Should be False, write actual output to all expected output files
@@ -34,6 +40,7 @@ def parseArgs() -> TestOpts:
3440 )
3541
3642 # Define the command-line arguments
43+ parser .add_argument ("--debug" , action = "store_true" , help = "Output debug messages" )
3744 parser .add_argument ("--start-at" , type = str , help = "Start with test in FILE" )
3845 parser .add_argument ("--only" , type = str , help = "Run only the test in FILE" )
3946 parser .add_argument ("--continue" , action = "store_true" ,
@@ -48,7 +55,9 @@ def parseArgs() -> TestOpts:
4855 nargs = '*' )
4956 # Parse the arguments
5057 args = parser .parse_args ()
51-
58+ if args .debug :
59+ global DEBUG
60+ DEBUG = True
5261 scriptDir = os .path .dirname (__file__ )
5362 return TestOpts (
5463 cmd = f'{ scriptDir } /code/wypp/runYourProgram.py' ,
@@ -244,6 +253,7 @@ def _runTest(testFile: str,
244253 env = os .environ .copy ()
245254 env ['PYTHONPATH' ] = os .pathsep .join ([os .path .join (ctx .opts .baseDir , 'code' )] + pythonPath )
246255 env ['WYPP_UNDER_TEST' ] = 'True'
256+ debug (' ' .join (cmd ))
247257 with open (actualStdoutFile , 'w' ) as stdoutFile , \
248258 open (actualStderrFile , 'w' ) as stderrFile :
249259 # Run the command
@@ -332,17 +342,20 @@ class WyppTestConfig:
332342 typecheck : Literal [True , False , "both" ]
333343 args : list [str ]
334344 pythonPath : Optional [str ]
345+ exitCode : Optional [int ]
335346 @staticmethod
336347 def default () -> WyppTestConfig :
337- return WyppTestConfig (typecheck = True , args = [], pythonPath = None )
348+ return WyppTestConfig (typecheck = True , args = [], pythonPath = None , exitCode = None )
338349
339350def readWyppTestConfig (path : str , * , max_lines : int = 5 ) -> WyppTestConfig :
340351 """
341352 Read a line like `# WYPP_TEST_CONFIG: {"typecheck": false}` from the first
342353 `max_lines` lines of the file at `path` and return it as a dict.
343354 Returns {} if not present.
344355 """
345- validKeys = ['typecheck' , 'args' , 'pythonPath' ]
356+ validKeys = ['typecheck' , 'args' , 'pythonPath' , 'exitCode' ]
357+ if not os .path .exists (path ):
358+ return WyppTestConfig .default ()
346359 with open (path , "r" , encoding = "utf-8" ) as f :
347360 for lineno in range (1 , max_lines + 1 ):
348361 line = f .readline ()
@@ -358,7 +371,10 @@ def readWyppTestConfig(path: str, *, max_lines: int = 5) -> WyppTestConfig:
358371 typecheck = j .get ('typecheck' , True )
359372 args = j .get ('args' , [])
360373 pythonPath = j .get ('pythonPath' )
361- return WyppTestConfig (typecheck = typecheck , args = args , pythonPath = pythonPath )
374+ exitCode = j .get ('exitCode' )
375+ cfg = WyppTestConfig (typecheck = typecheck , args = args , pythonPath = pythonPath , exitCode = exitCode )
376+ debug (f'Config for { path } : { cfg } ' )
377+ return cfg
362378 return WyppTestConfig .default ()
363379
364380def checkNoConfig (testFile : str ,
@@ -370,8 +386,6 @@ def checkNoConfig(testFile: str,
370386 checkOutputs : bool = True ,
371387 ctx : TestContext = globalCtx ,
372388 what : str = '' ):
373- if guessExitCode (testFile ) == 0 :
374- exitCode = 0
375389 status = _check (testFile , exitCode , typecheck , args , pythonPath , minVersion , checkOutputs , ctx , what )
376390 ctx .results .storeTestResult (testFile , status )
377391 if status == 'failed' :
@@ -396,6 +410,10 @@ def check(testFile: str,
396410 pythonPath = []
397411 if cfg .pythonPath :
398412 pythonPath = cfg .pythonPath .split (':' )
413+ if cfg .exitCode is not None :
414+ exitCode = cfg .exitCode
415+ elif guessExitCode (testFile ) == 0 :
416+ exitCode = 0
399417 if cfg .typecheck == 'both' :
400418 checkNoConfig (testFile , exitCode , typecheck = True , args = args ,
401419 pythonPath = pythonPath , minVersion = minVersion , checkOutputs = checkOutputs ,
0 commit comments