1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import os
21 import qm.common
22 from qm.extension import get_class_arguments
23 import qm.fields
24 import qm.label
25 import qm.structured_text
26 import qm.test.base
27 from qm.test.database import *
28 from qm.test.file_database import *
29 from qm.test.suite import *
30 from qm.test.classes.explicit_suite import ExplicitSuite
31 import qm.xmlutil
32 import shutil
33 import string
34 import xml
35 import xml.dom
36 import xml.sax
37
38
39
40
41
43 """An error in the format or contents of an XML test file."""
44
45 pass
46
47
48
50 """A database representing tests as XML files in a directory tree."""
51
58
59
70
71
82
83
84
119
120
122 """Construct the path to an attachment data file.
123
124 'item_id' -- The test or resource item of which the attachment
125 is part.
126
127 'file_name' -- The file name specified for the attachment."""
128
129
130 parent_suite_path \
131 = os.path.dirname(self._GetPathFromLabel(item_id))
132
133
134
135 abs_len = len(parent_suite_path) + len(os.sep)
136
137
138 base, extension = os.path.splitext(file_name)
139 safe_file_name = qm.label.thunk(base) + extension
140
141 data_file_path = os.path.join(parent_suite_path, safe_file_name)
142
143
144
145 if extension not in [self.GetTestExtension(),
146 self.GetSuiteExtension(),
147 self.GetResourceExtension()] \
148 and not os.path.exists(data_file_path):
149 return data_file_path[abs_len:]
150
151
152
153 index = 0
154 while 1:
155 data_file_path = os.path.join(parent_suite_path,
156 safe_file_name + ".%d" % index)
157 if not os.path.exists(data_file_path):
158 return data_file_path[abs_len:]
159 index = index + 1
160
161
162 - def __LoadItem(self, item_id, path, document_parser):
163 """Load an item (a test or resource) from an XML file.
164
165 This function is used for logic common to tests and resources.
166
167 'item_id' -- The ID of the item to get.
168
169 'path' -- The path to the test or resource file.
170
171 'document_parser' -- A function that takes an XML DOM document
172 as its argument and returns the constructed item object."""
173
174
175 document = qm.xmlutil.load_xml_file(path)
176
177 item = document_parser(item_id, document)
178
179 return item
180
181
183 """Return a test object constructed from a test document.
184
185 'test_id' -- The test ID of the test.
186
187 'document' -- A DOM document containing a single test element
188 from which the test is constructed."""
189
190
191 test_class, arguments \
192 = (qm.extension.parse_dom_element
193 (document.documentElement,
194 lambda n : qm.test.base.get_test_class(n, self),
195 self.__store))
196 test_class_name = qm.extension.get_extension_class_name(test_class)
197
198 for p in document.documentElement.getElementsByTagName("prerequisite"):
199 if not arguments.has_key("prerequisites"):
200 arguments["prerequisites"] = []
201 arguments["prerequisites"].append((qm.xmlutil.get_dom_text(p),
202 p.getAttribute("outcome")))
203
204 for r in document.documentElement.getElementsByTagName("resource"):
205 if not arguments.has_key("resources"):
206 arguments["resources"] = []
207 arguments["resources"].append(qm.xmlutil.get_dom_text(r))
208
209 test = TestDescriptor(self,
210 test_id,
211 test_class_name,
212 arguments)
213 return test
214
215
217 """Return a resource object constructed from a resource document.
218
219 'resource_id' -- The resource ID of the resource.
220
221 'document' -- A DOM document node containing a single resource
222 element from which the resource object is constructed."""
223
224
225 resource_class, arguments \
226 = (qm.extension.parse_dom_element
227 (document.documentElement,
228 lambda n : qm.test.base.get_resource_class(n, self)))
229 resource_class_name \
230 = qm.extension.get_extension_class_name(resource_class)
231
232 resource = ResourceDescriptor(self,
233 resource_id,
234 resource_class_name,
235 arguments)
236 return resource
237
238
240 """Load the test suite file at 'path' with suite ID 'suite_id'.
241
242 returns -- A 'Suite' object."""
243
244
245 if not os.path.isfile(path):
246 raise NoSuchSuiteError, "no suite file %s" % path
247
248 document = qm.xmlutil.load_xml_file(path)
249
250
251
252 suite = document.documentElement
253 if suite.tagName == "suite":
254 assert suite.tagName == "suite"
255
256 test_ids = qm.xmlutil.get_child_texts(suite, "test_id")
257 suite_ids = qm.xmlutil.get_child_texts(suite, "suite_id")
258
259 for id_ in test_ids + suite_ids:
260 if not self.IsValidLabel(id_, is_component = 0):
261 raise RuntimeError, qm.error("invalid id", id=id_)
262
263 return ExplicitSuite({ "is_implicit" : "false",
264 "test_ids" : test_ids,
265 "suite_ids" : suite_ids },
266 **{ ExplicitSuite.EXTRA_ID : suite_id,
267 ExplicitSuite.EXTRA_DATABASE : self })
268 else:
269
270 extension_class, arguments = \
271 qm.extension.parse_dom_element(
272 suite,
273 lambda n: get_extension_class(n, "suite", self),
274 self.GetAttachmentStore())
275
276 extras = { extension_class.EXTRA_ID : suite_id,
277 extension_class.EXTRA_DATABASE : self }
278 return extension_class(arguments, **extras)
279
280
293
294
296 """Returns the 'AttachmentStore' associated with the database.
297
298 returns -- The 'AttachmentStore' containing the attachments
299 associated with tests and resources in this database."""
300
301 return self.__store
302
303
311
312
313
314
315
316
317
318
319