Python’s object oriented design features allows considerable flexibility in how we design and structure our suite definition.
Each suite will have a different set of forces which determine how it should be designed.
Lets consider how we would design the tutorial examples in a more object oriented manner. We start with some design criteria we must meet.
- The default variables
...
- (ECF_HOME,etc)
...
- must
...
- be
...
- configurable
...
- and
...
- independent
...
- of
...
- the suites
- New suites must enable automatic job creation checking
- We need to write out definition as a separate file
- New suites should be able to re-use the “boiler plate” code defined by the above requirements
Here is possible design, that uses inheritance and the template design pattern:
#!/usr/bin/env python2.
...
7
...
import os
import ecflow
class DefaultVariables(object):
...
""
...
"
...
Provide the setup variables for each suite
...
"""
...
def add_to(self, node):
...
""
...
"
...
Adds ECF_INCLUDE,ECF_HOME to the input node
...
"""
...
node.add_variable("ECF_INCLUDE", os.getenv("HOME") + "/course")
...
node.add_variable("ECF_HOME", os.getenv("HOME") + "/course")
class BaseSuiteBuilder(object):
"""Abstract class. Add default variables to suite and enable job creation
...
...
...
checking for any derived
...
suite
...
...
""
...
"
...
...
def __init__
...
(self, default_variables):
...
self.defs = ecflow.Defs()
...
# use derived class name as suite
...
name
...
self.suite = self.defs.add_suite(type(self).__name__)
...
default_variables.add_to(self.suite)
...
def _build_definition_
...
hook(self):
...
""
...
"
...
Derived suite should override this function to build the
...
suite
Should not be called explicitly. How could we enforce this ?
...
...
...
""
...
"
...
...
pass
...
def setup(self):
...
""
...
"
...
Template/skeleton function.
...
...
...
Provides common algorithm for *all*
...
derivatives
Uses Holly wood principle.
...
...
...
""
...
"
...
...
# Build the
...
suite
...
self._build_definition_
...
hook()
...
...
# check job creation. Could use an
...
assert
...
job_check_
...
result
...
=
...
self.defs.check_job_creation()
...
if len(job_check_result) != 0:
...
print "Job creation
...
failed\n" + job_check_result
...
# Check trigger expressions and limit references
...
"
...
print self.defs.check()
...
# Allows definition creation to be separated from the
...
load
...
# Use the class name as the name of the definition
...
file
...
self.defs.save_as_defs( type(self).__name__
...
...
+
...
...
"
...
.def
...
"
...
)
...
...
class
...
SuiteBuilder(BaseSuiteBuilder):
...
""
...
"
...
My example suite.
...
Generates SuiteBuilder.def
...
"""
...
def __init__
...
(self, default_variables):
...
BaseSuiteBuilder.__init__
...
(self, default_variables)
...
def _build_definition_
...
hook(self):
...
f1
...
=
...
self.suite.add_family("family")
...
f1.add_task("task1")
...
f1.add_task("task2")
...
class
...
TestSuite(BaseSuiteBuilder):
...
""
...
"
...
My test suite. Generates TestSuite.def
...
"""
...
def __init__
...
(self, default_variables):
...
BaseSuiteBuilder.__init__
...
(self, default_variables)
...
def _build_definition_
...
hook(self):
...
self.suite.add_task("task1")
if __name__
...
...
==
...
...
"
...
__main__
...
"
...
:
...
...
my_suite = SuiteBuilder(DefaultVariables())
...
my_suite.setup()
...
my_test_
...
suite = TestSuite(DefaultVariables())
...
my_test_
...
suite.setup()
...