mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merged in jmchilton/galaxy-central-fork-1 (pull request #246)
Small functional test framework enhancements
This commit is contained in:
@@ -35,10 +35,13 @@ class Configuration( object ):
|
||||
self.gid = os.getgid() # if running under newgrp(1) we'll need to fix the group of data created on the cluster
|
||||
# Database related configuration
|
||||
self.database = resolve_path( kwargs.get( "database_file", "database/universe.sqlite" ), self.root )
|
||||
self.database_connection = kwargs.get( "database_connection", False )
|
||||
self.database_connection = kwargs.get( "database_connection", False )
|
||||
self.database_engine_options = get_database_engine_options( kwargs )
|
||||
self.database_create_tables = string_as_bool( kwargs.get( "database_create_tables", "True" ) )
|
||||
self.database_query_profiling_proxy = string_as_bool( kwargs.get( "database_query_profiling_proxy", "False" ) )
|
||||
# Don't set this to true for production databases, but probably should
|
||||
# default to True for sqlite databases.
|
||||
self.database_auto_migrate = string_as_bool( kwargs.get( "database_auto_migrate", "False" ) )
|
||||
# Where dataset files are stored
|
||||
self.file_path = resolve_path( kwargs.get( "file_path", "database/files" ), self.root )
|
||||
self.new_file_path = resolve_path( kwargs.get( "new_file_path", "database/tmp" ), self.root )
|
||||
|
||||
@@ -45,7 +45,22 @@ def create_or_verify_database( url, galaxy_config_file, engine_options={}, app=N
|
||||
log.error( "database_connection contains an unknown SQLAlchemy database dialect: %s" % dialect )
|
||||
# Create engine and metadata
|
||||
engine = create_engine( url, **engine_options )
|
||||
|
||||
def migrate():
|
||||
try:
|
||||
# Declare the database to be under a repository's version control
|
||||
db_schema = schema.ControlledSchema.create( engine, migrate_repository )
|
||||
except:
|
||||
# The database is already under version control
|
||||
db_schema = schema.ControlledSchema( engine, migrate_repository )
|
||||
# Apply all scripts to get to current version
|
||||
migrate_to_current_version( engine, db_schema )
|
||||
|
||||
meta = MetaData( bind=engine )
|
||||
if getattr( app.config, 'database_auto_migrate', False ):
|
||||
migrate()
|
||||
return
|
||||
|
||||
# Try to load dataset table
|
||||
try:
|
||||
dataset_table = Table( "dataset", meta, autoload=True )
|
||||
@@ -55,15 +70,7 @@ def create_or_verify_database( url, galaxy_config_file, engine_options={}, app=N
|
||||
if app:
|
||||
app.new_installation = True
|
||||
log.info( "No database, initializing" )
|
||||
# Database might or might not be versioned
|
||||
try:
|
||||
# Declare the database to be under a repository's version control
|
||||
db_schema = schema.ControlledSchema.create( engine, migrate_repository )
|
||||
except:
|
||||
# The database is already under version control
|
||||
db_schema = schema.ControlledSchema( engine, migrate_repository )
|
||||
# Apply all scripts to get to current version
|
||||
migrate_to_current_version( engine, db_schema )
|
||||
migrate()
|
||||
return
|
||||
try:
|
||||
hda_table = Table( "history_dataset_association", meta, autoload=True )
|
||||
|
||||
+114
-70
@@ -1,6 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os, sys, shutil, tempfile, re
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import tempfile
|
||||
import re
|
||||
from ConfigParser import SafeConfigParser
|
||||
|
||||
# Assume we are run from the galaxy root directory, add lib to the python path
|
||||
@@ -25,10 +29,18 @@ eggs.require( "Cheetah" )
|
||||
# http://code.google.com/p/python-nose/issues/detail?id=284
|
||||
eggs.require( "pysqlite" )
|
||||
|
||||
import atexit, logging, os, os.path, sys, tempfile
|
||||
import twill, unittest, time
|
||||
import subprocess, sys, threading, random
|
||||
import httplib, socket
|
||||
import atexit
|
||||
import logging
|
||||
import os.path
|
||||
import twill
|
||||
import unittest
|
||||
import time
|
||||
import subprocess
|
||||
import threading
|
||||
import random
|
||||
import httplib
|
||||
import socket
|
||||
import urllib
|
||||
from paste import httpserver
|
||||
import galaxy.app
|
||||
from galaxy.app import UniverseApplication
|
||||
@@ -56,6 +68,7 @@ installed_tool_panel_configs = [ 'shed_tool_conf.xml' ]
|
||||
# should this serve static resources (scripts, images, styles, etc.)
|
||||
STATIC_ENABLED = True
|
||||
|
||||
|
||||
def get_static_settings():
|
||||
"""Returns dictionary of the settings necessary for a galaxy App
|
||||
to be wrapped in the static middleware.
|
||||
@@ -68,16 +81,17 @@ def get_static_settings():
|
||||
#TODO: these should be copied from universe_wsgi.ini
|
||||
return dict(
|
||||
#TODO: static_enabled needed here?
|
||||
static_enabled = True,
|
||||
static_cache_time = 360,
|
||||
static_dir = static_dir,
|
||||
static_images_dir = os.path.join( static_dir, 'images', '' ),
|
||||
static_favicon_dir = os.path.join( static_dir, 'favicon.ico' ),
|
||||
static_scripts_dir = os.path.join( static_dir, 'scripts', '' ),
|
||||
static_style_dir = os.path.join( static_dir, 'june_2007_style', 'blue' ),
|
||||
static_robots_txt = os.path.join( static_dir, 'robots.txt' ),
|
||||
static_enabled=True,
|
||||
static_cache_time=360,
|
||||
static_dir=static_dir,
|
||||
static_images_dir=os.path.join( static_dir, 'images', '' ),
|
||||
static_favicon_dir=os.path.join( static_dir, 'favicon.ico' ),
|
||||
static_scripts_dir=os.path.join( static_dir, 'scripts', '' ),
|
||||
static_style_dir=os.path.join( static_dir, 'june_2007_style', 'blue' ),
|
||||
static_robots_txt=os.path.join( static_dir, 'robots.txt' ),
|
||||
)
|
||||
|
||||
|
||||
def get_webapp_global_conf():
|
||||
"""Get the global_conf dictionary sent as the first argument to app_factory.
|
||||
"""
|
||||
@@ -87,12 +101,13 @@ def get_webapp_global_conf():
|
||||
global_conf.update( get_static_settings() )
|
||||
return global_conf
|
||||
|
||||
|
||||
def generate_config_file( input_filename, output_filename, config_items ):
|
||||
'''
|
||||
Generate a config file with the configuration that has been defined for the embedded web application.
|
||||
This is mostly relevant when setting metadata externally, since the script for doing that does not
|
||||
have access to app.config.
|
||||
'''
|
||||
'''
|
||||
cp = SafeConfigParser()
|
||||
cp.read( input_filename )
|
||||
config_items_by_section = []
|
||||
@@ -110,9 +125,9 @@ def generate_config_file( input_filename, output_filename, config_items ):
|
||||
config_tuple = 'app:main', label, value
|
||||
config_items_by_section.append( config_tuple )
|
||||
print( config_items_by_section )
|
||||
|
||||
# Replace the default values with the provided configuration.
|
||||
for section, label, value in config_items_by_section:
|
||||
|
||||
if cp.has_option( section, label ):
|
||||
cp.remove_option( section, label )
|
||||
cp.set( section, label, str( value ) )
|
||||
@@ -120,6 +135,7 @@ def generate_config_file( input_filename, output_filename, config_items ):
|
||||
cp.write( fh )
|
||||
fh.close()
|
||||
|
||||
|
||||
def run_tests( test_config ):
|
||||
loader = nose.loader.TestLoader( config=test_config )
|
||||
plug_loader = test_config.plugins.prepareTestLoader( loader )
|
||||
@@ -134,7 +150,23 @@ def run_tests( test_config ):
|
||||
test_runner = plug_runner
|
||||
return test_runner.run( tests )
|
||||
|
||||
def main():
|
||||
|
||||
def __copy_database_template( source, db_path ):
|
||||
"""
|
||||
Copy a 'clean' sqlite template database (from file or URL) to specified
|
||||
database path.
|
||||
"""
|
||||
os.makedirs( os.path.dirname( db_path ) )
|
||||
if os.path.exists( source ):
|
||||
shutil.copy( source, db_path )
|
||||
assert os.path.exists( db_path )
|
||||
elif source.startswith("http"):
|
||||
urllib.urlretrieve( source, db_path )
|
||||
else:
|
||||
raise Exception( "Failed to copy database template from source %s" % source )
|
||||
|
||||
|
||||
def main():
|
||||
# ---- Configuration ------------------------------------------------------
|
||||
galaxy_test_host = os.environ.get( 'GALAXY_TEST_HOST', default_galaxy_test_host )
|
||||
galaxy_test_port = os.environ.get( 'GALAXY_TEST_PORT', None )
|
||||
@@ -174,7 +206,7 @@ def main():
|
||||
start_server = 'GALAXY_TEST_EXTERNAL' not in os.environ
|
||||
if os.path.exists( 'tool_data_table_conf.test.xml' ):
|
||||
tool_data_table_config_path = 'tool_data_table_conf.test.xml'
|
||||
else:
|
||||
else:
|
||||
tool_data_table_config_path = 'tool_data_table_conf.xml'
|
||||
shed_tool_data_table_config = 'shed_tool_data_table_conf.xml'
|
||||
tool_dependency_dir = os.environ.get( 'GALAXY_TOOL_DEPENDENCY_DIR', None )
|
||||
@@ -182,7 +214,9 @@ def main():
|
||||
galaxy_test_tmp_dir = os.environ.get( 'GALAXY_TEST_TMP_DIR', None )
|
||||
if galaxy_test_tmp_dir is None:
|
||||
galaxy_test_tmp_dir = tempfile.mkdtemp()
|
||||
|
||||
|
||||
database_auto_migrate = False
|
||||
|
||||
if start_server:
|
||||
psu_production = False
|
||||
galaxy_test_proxy_port = None
|
||||
@@ -212,29 +246,29 @@ def main():
|
||||
job_working_directory = os.path.join( new_file_path, 'job_working_directory' )
|
||||
os.mkdir( cluster_files_directory )
|
||||
os.mkdir( job_working_directory )
|
||||
kwargs = dict( database_engine_option_pool_size = '10',
|
||||
database_engine_option_max_overflow = '20',
|
||||
database_engine_option_strategy = 'threadlocal',
|
||||
nginx_x_accel_redirect_base = '/_x_accel_redirect',
|
||||
nginx_upload_store = nginx_upload_store,
|
||||
nginx_upload_path = '/_upload',
|
||||
allow_library_path_paste = 'True',
|
||||
cluster_files_directory = cluster_files_directory,
|
||||
job_working_directory = job_working_directory,
|
||||
outputs_to_working_directory = 'True',
|
||||
static_enabled = 'False',
|
||||
debug = 'False',
|
||||
track_jobs_in_database = 'True',
|
||||
job_scheduler_policy = 'FIFO',
|
||||
start_job_runners = 'pbs',
|
||||
default_cluster_job_runner = default_cluster_job_runner )
|
||||
kwargs = dict( database_engine_option_pool_size='10',
|
||||
database_engine_option_max_overflow='20',
|
||||
database_engine_option_strategy='threadlocal',
|
||||
nginx_x_accel_redirect_base='/_x_accel_redirect',
|
||||
nginx_upload_store=nginx_upload_store,
|
||||
nginx_upload_path='/_upload',
|
||||
allow_library_path_paste='True',
|
||||
cluster_files_directory=cluster_files_directory,
|
||||
job_working_directory=job_working_directory,
|
||||
outputs_to_working_directory='True',
|
||||
static_enabled='False',
|
||||
debug='False',
|
||||
track_jobs_in_database='True',
|
||||
job_scheduler_policy='FIFO',
|
||||
start_job_runners='pbs',
|
||||
default_cluster_job_runner=default_cluster_job_runner )
|
||||
psu_production = True
|
||||
else:
|
||||
tempdir = tempfile.mkdtemp( dir=galaxy_test_tmp_dir )
|
||||
# Configure the database path.
|
||||
if 'GALAXY_TEST_DBPATH' in os.environ:
|
||||
galaxy_db_path = os.environ[ 'GALAXY_TEST_DBPATH' ]
|
||||
else:
|
||||
else:
|
||||
galaxy_db_path = os.path.join( tempdir, 'database' )
|
||||
# Configure the paths Galaxy needs to test tools.
|
||||
file_path = os.path.join( galaxy_db_path, 'files' )
|
||||
@@ -243,7 +277,16 @@ def main():
|
||||
if 'GALAXY_TEST_DBURI' in os.environ:
|
||||
database_connection = os.environ['GALAXY_TEST_DBURI']
|
||||
else:
|
||||
database_connection = 'sqlite:///' + os.path.join( galaxy_db_path, 'universe.sqlite' )
|
||||
db_path = os.path.join( galaxy_db_path, 'universe.sqlite' )
|
||||
if 'GALAXY_TEST_DB_TEMPLATE' in os.environ:
|
||||
# Middle ground between recreating a completely new
|
||||
# database and pointing at existing database with
|
||||
# GALAXY_TEST_DBURI. The former requires a lot of setup
|
||||
# time, the latter results in test failures in certain
|
||||
# cases (namely tool shed tests expecting clean database).
|
||||
__copy_database_template(os.environ['GALAXY_TEST_DB_TEMPLATE'], db_path)
|
||||
database_auto_migrate = True
|
||||
database_connection = 'sqlite:///%s' % db_path
|
||||
kwargs = {}
|
||||
for dir in file_path, new_file_path:
|
||||
try:
|
||||
@@ -252,33 +295,34 @@ def main():
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# ---- Build Application --------------------------------------------------
|
||||
app = None
|
||||
# ---- Build Application --------------------------------------------------
|
||||
app = None
|
||||
if start_server:
|
||||
kwargs = dict( admin_users = 'test@bx.psu.edu',
|
||||
allow_library_path_paste = True,
|
||||
allow_user_creation = True,
|
||||
allow_user_deletion = True,
|
||||
database_connection = database_connection,
|
||||
datatype_converters_config_file = "datatype_converters_conf.xml.sample",
|
||||
file_path = file_path,
|
||||
id_secret = 'changethisinproductiontoo',
|
||||
job_queue_workers = 5,
|
||||
job_working_directory = job_working_directory,
|
||||
library_import_dir = library_import_dir,
|
||||
log_destination = "stdout",
|
||||
new_file_path = new_file_path,
|
||||
running_functional_tests = True,
|
||||
shed_tool_data_table_config = shed_tool_data_table_config,
|
||||
template_path = "templates",
|
||||
test_conf = "test.conf",
|
||||
tool_config_file = tool_config_file,
|
||||
tool_data_table_config_path = tool_data_table_config_path,
|
||||
tool_path = tool_path,
|
||||
tool_parse_help = False,
|
||||
update_integrated_tool_panel = False,
|
||||
use_heartbeat = False,
|
||||
user_library_import_dir = user_library_import_dir )
|
||||
kwargs = dict( admin_users='test@bx.psu.edu',
|
||||
allow_library_path_paste=True,
|
||||
allow_user_creation=True,
|
||||
allow_user_deletion=True,
|
||||
database_connection=database_connection,
|
||||
database_auto_migrate=database_auto_migrate,
|
||||
datatype_converters_config_file="datatype_converters_conf.xml.sample",
|
||||
file_path=file_path,
|
||||
id_secret='changethisinproductiontoo',
|
||||
job_queue_workers=5,
|
||||
job_working_directory=job_working_directory,
|
||||
library_import_dir=library_import_dir,
|
||||
log_destination="stdout",
|
||||
new_file_path=new_file_path,
|
||||
running_functional_tests=True,
|
||||
shed_tool_data_table_config=shed_tool_data_table_config,
|
||||
template_path="templates",
|
||||
test_conf="test.conf",
|
||||
tool_config_file=tool_config_file,
|
||||
tool_data_table_config_path=tool_data_table_config_path,
|
||||
tool_path=tool_path,
|
||||
tool_parse_help=False,
|
||||
update_integrated_tool_panel=False,
|
||||
use_heartbeat=False,
|
||||
user_library_import_dir=user_library_import_dir )
|
||||
if psu_production:
|
||||
kwargs[ 'global_conf' ] = None
|
||||
if not database_connection.startswith( 'sqlite://' ):
|
||||
@@ -309,7 +353,7 @@ def main():
|
||||
|
||||
# ---- Run webserver ------------------------------------------------------
|
||||
server = None
|
||||
|
||||
|
||||
if start_server:
|
||||
webapp = buildapp.app_factory( kwargs[ 'global_conf' ], app=app,
|
||||
use_translogger=False, static_enabled=STATIC_ENABLED )
|
||||
@@ -338,7 +382,7 @@ def main():
|
||||
t.start()
|
||||
# Test if the server is up
|
||||
for i in range( 10 ):
|
||||
conn = httplib.HTTPConnection( galaxy_test_host, galaxy_test_port ) # directly test the app, not the proxy
|
||||
conn = httplib.HTTPConnection( galaxy_test_host, galaxy_test_port ) # directly test the app, not the proxy
|
||||
conn.request( "GET", "/" )
|
||||
if conn.getresponse().status == 200:
|
||||
break
|
||||
@@ -347,7 +391,7 @@ def main():
|
||||
raise Exception( "Test HTTP server did not return '200 OK' after 10 tries" )
|
||||
# Test if the proxy server is up
|
||||
if psu_production:
|
||||
conn = httplib.HTTPConnection( galaxy_test_host, galaxy_test_proxy_port ) # directly test the app, not the proxy
|
||||
conn = httplib.HTTPConnection( galaxy_test_host, galaxy_test_proxy_port ) # directly test the app, not the proxy
|
||||
conn.request( "GET", "/" )
|
||||
if not conn.getresponse().status == 200:
|
||||
raise Exception( "Test HTTP proxy server did not return '200 OK'" )
|
||||
@@ -366,10 +410,10 @@ def main():
|
||||
success = False
|
||||
try:
|
||||
tool_configs = app.config.tool_configs
|
||||
# What requires these? Handy for (eg) functional tests to save outputs?
|
||||
# What requires these? Handy for (eg) functional tests to save outputs?
|
||||
if galaxy_test_save:
|
||||
os.environ[ 'GALAXY_TEST_SAVE' ] = galaxy_test_save
|
||||
# Pass in through script setenv, will leave a copy of ALL test validate files
|
||||
# Pass in through script setenv, will leave a copy of ALL test validate files
|
||||
os.environ[ 'GALAXY_TEST_HOST' ] = galaxy_test_host
|
||||
if testing_migrated_tools or testing_installed_tools:
|
||||
shed_tools_dict = {}
|
||||
@@ -398,7 +442,7 @@ def main():
|
||||
functional.test_toolbox.build_tests( testing_shed_tools=True )
|
||||
test_config = nose.config.Config( env=os.environ, ignoreFiles=ignore_files, plugins=nose.plugins.manager.DefaultPluginManager() )
|
||||
test_config.configure( sys.argv )
|
||||
result = run_tests( test_config )
|
||||
result = run_tests( test_config )
|
||||
success = result.wasSuccessful()
|
||||
try:
|
||||
os.unlink( tmp_tool_panel_conf )
|
||||
@@ -415,11 +459,11 @@ def main():
|
||||
os.environ[ 'GALAXY_TEST_FILE_DIR' ] = galaxy_test_file_dir
|
||||
test_config = nose.config.Config( env=os.environ, ignoreFiles=ignore_files, plugins=nose.plugins.manager.DefaultPluginManager() )
|
||||
test_config.configure( sys.argv )
|
||||
result = run_tests( test_config )
|
||||
result = run_tests( test_config )
|
||||
success = result.wasSuccessful()
|
||||
except:
|
||||
log.exception( "Failure running tests" )
|
||||
|
||||
|
||||
log.info( "Shutting down" )
|
||||
# ---- Tear down -----------------------------------------------------------
|
||||
if server:
|
||||
|
||||
@@ -1,38 +1,61 @@
|
||||
import sys, new
|
||||
import sys
|
||||
import new
|
||||
from galaxy.tools.parameters import grouping
|
||||
from galaxy.tools.parameters import basic
|
||||
from base.twilltestcase import TwillTestCase
|
||||
import galaxy.model
|
||||
from galaxy.model.orm import *
|
||||
from galaxy.model.orm import and_, desc
|
||||
from galaxy.model.mapping import context as sa_session
|
||||
|
||||
toolbox = None
|
||||
|
||||
|
||||
class ToolTestCase( TwillTestCase ):
|
||||
"""Abstract test case that runs tests based on a `galaxy.tools.test.ToolTest`"""
|
||||
|
||||
def do_it( self, testdef, shed_tool_id=None ):
|
||||
"""
|
||||
Run through a tool test case.
|
||||
"""
|
||||
self.__handle_test_def_errors( testdef )
|
||||
|
||||
latest_history = self.__setup_test_history()
|
||||
|
||||
self.__setup_test_data( testdef, shed_tool_id )
|
||||
|
||||
data_list = self.__run_tool( testdef )
|
||||
self.assertTrue( data_list )
|
||||
|
||||
self.__verify_outputs( testdef, shed_tool_id, data_list )
|
||||
|
||||
self.__delete_history( latest_history )
|
||||
|
||||
def __handle_test_def_errors(self, testdef):
|
||||
# If the test generation had an error, raise
|
||||
if testdef.error:
|
||||
if testdef.exception:
|
||||
raise testdef.exception
|
||||
else:
|
||||
raise Exception( "Test parse failure" )
|
||||
|
||||
def __setup_test_history( self ):
|
||||
# Start with a new history
|
||||
self.logout()
|
||||
self.login( email='test@bx.psu.edu' )
|
||||
admin_user = sa_session.query( galaxy.model.User ).filter( galaxy.model.User.table.c.email=='test@bx.psu.edu' ).one()
|
||||
admin_user = sa_session.query( galaxy.model.User ).filter( galaxy.model.User.table.c.email == 'test@bx.psu.edu' ).one()
|
||||
self.new_history()
|
||||
latest_history = sa_session.query( galaxy.model.History ) \
|
||||
.filter( and_( galaxy.model.History.table.c.deleted==False,
|
||||
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
|
||||
.filter( and_( galaxy.model.History.table.c.deleted == False,
|
||||
galaxy.model.History.table.c.user_id == admin_user.id ) ) \
|
||||
.order_by( desc( galaxy.model.History.table.c.create_time ) ) \
|
||||
.first()
|
||||
assert latest_history is not None, "Problem retrieving latest_history from database"
|
||||
if len( self.get_history_as_data_list() ) > 0:
|
||||
raise AssertionError("ToolTestCase.do_it failed")
|
||||
return latest_history
|
||||
|
||||
def __setup_test_data( self, testdef, shed_tool_id ):
|
||||
# Upload any needed files
|
||||
for fname, extra in testdef.required_files:
|
||||
children = extra.get( 'children', [] )
|
||||
metadata = extra.get( 'metadata', [] )
|
||||
composite_data = extra.get( 'composite_data', [] )
|
||||
self.upload_file( fname,
|
||||
@@ -41,9 +64,11 @@ class ToolTestCase( TwillTestCase ):
|
||||
metadata=metadata,
|
||||
composite_data=composite_data,
|
||||
shed_tool_id=shed_tool_id )
|
||||
|
||||
print "Uploaded file: ", fname, ", ftype: ", extra.get( 'ftype', 'auto' ), ", extra: ", extra
|
||||
#Post upload attribute editing
|
||||
edit_attributes = extra.get( 'edit_attributes', [] )
|
||||
|
||||
#currently only renaming is supported
|
||||
for edit_att in edit_attributes:
|
||||
if edit_att.get( 'type', None ) == 'name':
|
||||
@@ -51,29 +76,35 @@ class ToolTestCase( TwillTestCase ):
|
||||
assert new_name, 'You must supply the new dataset name as the value tag of the edit_attributes tag'
|
||||
hda_id = self.get_history_as_data_list()[-1].get( 'id' )
|
||||
try:
|
||||
self.edit_hda_attribute_info( hda_id = str(hda_id), new_name = new_name )
|
||||
self.edit_hda_attribute_info( hda_id=str(hda_id), new_name=new_name )
|
||||
except:
|
||||
print "### call to edit_hda failed for hda_id %s, new_name=%s" % (hda_id,new_name)
|
||||
print "### call to edit_hda failed for hda_id %s, new_name=%s" % (hda_id, new_name)
|
||||
else:
|
||||
raise Exception( 'edit_attributes type (%s) is unimplemented' % edit_att.get( 'type', None ) )
|
||||
|
||||
def __run_tool( self, testdef ):
|
||||
# We need to handle the case where we've uploaded a valid compressed file since the upload
|
||||
# tool will have uncompressed it on the fly.
|
||||
all_inputs = {}
|
||||
for name, value, _ in testdef.inputs:
|
||||
all_inputs[ name ] = value
|
||||
|
||||
# See if we have a grouping.Repeat element
|
||||
repeat_name = None
|
||||
for input_name, input_value in testdef.tool.inputs_by_page[0].items():
|
||||
if isinstance( input_value, grouping.Repeat ) and all_inputs.get( input_name, 1 ) not in [ 0, "0" ]: #default behavior is to test 1 repeat, for backwards compatibility
|
||||
if isinstance( input_value, grouping.Repeat ) and all_inputs.get( input_name, 1 ) not in [ 0, "0" ]: # default behavior is to test 1 repeat, for backwards compatibility
|
||||
repeat_name = input_name
|
||||
break
|
||||
|
||||
#check if we need to verify number of outputs created dynamically by tool
|
||||
if testdef.tool.force_history_refresh:
|
||||
job_finish_by_output_count = len( self.get_history_as_data_list() )
|
||||
else:
|
||||
job_finish_by_output_count = False
|
||||
|
||||
# Do the first page
|
||||
page_inputs = self.__expand_grouping(testdef.tool.inputs_by_page[0], all_inputs)
|
||||
page_inputs = self.__expand_grouping(testdef.tool.inputs_by_page[0], all_inputs)
|
||||
|
||||
# Run the tool
|
||||
self.run_tool( testdef.tool.id, repeat_name=repeat_name, **page_inputs )
|
||||
print "page_inputs (0)", page_inputs
|
||||
@@ -82,6 +113,7 @@ class ToolTestCase( TwillTestCase ):
|
||||
page_inputs = self.__expand_grouping(testdef.tool.inputs_by_page[i], all_inputs)
|
||||
self.submit_form( **page_inputs )
|
||||
print "page_inputs (%i)" % i, page_inputs
|
||||
|
||||
# Check the results ( handles single or multiple tool outputs ). Make sure to pass the correct hid.
|
||||
# The output datasets from the tool should be in the same order as the testdef.outputs.
|
||||
data_list = None
|
||||
@@ -89,21 +121,30 @@ class ToolTestCase( TwillTestCase ):
|
||||
data_list = self.get_history_as_data_list()
|
||||
if job_finish_by_output_count and len( testdef.outputs ) > ( len( data_list ) - job_finish_by_output_count ):
|
||||
data_list = None
|
||||
self.assertTrue( data_list )
|
||||
return data_list
|
||||
|
||||
def __verify_outputs( self, testdef, shed_tool_id, data_list ):
|
||||
maxseconds = testdef.maxseconds
|
||||
|
||||
elem_index = 0 - len( testdef.outputs )
|
||||
for output_tuple in testdef.outputs:
|
||||
name, outfile, attributes = output_tuple
|
||||
# Get the correct hid
|
||||
elem = data_list[ elem_index ]
|
||||
self.assertTrue( elem is not None )
|
||||
elem_hid = elem.get( 'hid' )
|
||||
self.__verify_output( output_tuple, shed_tool_id, elem, maxseconds=maxseconds )
|
||||
elem_index += 1
|
||||
|
||||
def __verify_output( self, output_tuple, shed_tool_id, elem, maxseconds ):
|
||||
name, outfile, attributes = output_tuple
|
||||
elem_hid = elem.get( 'hid' )
|
||||
try:
|
||||
self.verify_dataset_correctness( outfile, hid=elem_hid, maxseconds=testdef.maxseconds, attributes=attributes, shed_tool_id=shed_tool_id )
|
||||
except Exception, e:
|
||||
self.verify_dataset_correctness( outfile, hid=elem_hid, attributes=attributes, shed_tool_id=shed_tool_id )
|
||||
except Exception:
|
||||
print >>sys.stderr, self.get_job_stdout( elem.get( 'id' ), format=True )
|
||||
print >>sys.stderr, self.get_job_stderr( elem.get( 'id' ), format=True )
|
||||
raise
|
||||
|
||||
def __delete_history( self, latest_history ):
|
||||
self.delete_history( id=self.security.encode_id( latest_history.id ) )
|
||||
|
||||
def __expand_grouping( self, tool_inputs, declared_inputs, prefix='' ):
|
||||
@@ -121,14 +162,14 @@ class ToolTestCase( TwillTestCase ):
|
||||
else:
|
||||
expanded_inputs[ "%s|%s" % ( new_prefix, value.test_param.name ) ] = case.value
|
||||
for input_name, input_value in case.inputs.items():
|
||||
expanded_inputs.update( self.__expand_grouping( { input_name:input_value }, declared_inputs, prefix = new_prefix ) )
|
||||
expanded_inputs.update( self.__expand_grouping( { input_name: input_value }, declared_inputs, prefix=new_prefix ) )
|
||||
elif isinstance( value, grouping.Repeat ):
|
||||
for repeat_index in xrange( 0, 1 ): #need to allow for and figure out how many repeats we have
|
||||
for repeat_index in xrange( 0, 1 ): # need to allow for and figure out how many repeats we have
|
||||
for r_name, r_value in value.inputs.iteritems():
|
||||
new_prefix = "%s_%d" % ( value.name, repeat_index )
|
||||
if prefix:
|
||||
new_prefix = "%s|%s" % ( prefix, new_prefix )
|
||||
expanded_inputs.update( self.__expand_grouping( { new_prefix : r_value }, declared_inputs, prefix = new_prefix ) )
|
||||
new_prefix = "%s_%d" % ( value.name, repeat_index )
|
||||
if prefix:
|
||||
new_prefix = "%s|%s" % ( prefix, new_prefix )
|
||||
expanded_inputs.update( self.__expand_grouping( { new_prefix : r_value }, declared_inputs, prefix=new_prefix ) )
|
||||
elif value.name not in declared_inputs:
|
||||
print "%s not declared in tool test, will not change default value." % value.name
|
||||
elif isinstance(declared_inputs[value.name], str):
|
||||
@@ -143,6 +184,7 @@ class ToolTestCase( TwillTestCase ):
|
||||
expanded_inputs[value.name] = declared_inputs[value.name]
|
||||
return expanded_inputs
|
||||
|
||||
|
||||
def build_tests( testing_shed_tools=False ):
|
||||
"""
|
||||
If the module level variable `toolbox` is set, generate `ToolTestCase`
|
||||
@@ -151,12 +193,15 @@ def build_tests( testing_shed_tools=False ):
|
||||
"""
|
||||
if toolbox is None:
|
||||
return
|
||||
|
||||
# Push all the toolbox tests to module level
|
||||
G = globals()
|
||||
|
||||
# Eliminate all previous tests from G.
|
||||
for key, val in G.items():
|
||||
if key.startswith( 'TestForTool_' ):
|
||||
del G[ key ]
|
||||
|
||||
for i, tool_id in enumerate( toolbox.tools_by_id ):
|
||||
tool = toolbox.get_tool( tool_id )
|
||||
if tool.tests:
|
||||
|
||||
Reference in New Issue
Block a user