118
118
true = classmethod(lambda *x: True)
119
119
false = classmethod(lambda *x: False)
121
def __init__(self, pass_msg, fail_msg, default='match'):
121
def __init__(self, test_case):
122
122
"""Initialise with descriptions (pass,fail) and a default behavior for output
123
123
If default is match, unspecified files are matched exactly
124
124
If default is ignore, unspecified files are ignored
125
125
The default default is match.
127
self._pass_msg = pass_msg
128
self._fail_msg = fail_msg
129
self._default = default
130
if default == 'ignore':
127
self._pass_msg = test_case.passmsg
128
self._fail_msg = test_case.failmsg
129
self._default = test_case.test_default
130
if self._default == 'ignore':
131
131
self._default_func = self.true
133
133
self._default_func = self.match
138
138
self._exception_test = ('check', self._default_func)
139
139
self._result_test = ('check', self._default_func)
140
140
self._code_test = ('check', self._default_func)
142
for part in test_case.parts:
143
if part.part_type =="file":
144
self.add_file_test(part)
145
elif part.part_type =="stdout":
146
self.add_stdout_test(part)
147
elif part.part_type =="stderr":
148
self.add_stderr_test(part)
149
elif part.part_type =="result":
150
self.add_result_test(part)
151
elif part.part_type =="exception":
152
self.add_exception_test(part)
153
elif part.part_type =="code":
154
self.add_code_test(part)
142
156
def _set_default_function(self, function, test_type):
143
157
""""Ensure test type is valid and set function to a default
191
205
for filename, (test_type, function) in self._file_tests.items():
192
206
self._file_tests[filename] = (test_type, self._validate_function(function, included_code))
194
def add_result_test(self, function, test_type='norm'):
208
def add_result_test(self, part):
195
209
"Test part that compares function return values"
196
function = self._set_default_function(function, test_type)
197
self._result_test = (test_type, function)
210
function = self._set_default_function(part.data, part.test_type)
211
self._result_test = (part.test_type, function)
199
def add_stdout_test(self, function, test_type='norm'):
213
def add_stdout_test(self, part):
200
214
"Test part that compares stdout"
201
function = self._set_default_function(function, test_type)
202
self._stdout_test = (test_type, function)
204
def add_stderr_test(self, function, test_type='norm'):
205
"Test part that compares stderr"
206
function = self._set_default_function(function, test_type)
207
self._stderr_test = (test_type, function)
209
def add_exception_test(self, function, test_type='norm'):
210
"Test part that compares stderr"
211
function = self._set_default_function(function, test_type)
212
self._exception_test = (test_type, function)
214
def add_file_test(self, filename, function, test_type='norm'):
215
function = self._set_default_function(part.data, part.test_type)
216
self._stdout_test = (part.test_type, function)
218
def add_stderr_test(self, part):
219
"Test part that compares stderr"
220
function = self._set_default_function(part.data, part.test_type)
221
self._stderr_test = (part.test_type, function)
223
def add_exception_test(self, part):
224
"Test part that compares stderr"
225
function = self._set_default_function(part.data, part.test_type)
226
self._exception_test = (part.test_type, function)
228
def add_file_test(self, part):
215
229
"Test part that compares the contents of a specified file"
216
function = self._set_default_function(function, test_type)
217
self._file_tests[filename] = (test_type, function)
230
function = self._set_default_function(part.data, part.test_type)
231
self._file_tests[part.filename] = (part.test_type, function)
219
def add_code_test(self, function, test_type='norm'):
233
def add_code_test(self, part):
220
234
"Test part that examines the supplied code"
221
function = self._set_default_function(function, test_type)
222
self._code_test = (test_type, function)
235
function = self._set_default_function(part.data, part.test_type)
236
self._code_test = (part.test_type, function)
224
238
def _check_output(self, solution_output, attempt_output, test_type, f):
225
239
"""Compare solution output and attempt output using the
308
322
A set of tests with a common inputs
310
def __init__(self, console, name='', function=None, stdin='', filespace=None, global_space=None):
324
def __init__(self, console, suite):
311
325
"""Initialise with name and optionally, a function to test (instead of the entire script)
312
326
The inputs stdin, the filespace and global variables can also be specified at
313
327
initialisation, but may also be set later.
315
329
self._console = console
317
if global_space == None:
319
if filespace == None:
330
self._name = suite.description
332
function = suite.function
324
333
if function == '': function = None
325
334
self._function = function
326
335
self._list_args = []
327
336
self._keyword_args = {}
329
self.set_stdin(stdin)
330
self._filespace = testfilespace.TestFilespace(filespace)
331
self._global_space = global_space
338
self.set_stdin(suite.stdin)
339
self._filespace = testfilespace.TestFilespace(None)
340
self._global_space = {}
333
342
self._allowed_exceptions = set()
345
for var in suite.variables:
346
if var.var_type == "file":
348
elif var.var_type == "var":
349
self.add_variable(var)
350
elif var.var_type == "arg":
351
args[var.arg_no] = var
352
elif var.var_type == "exception":
353
self.add_exception(var)
355
for i in xrange(len(args)):
356
self.add_arg(args[i])
357
for test_case in suite.test_cases:
358
self.add_part(TestCasePart(test_case))
335
360
def set_stdin(self, stdin):
336
361
""" Set the given string as the stdin for this test case"""
337
362
# stdin must have a newline at the end for raw_input to work properly
338
if stdin[-1:] != '\n':
363
if stdin is not None:
364
if stdin[-1:] != '\n':
340
368
self._stdin = stdin
342
def add_file(self, filename, data):
370
def add_file(self, filevar):
343
371
""" Insert the given filename-data pair into the filespace for this test case"""
344
372
# TODO: Add the file to the console
345
self._filespace.add_file(filename, data)
373
self._filespace.add_file(filevar.var_name, "")
347
def add_variable(self, variable, value):
375
def add_variable(self, var):
348
376
""" Add the given varibale-value pair to the initial global environment
349
377
for this test case. The value is the string repr() of an actual value.
350
378
Throw an exception if the value cannot be paresed.
354
self._global_space[variable] = eval(value)
382
self._global_space[var.var_name] = eval(var.var_value)
356
raise TestCreationError("Invalid value for variable %s: %s" %(variable, value))
384
raise TestCreationError("Invalid value for variable %s: %s"
385
%(var.var_name, var.var_value))
358
def add_arg(self, value, name=None):
387
def add_arg(self, var):
359
388
""" Add a value to the argument list. This only applies when testing functions.
360
389
By default arguments are not named, but if they are, they become keyword arguments.
363
if name == None or name == '':
364
self._list_args.append(eval(value))
392
if var.var_name == None or var.var_name == '':
393
self._list_args.append(eval(var.var_value))
366
self._keyword_args[name] = value
395
self._keyword_args[var.var_name] = var.var_value
368
raise TestCreationError("Invalid value for function argument: %s" %value)
397
raise TestCreationError("Invalid value for function argument: %s" %var.var_value)
370
399
def add_exception(self, exception_name):
371
self._allowed_exceptions.add(exception_name)
400
self._allowed_exceptions.add(var.var_name)
373
402
def add_part(self, test_part):
374
403
""" Add a TestPart to this test case"""
524
553
The complete collection of test cases for a given exercise
526
def __init__(self, name, console, solution=None):
555
def __init__(self, exercise, console):
527
556
"""Initialise with the name of the test suite (the exercise name) and the solution.
528
557
The solution may be specified later.
530
self._solution = solution
559
self._solution = exercise.solution
560
self._name = exercise.id
561
self._exercise = exercise
533
563
self._console = console
534
self.add_include_code("")
536
def add_solution(self, solution):
537
" Specify the solution script for this exercise "
538
self._solution = solution
564
self.add_include_code(exercise.include)
566
for test_case in exercise.test_suites:
567
new_case = TestCase(console, test_case)
568
self.add_case(new_case)
540
570
def has_solution(self):
541
571
" Returns true if a solution has been provided "