FLEXPART Testing Environment CTBTO WO8
 All Classes Namespaces Files Functions Variables Pages
TestSuite.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 """
3 Created on Thu Aug 13 23:45:12 2015
4 
5 @author: morton
6 
7 Don Morton
8 Boreal Scientific Computing LLC, Fairbanks, Alaska, USA
9 Don.Morton@borealscicomp.com
10 http://www.borealscicomp.com/
11 
12 @contributors
13 Christian Maurer
14 Delia Arnold
15 ZAMG, Vienna, Austria
16 christian.maurer@zamg.ac.at
17 delia.arnold-arias@zamg.ac.at
18 
19 """
20 
21 import os
22 import xml.etree.ElementTree as XMLTree
23 
24 import distrotest.BasicTest as BasicTest
25 import distrotest.RunCase as RunCase
26 import distrotest.MetCase as MetCase
27 import distrotest.Distribution as Distribution
28 
29 class TestSuite(object):
30 
31  """
32  Container for an entire test suite, initialised from an XML config file.
33  A TestSuite object contains Distribution classes, which in turn will each
34  contain MetCase, RunCase and BasicTest objects. A TestSuite object should
35  have all of the information necessary for testing routines to do their
36  thang.
37  """
38 
39  def __init__(self, xml_files=None):
40 
41  """
42  Creates a list of Distribution objects from a list of xml_files.
43  If only a single file is entered as an argument (which may often
44  be the case), it is inserted into a list of one element. An XML file
45  is read, and a Distribution object is manufactured from this
46  """
47 
48  if xml_files:
49  if type(xml_files) is str:
50  self._xml_files = [xml_files]
51  elif type(xml_files) is list:
52  self._xml_files = xml_files
53  else:
54  raise Exception('xml_files should be a list')
55  else:
56  raise Exception('A list of valid xml_files is needed')
57 
58  # If we are here, we have our XML file list, and we should load the
59  # contents of each one into a Distribution object
61  for the_xml_file in self._xml_files:
62 
63  # print the_xml_file
64  try:
65  #print 'hello'
66  distro_tree = XMLTree.parse(the_xml_file)
67  #print distro_tree
68 
69  except:
70  print 'Error parsing XML file: ' + str(the_xml_file)
71  raise Exception
72 
73  distro_object = self._create_distribution(distro_tree=distro_tree)
74  self._distribution_list.append( distro_object )
75 
76 
77 
78 
80  return self._distribution_list
81 
82  def _create_distribution(self, distro_tree=None):
83 
84  """
85  Creates and returns a distribution object (e.g. FLEXPART-ECMWF
86  (nested/not nested input), FLEXPART-GFS or FLEXPART-WRF) based
87  on the parsed XML distribution tree
88 
89  """
90 
91  # Find the Distribution parameter and MetCase nodes and iterate
92  # through those to create the
93  # MetCase Objects (which will recursively create RunCase and
94  # BasicTest objects). This is set up, however, to permit empty
95  # metcase lists. Creates and returns a Distribution object
96 
97  the_distribution = None
98  if distro_tree:
99 
100  distro_path = parmod_path = exec_name = None
101  met_case_list = []
102  distro_root = distro_tree.getroot()
103  for child in distro_root:
104  if child.tag == 'metcase':
105  the_met_case = self._create_met_case(met_case_tree=child)
106  met_case_list.append(the_met_case)
107  elif child.tag == 'short_descr':
108  descr = child.text.strip()
109  elif child.tag == 'distropath':
110  distro_path = child.text.strip()
111  elif child.tag == 'parmodpath':
112  parmod_path = child.text.strip()
113  elif child.tag == 'execname':
114  exec_name = child.text.strip()
115 
116 
117  if descr and distro_path and exec_name:
118  the_distribution = Distribution.Distribution(
119  descr=descr,
120  distro_path=distro_path,
121  parmod_path=parmod_path,
122  exec_name=exec_name,
123  met_case_list=met_case_list
124  )
125  else:
126  raise ValueError(
127  "Unable to create Distribution object - missing args"
128  )
129 
130  return the_distribution
131 
132 
133  def _create_met_case(self, met_case_tree=None):
134 
135  """ Creates and returns a MetCase object based on the parsed XML
136  tree. This will read in the parameters for a MetCase object, as
137  well as RunCase objects, if available. Otherwise, inserts an empty
138  RunCase list"""
139 
140  the_met_case = None
141  metnestfile_dir = None
142  if met_case_tree is not None:
143  run_case_list = []
144  met_case_root = met_case_tree.getchildren()
145  for child in met_case_root:
146  if child.tag == 'runcase':
147  the_run_case = self._create_run_case(run_case_tree=child)
148  run_case_list.append(the_run_case)
149  elif child.tag == "short_descr":
150  descr = child.text.strip()
151  elif child.tag == "metfiledir":
152  metfile_dir = child.text.strip()
153  elif child.tag == "metnestfiledir":
154  metnestfile_dir = child.text.strip()
155 
156  if descr and metfile_dir:
157  the_met_case = MetCase.MetCase(descr=descr,
158  metfile_dir=metfile_dir,
159  metnestfile_dir=metnestfile_dir,
160  run_case_list=run_case_list)
161  else:
162  raise ValueError(
163  "Unable to create MetCase object - missing args"
164  )
165 
166  return the_met_case
167 
168  def _create_run_case(self, run_case_tree=None):
169  """Creates and returns a RunCase object based on the parsed XML tree.
170  This will read in the parameters for runcase objects, as
171  well as BasicTest objects, if available. Otherwise, inserts and
172  empty BasicTest list"""
173 
174  the_run_case = None
175  if run_case_tree is not None:
176  descr = testtype = max_threshold = None
177 
178  basic_test_list = []
179  run_case_root = run_case_tree.getchildren()
180  for child in run_case_root:
181  if child.tag == 'basictest':
182  the_basic_test = self._create_basic_test(basic_test_tree=child)
183  basic_test_list.append(the_basic_test)
184  elif child.tag == 'short_descr':
185  descr = child.text.strip()
186  elif child.tag == 'casedir':
187  case_dir = child.text.strip()
188  elif child.tag == 'controldatadir':
189  control_data_dir = child.text.strip()
190 
191 
192  if descr and case_dir and control_data_dir:
193  the_run_case = RunCase.RunCase(descr=descr,
194  case_dir=case_dir,
195  control_data_dir=control_data_dir,
196  test_list=basic_test_list)
197  else:
198  raise ValueError(
199  "Unable to create RunCase object - missing args"
200  )
201 
202  return the_run_case
203 
204 
205  def _create_basic_test(self, basic_test_tree=None):
206 
207  """ Creates and returns a BasicTest object based on the parsed
208  XML tree parameters"""
209 
210  the_basic_test = None
211  if basic_test_tree is not None:
212  basic_test_root = basic_test_tree.getchildren()
213 
214  for child in basic_test_root:
215  if child.tag == 'short_descr':
216  descr = child.text.strip()
217  elif child.tag == 'type':
218  testtype = child.text.strip()
219  elif child.tag == 'max_threshold':
220  max_threshold = child.text.strip()
221 
222  if descr and testtype and max_threshold:
223  the_basic_test = BasicTest.BasicTest(descr=descr,
224  test_type=testtype,
225  threshold=max_threshold)
226  else:
227  raise ValueError(
228  "Unable to create BasicTest object - missing args"
229  )
230 
231  return the_basic_test
232 
233