mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Outline new API based galaxy interactor for functional tests.
Add mechanism to tool test parser code to determine which Galaxy interactor should be used ('twill' or 'api' are current options). This maybe a stop gap to force usage of the API interactor until that becomes the default or may prove in the long term to be essential if there are certain tools that will always require Twill-specific functionality or if new browser-based JavaScript (e.g. w/selenium) are implemented. An interactor value can be specified at the tests level and/or at the level of individual test elements in the tool XML (using the 'interactor' attribute on either element).
The current default interactor is 'twill'. The default interactor app-wide can be overridden with the GALAXY_TEST_DEFAULT_INTERACTOR environment variable.
This commit is contained in:
@@ -52,7 +52,7 @@ from galaxy.tools.parameters.input_translation import ToolInputTranslator
|
||||
from galaxy.tools.parameters.output import ToolOutputActionGroup
|
||||
from galaxy.tools.parameters.validation import LateValidationError
|
||||
from galaxy.tools.filters import FilterFactory
|
||||
from galaxy.tools.test import ToolTestBuilder
|
||||
from galaxy.tools.test import parse_tests_elem
|
||||
from galaxy.util import listify, parse_xml, rst_to_html, string_as_bool, string_to_object, xml_text, xml_to_string
|
||||
from galaxy.util.bunch import Bunch
|
||||
from galaxy.util.expressions import ExpressionContext
|
||||
@@ -1222,7 +1222,7 @@ class Tool( object, Dictifiable ):
|
||||
tests_elem = root.find( "tests" )
|
||||
if tests_elem:
|
||||
try:
|
||||
self.parse_tests( tests_elem )
|
||||
self.tests = parse_tests_elem( self, tests_elem )
|
||||
except:
|
||||
log.exception( "Failed to parse tool tests" )
|
||||
else:
|
||||
@@ -1564,16 +1564,6 @@ class Tool( object, Dictifiable ):
|
||||
log.error( "Traceback: %s" % trace_msg )
|
||||
return return_level
|
||||
|
||||
def parse_tests( self, tests_elem ):
|
||||
"""
|
||||
Parse any "<test>" elements, create a `ToolTestBuilder` for each and
|
||||
store in `self.tests`.
|
||||
"""
|
||||
self.tests = []
|
||||
for i, test_elem in enumerate( tests_elem.findall( 'test' ) ):
|
||||
test = ToolTestBuilder( self, test_elem, i )
|
||||
self.tests.append( test )
|
||||
|
||||
def parse_input_page( self, input_elem, enctypes ):
|
||||
"""
|
||||
Parse a page of inputs. This basically just calls 'parse_input_elem',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
import os.path
|
||||
from parameters import basic
|
||||
from parameters import grouping
|
||||
@@ -8,6 +9,21 @@ log = logging.getLogger( __name__ )
|
||||
|
||||
DEFAULT_FTYPE = 'auto'
|
||||
DEFAULT_DBKEY = 'hg17'
|
||||
DEFAULT_INTERACTOR = "twill" # Default mechanism test code uses for interacting with Galaxy instance.
|
||||
|
||||
|
||||
def parse_tests_elem(tool, tests_elem):
|
||||
"""
|
||||
Build ToolTestBuilder objects for each "<test>" elements and
|
||||
return default interactor (if any).
|
||||
"""
|
||||
default_interactor = os.environ.get( 'GALAXY_TEST_DEFAULT_INTERACTOR', DEFAULT_INTERACTOR )
|
||||
tests_default_interactor = tests_elem.get( 'interactor', default_interactor )
|
||||
tests = []
|
||||
for i, test_elem in enumerate( tests_elem.findall( 'test' ) ):
|
||||
test = ToolTestBuilder( tool, test_elem, i, default_interactor=tests_default_interactor )
|
||||
tests.append( test )
|
||||
return tests
|
||||
|
||||
|
||||
class ToolTestBuilder( object ):
|
||||
@@ -17,7 +33,7 @@ class ToolTestBuilder( object ):
|
||||
doing dynamic tests in this way allows better integration)
|
||||
"""
|
||||
|
||||
def __init__( self, tool, test_elem, i ):
|
||||
def __init__( self, tool, test_elem, i, default_interactor ):
|
||||
name = test_elem.get( 'name', 'Test-%d' % (i + 1) )
|
||||
maxseconds = int( test_elem.get( 'maxseconds', '120' ) )
|
||||
|
||||
@@ -30,7 +46,7 @@ class ToolTestBuilder( object ):
|
||||
self.error = False
|
||||
self.exception = None
|
||||
|
||||
self.__parse_elem( test_elem, i )
|
||||
self.__parse_elem( test_elem, i, default_interactor )
|
||||
|
||||
def test_data( self ):
|
||||
"""
|
||||
@@ -57,12 +73,18 @@ class ToolTestBuilder( object ):
|
||||
|
||||
yield data_dict
|
||||
|
||||
def __parse_elem( self, test_elem, i ):
|
||||
def __parse_elem( self, test_elem, i, default_interactor ):
|
||||
# Composite datasets need a unique name: each test occurs in a fresh
|
||||
# history, but we'll keep it unique per set of tests - use i (test #)
|
||||
# and composite_data_names_counter (instance per test #)
|
||||
composite_data_names_counter = 0
|
||||
try:
|
||||
# Mechanism test code uses for interacting with Galaxy instance,
|
||||
# until 'api' is the default switch this to API to use its new
|
||||
# features. Once 'api' is the default set to 'twill' to use legacy
|
||||
# features or workarounds.
|
||||
self.interactor = test_elem.get( 'interactor', default_interactor )
|
||||
|
||||
for param_elem in test_elem.findall( "param" ):
|
||||
attrib = dict( param_elem.attrib )
|
||||
if 'values' in attrib:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import sys
|
||||
import new
|
||||
import os
|
||||
from galaxy.tools.parameters import grouping
|
||||
from galaxy.util import string_as_bool
|
||||
from base.twilltestcase import TwillTestCase
|
||||
import galaxy.model
|
||||
from galaxy.model.orm import and_, desc
|
||||
@@ -20,7 +22,7 @@ class ToolTestCase( TwillTestCase ):
|
||||
|
||||
self.__handle_test_def_errors( testdef )
|
||||
|
||||
galaxy_interactor = GalaxyInteractorTwill( self )
|
||||
galaxy_interactor = self.__galaxy_interactor( testdef )
|
||||
|
||||
test_history = galaxy_interactor.new_history()
|
||||
|
||||
@@ -38,6 +40,11 @@ class ToolTestCase( TwillTestCase ):
|
||||
|
||||
galaxy_interactor.delete_history( test_history )
|
||||
|
||||
def __galaxy_interactor( self, testdef ):
|
||||
interactor_key = testdef.interactor
|
||||
interactor_class = GALAXY_INTERACTORS[ interactor_key ]
|
||||
return interactor_class( self )
|
||||
|
||||
def __handle_test_def_errors(self, testdef):
|
||||
# If the test generation had an error, raise
|
||||
if testdef.error:
|
||||
@@ -68,6 +75,25 @@ class ToolTestCase( TwillTestCase ):
|
||||
raise
|
||||
|
||||
|
||||
class GalaxyInteractorApi( object ):
|
||||
|
||||
def __init__( self, twill_test_case ):
|
||||
self.twill_test_case = twill_test_case
|
||||
self.master_api_key = twill_test_case.master_api_key
|
||||
|
||||
def new_history( self ):
|
||||
return None
|
||||
|
||||
def stage_data_async( self, test_data, shed_tool_id, async=True ):
|
||||
return lambda: True
|
||||
|
||||
def run_tool( self, testdef ):
|
||||
return []
|
||||
|
||||
def delete_history( self, history ):
|
||||
return None
|
||||
|
||||
|
||||
class GalaxyInteractorTwill( object ):
|
||||
|
||||
def __init__( self, twill_test_case ):
|
||||
@@ -231,3 +257,9 @@ def build_tests( testing_shed_tools=False, master_api_key=None ):
|
||||
# from baseclasses (which should be a tuple of classes) and with namespace dict.
|
||||
new_class_obj = new.classobj( name, baseclasses, namespace )
|
||||
G[ name ] = new_class_obj
|
||||
|
||||
|
||||
GALAXY_INTERACTORS = {
|
||||
'api': GalaxyInteractorApi,
|
||||
'twill': GalaxyInteractorTwill,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user