~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to www/apps/tutorialservice/test/TestFramework.py

  • Committer: stevenbird
  • Date: 2008-02-19 03:59:20 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:502
www/apps/tutorialservice/__init__.py
* changed name from "Problem" to "Exercise"

www/apps/tutorialservice/test/parse_tute.py,TestFramework.py
* changed "succeed" to "pass" for consistency
* added code_test functionality to TestCasePart
* added check_code to run normalisations and comparisons
  on code instead of output
* extended solution_data and attempt_data dictionaries to
  include the code
* still broken with an error on line 423 of TestFramework.py
  (the function supplied in the XML file for testing the code
  can't be called?)

Show diffs side-by-side

added added

removed removed

Lines of Context:
103
103
class TestCasePart:
104
104
    """
105
105
    A part of a test case which compares a subset of the input files or file streams.
106
 
    This can be done either with a comparision function, or by comparing directly, after
 
106
    This can be done either with a comparison function, or by comparing directly, after
107
107
    applying normalisations.
108
108
    """
109
109
 
114
114
    true = classmethod(lambda *x: True)
115
115
    false = classmethod(lambda *x: False)
116
116
 
117
 
    def __init__(self, succeed, fail, default='match'):
118
 
        """Initialise with descriptions (succeed,fail) and a default behavior for output
 
117
    def __init__(self, pass_msg, fail_msg, default='match'):
 
118
        """Initialise with descriptions (pass,fail) and a default behavior for output
119
119
        If default is match, unspecified files are matched exactly
120
120
        If default is ignore, unspecified files are ignored
121
121
        The default default is match.
122
122
        """
123
 
        self._succeed = succeed
124
 
        self._fail = fail
 
123
        self._pass_msg = pass_msg
 
124
        self._fail_msg = fail_msg
125
125
        self._default = default
126
126
        if default == 'ignore':
127
127
            self._default_func = self.true
133
133
        self._stderr_test = ('check', self._default_func)
134
134
        self._exception_test = ('check', self._default_func)
135
135
        self._result_test = ('check', self._default_func)
 
136
        self._code_test = ('check', self._default_func)
136
137
 
137
138
    def _set_default_function(self, function, test_type):
138
139
        """"Ensure test type is valid and set function to a default
149
150
 
150
151
    def _validate_function(self, function, included_code):
151
152
        """Create a function object from the given string.
152
 
        If a valid function object cannot be created, raise and error.
 
153
        If a valid function object cannot be created, raise an error.
153
154
        """
154
155
        if not callable(function):
155
156
            try:
184
185
        "Test part that compares function return values"
185
186
        function = self._set_default_function(function, test_type)
186
187
        self._result_test = (test_type, function)
187
 
 
188
188
            
189
189
    def add_stdout_test(self, function, test_type='norm'):
190
190
        "Test part that compares stdout"
191
191
        function = self._set_default_function(function, test_type)
192
192
        self._stdout_test = (test_type, function)
193
 
        
194
193
 
195
194
    def add_stderr_test(self, function, test_type='norm'):
196
195
        "Test part that compares stderr"
207
206
        function = self._set_default_function(function, test_type)
208
207
        self._file_tests[filename] = (test_type, function)
209
208
 
 
209
    def add_code_test(self, function, test_type='norm'):
 
210
        "Test part that examines the supplied code"
 
211
        function = self._set_default_function(function, test_type)
 
212
        self._code_test = (test_type, function)
 
213
 
210
214
    def _check_output(self, solution_output, attempt_output, test_type, f):
211
215
        """Compare solution output and attempt output using the
212
 
        specified comparision function.
 
216
        specified comparison function.
213
217
        """
214
218
        # converts unicode to string
215
219
        if type(solution_output) == unicode:    
223
227
        else:
224
228
            return f(solution_output, attempt_output)
225
229
 
 
230
    def _check_code(self, solution, attempt, test_type, f):
 
231
        """Compare solution code and attempt code using the
 
232
        specified comparison function.
 
233
        """
 
234
        if not callable(f):
 
235
            raise TestCreationError("Invalid function %s" %f)
 
236
        if test_type == 'norm':
 
237
            return f(solution) == f(attempt)
 
238
        else:
 
239
            return f(solution, attempt)
 
240
 
226
241
    def run(self, solution_data, attempt_data):
227
242
        """Run the tests to compare the solution and attempt data
228
243
        Returns the empty string if the test passes, or else an error message.
229
244
        """
230
245
 
 
246
        # check source code itself
 
247
        (test_type, f) = self._code_test
 
248
        if not self._check_code(solution_data['code'], attempt_data['code'], test_type, f):       
 
249
            return 'Unexpected code'
 
250
 
231
251
        # check function return value (None for scripts)
232
252
        (test_type, f) = self._result_test
233
253
        if not self._check_output(solution_data['result'], attempt_data['result'], test_type, f):       
234
 
            return 'function return value does not match'
 
254
            return 'Unexpected function return value'
235
255
 
236
256
        # check stdout
237
257
        (test_type, f) = self._stdout_test
238
258
        if not self._check_output(solution_data['stdout'], attempt_data['stdout'], test_type, f):       
239
 
            return 'stdout does not match'
 
259
            return 'Unexpected output'
240
260
 
241
261
        #check stderr
242
262
        (test_type, f) = self._stderr_test
243
263
        if not self._check_output(solution_data['stderr'], attempt_data['stderr'], test_type, f):        
244
 
            return 'stderr does not match'
 
264
            return 'Unexpected error output'
245
265
 
246
266
        #check exception
247
267
        (test_type, f) = self._exception_test
248
268
        if not self._check_output(solution_data['exception'], attempt_data['exception'], test_type, f):        
249
 
            return 'exception does not match'
250
 
 
 
269
            return 'Unexpected exception'
251
270
 
252
271
        solution_files = solution_data['modified_files']
253
272
        attempt_files = attempt_data['modified_files']
404
423
                raise TestError(sys.exc_info())
405
424
            
406
425
            result_dict = {}
407
 
            result_dict['description'] = test_part._succeed
 
426
            result_dict['description'] = test_part._pass_msg
408
427
            result_dict['passed'] = (result == '')
409
428
            if result_dict['passed'] == False:
410
429
                result_dict['error_message'] = result
411
 
                result_dict['description'] = test_part._fail
 
430
                result_dict['description'] = test_part._fail_msg
412
431
                passed = False
413
432
                
414
433
            results.append(result_dict)
422
441
        """ Execute the file given by 'filename' in global_space, and return the outputs. """
423
442
        self._initialise_global_space(global_space)
424
443
        data = self._run_function(lambda: execfile(filename, global_space))
 
444
        data['code'] = open(filename).read()
425
445
        return data
426
446
 
427
447
    def _execstring(self, string, global_space):
432
452
            exec string in global_space
433
453
            
434
454
        data = self._run_function(f)
 
455
        data['code'] = string
435
456
        return data
436
457
 
437
458
    def _initialise_global_space(self, global_space):
522
543
        self._tests.append(test_case)
523
544
        test_case.validate_functions(self._include_space)
524
545
 
525
 
    def run_tests(self, attempt_code, stop_on_fail=True):
 
546
    def run_tests(self, attempt_code, stop_on_fail=False):
526
547
        " Run all test cases and collate the results "
527
548
        
528
549
        problem_dict = {}