18
18
# Module: parse_exercise
19
19
# Author: Dilshan Angampitiya
20
20
# Steven Bird (revisions)
24
This file provides the function parse_exercise_file which takes an xml
25
specification of an exercise file and returns a test suite object for
26
that exercise. It throws a ParseException if there was a problem
30
from xml.dom.minidom import *
23
This file was hacked apart by Nick
31
26
from TestFramework import *
33
DEFAULT_TEST_TYPE = 'norm'
34
DEFAULT_CASE_TYPE = 'match'
36
class ParseException(Exception):
37
" Error when parsing the xml exercise file "
38
def __init___(self, reason):
44
def getTextData(element):
45
""" Get the text and cdata inside an element
46
Leading and trailing whitespace are stripped
49
for child in element.childNodes:
50
if child.nodeType == child.CDATA_SECTION_NODE:
52
if child.nodeType == child.TEXT_NODE:
57
def getCasePartData(partNode):
58
""" Create an TestCasePart instance from test part xml data
61
func_pass = partNode.getAttribute('pass')
62
func_fail = partNode.getAttribute('fail')
63
default = partNode.getAttribute('default')
64
if default == '': default = DEFAULT_CASE_TYPE
66
part = TestCasePart(func_pass, func_fail, default)
68
for child in partNode.childNodes:
69
if child.nodeType != child.ELEMENT_NODE:
72
if child.tagName == 'stdout':
73
test_type = child.getAttribute('type')
74
if test_type == '': test_type = DEFAULT_TEST_TYPE
75
part.add_stdout_test(getTextData(child), test_type)
76
elif child.tagName == 'stderr':
77
test_type = child.getAttribute('type')
78
if test_type == '': test_type = DEFAULT_TEST_TYPE
79
part.add_stderr_test(getTextData(child), test_type)
80
elif child.tagName == 'result':
81
test_type = child.getAttribute('type')
82
if test_type == '': test_type = DEFAULT_TEST_TYPE
83
part.add_result_test(getTextData(child), test_type)
84
elif child.tagName == 'exception':
85
test_type = child.getAttribute('type')
86
if test_type == '': test_type = DEFAULT_TEST_TYPE
87
part.add_exception_test(getTextData(child), test_type)
88
elif child.tagName == 'file':
89
test_type = child.getAttribute('type')
90
if test_type == '': test_type = DEFAULT_TEST_TYPE
91
filename = child.getAttribute('name')
93
raise ParseException("File without name in case %s" %case_name)
94
part.add_file_test(filename, getTextData(child), test_type)
95
elif child.tagName == 'code':
96
test_type = child.getAttribute('type')
97
if test_type == '': test_type = DEFAULT_TEST_TYPE
98
part.add_code_test(getTextData(child), test_type)
102
def getCaseData(caseNode, console):
103
""" Create a TestCase instance from test case xml data
106
case_name = caseNode.getAttribute('name')
107
function = caseNode.getAttribute('function')
108
if function == '': function = None
109
case = TestCase(console, case_name, function)
111
for child in caseNode.childNodes:
112
if child.nodeType != child.ELEMENT_NODE:
115
if child.tagName == 'stdin':
117
case.set_stdin(getTextData(child))
118
elif child.tagName == 'file':
120
filename = child.getAttribute('name')
122
raise ParseException("File without name in case %s" %case_name)
123
case.add_file(filename, getTextData(child))
124
elif child.tagName == 'var':
126
var_name = child.getAttribute('name')
127
var_val = child.getAttribute('value')
128
if not var_name or not var_val:
129
raise ParseException("Incomplete variable in case %s" %case_name)
130
case.add_variable(var_name, var_val)
131
elif child.tagName == 'arg':
133
arg_val = child.getAttribute('value')
134
arg_name = child.getAttribute('name')
135
if arg_name == '': arg_name = None
138
raise ParseException("Incomplete argument in case %s" %case_name)
139
case.add_arg(arg_val, arg_name)
140
elif child.tagName == 'exception':
141
exception_name = child.getAttribute('name')
142
if not exception_name:
143
raise ParseException("Incomplete exception in case %s" %case_name)
144
case.add_exception(exception_name)
145
elif child.tagName == 'function':
146
# specify a test case part
147
case.add_part(getCasePartData(child))
151
def parse_exercise_file(fileobj, console, exercise_num=1):
152
""" Parse an xml exercise file and return a testsuite for that exercise """
158
for child in dom.childNodes:
159
if child.nodeType == child.ELEMENT_NODE and child.tagName == 'exercise':
161
if count == exercise_num:
166
raise ParseException("Not enough exercises")
169
exercise_name = exercise.getAttribute('name')
170
if not exercise_name:
171
raise ParseException('Exercise name not supplied')
173
exercise_suite = TestSuite(exercise_name, console)
175
# get solution and include info
176
for child in exercise.childNodes:
177
if child.nodeType != child.ELEMENT_NODE:
179
if child.tagName == 'solution':
180
exercise_suite.add_solution(getTextData(child))
181
elif child.tagName == 'include':
182
exercise_suite.add_include_code(getTextData(child))
183
elif child.tagName == 'case':
184
exercise_suite.add_case(getCaseData(child, console))
186
return exercise_suite
28
def parse_exercise_file(exercise, console):
29
""" Parse an xml exercise file and return a testsuite for that exercise """
30
# Generate the TestSuite for the given exercise
31
return TestSuite(exercise, console)