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":
145
elif part.part_type =="stdout":
146
add_stdout_test(part)
147
elif part.part_type =="stderr":
148
add_stderr_test(part)
149
elif part.part_type =="result":
150
add_result_test(part)
151
elif part.part_type =="exception":
152
add_exception_test(part)
153
elif part.part_type =="code":
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)
210
function = self._set_default_function(part.data, part.test_type)
197
211
self._result_test = (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)
215
function = self._set_default_function(part.data, part.test_type)
202
216
self._stdout_test = (test_type, function)
204
def add_stderr_test(self, function, test_type='norm'):
218
def add_stderr_test(self, part):
205
219
"Test part that compares stderr"
206
function = self._set_default_function(function, test_type)
220
function = self._set_default_function(part.data, part.test_type)
207
221
self._stderr_test = (test_type, function)
209
def add_exception_test(self, function, test_type='norm'):
223
def add_exception_test(self, part):
210
224
"Test part that compares stderr"
211
function = self._set_default_function(function, test_type)
225
function = self._set_default_function(part.data, part.test_type)
212
226
self._exception_test = (test_type, function)
214
def add_file_test(self, filename, function, test_type='norm'):
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] = (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)
235
function = self._set_default_function(part.data, part.test_type)
222
236
self._code_test = (test_type, function)
224
238
def _check_output(self, solution_output, attempt_output, test_type, f):
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()
344
for var in suite.variables:
345
if var.var_type == "file":
347
elif var.var_type == "var":
348
self.add_variable(var)
349
elif var.var_type == "arg":
351
elif var.var_type == "exception":
352
self.add_exception(var)
354
for test_case in suite.test_cases:
355
self.add_part(TestCasePart(test_case))
335
357
def set_stdin(self, stdin):
336
358
""" Set the given string as the stdin for this test case"""
337
359
# stdin must have a newline at the end for raw_input to work properly
338
if stdin[-1:] != '\n':
360
if stdin is not None:
361
if stdin[-1:] != '\n':
340
365
self._stdin = stdin
342
def add_file(self, filename, data):
367
def add_file(self, filevar):
343
368
""" Insert the given filename-data pair into the filespace for this test case"""
344
369
# TODO: Add the file to the console
345
self._filespace.add_file(filename, data)
370
self._filespace.add_file(filevar.var_name, "")
347
def add_variable(self, variable, value):
372
def add_variable(self, var):
348
373
""" Add the given varibale-value pair to the initial global environment
349
374
for this test case. The value is the string repr() of an actual value.
350
375
Throw an exception if the value cannot be paresed.
354
self._global_space[variable] = eval(value)
379
self._global_space[var.var_name] = eval(var.var_value)
356
raise TestCreationError("Invalid value for variable %s: %s" %(variable, value))
381
raise TestCreationError("Invalid value for variable %s: %s"
382
%(var.var_name, var.var_value))
358
def add_arg(self, value, name=None):
384
def add_arg(self, var):
359
385
""" Add a value to the argument list. This only applies when testing functions.
360
386
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))
389
if var.var_name == None or var.var_name == '':
390
self._list_args.append(eval(var.var_value))
366
self._keyword_args[name] = value
392
self._keyword_args[var.var_name] = var.var_value
368
raise TestCreationError("Invalid value for function argument: %s" %value)
394
raise TestCreationError("Invalid value for function argument: %s" %var.var_value)
370
396
def add_exception(self, exception_name):
371
self._allowed_exceptions.add(exception_name)
397
self._allowed_exceptions.add(var.var_name)
373
399
def add_part(self, test_part):
374
400
""" Add a TestPart to this test case"""
524
550
The complete collection of test cases for a given exercise
526
def __init__(self, name, console, solution=None):
552
def __init__(self, exercise, console):
527
553
"""Initialise with the name of the test suite (the exercise name) and the solution.
528
554
The solution may be specified later.
530
self._solution = solution
556
self._solution = exercise.solution
557
self._name = exercise.id
558
self._exercise = exercise
533
560
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
561
self.add_include_code(exercise.include)
563
for test_case in exercise.test_suites:
564
new_case = TestCase(console, test_case)
565
self.add_case(new_case)
540
567
def has_solution(self):
541
568
" Returns true if a solution has been provided "