- Data tables - See all data tables available in this Galaxy.
+ Data tables - See all data tables available in this Galaxy.
- Display applications - See all display applications configured in this Galaxy.
+ Display applications - See all display applications configured in this Galaxy.
- Manage jobs - Display all jobs that are currently not finished (i.e., their state is new, waiting, queued, or running). Administrators are able to cleanly stop long-running jobs.
+ Manage jobs - Display all jobs that are currently not finished (i.e., their state is new, waiting, queued, or running). Administrators are able to cleanly stop long-running jobs.
- Local data - Manage the reference (and other) data that is stored within Tool Data Tables. See wiki for details.
+ Local data - Manage the reference (and other) data that is stored within Tool Data Tables. See wiki for details.
User Management
- Users - The primary user management interface, displaying information associated with each user and providing operations for resetting passwords, updating user information, impersonating a user, and more.
+ Users - The primary user management interface, displaying information associated with each user and providing operations for resetting passwords, updating user information, impersonating a user, and more.
%if trans.app.config.enable_quotas:
- Quotas - Manage user space quotas. See wiki for details.
+ Quotas - Manage user space quotas. See wiki for details.
%endif
- Groups - A view of all groups along with the members of the group and the roles associated with each group.
+ Groups - A view of all groups along with the members of the group and the roles associated with each group.
- Roles - A view of all non-private roles along with the role type, and the users and groups that are associated with the role.
+ Roles - A view of all non-private roles along with the role type, and the users and groups that are associated with the role.
Also includes a view of the data library datasets that are associated with the role and the permissions applied to each dataset.
- Forms - Manage local form definitions.
+ Forms - Manage local form definitions.
- View migration stages - See the list of migration stages that moved sets of tools from the distribution to the Tool Shed.
+ View migration stages - See the list of migration stages that moved sets of tools from the distribution to the Tool Shed.
%endif
diff --git a/test/api/test_pages.py b/test/api/test_pages.py
index 4126fa0a46e..8b4a19adc0f 100644
--- a/test/api/test_pages.py
+++ b/test/api/test_pages.py
@@ -97,7 +97,7 @@ class PageApiTestCase(BasePageApiTestCase):
page_response = self._post("pages", page_request)
self._assert_status_code_is(page_response, 400)
self._assert_error_code_is(page_response, error_codes.USER_REQUEST_INVALID_PARAMETER)
- assert "embedded HTML content" in page_response.content
+ assert "embedded HTML content" in page_response.text
def test_show(self):
response_json = self._create_valid_page_with_slug("pagetoshow")
diff --git a/test/api/test_tools_upload.py b/test/api/test_tools_upload.py
index b1ffc6f307a..cd6415c497a 100644
--- a/test/api/test_tools_upload.py
+++ b/test/api/test_tools_upload.py
@@ -12,7 +12,7 @@ from base.populators import (
uses_test_history,
)
-from galaxy.tools.verify.test_data import TestDataResolver
+from galaxy.tool_util.verify.test_data import TestDataResolver
class ToolsUploadTestCase(api.ApiTestCase):
diff --git a/test/base/driver_util.py b/test/base/driver_util.py
index 92587939904..38a9745a50d 100644
--- a/test/base/driver_util.py
+++ b/test/base/driver_util.py
@@ -35,7 +35,7 @@ from galaxy.app import UniverseApplication as GalaxyUniverseApplication
from galaxy.config import LOGGING_CONFIG_DEFAULT
from galaxy.model import mapping
from galaxy.model.tool_shed_install import mapping as toolshed_mapping
-from galaxy.tools.verify.interactor import GalaxyInteractorApi, verify_tool
+from galaxy.tool_util.verify.interactor import GalaxyInteractorApi, verify_tool
from galaxy.util import asbool, download_to_file
from galaxy.util.properties import load_app_properties
from galaxy.web import buildapp
@@ -961,6 +961,11 @@ class GalaxyTestDriver(TestDriver):
galaxy_db_path,
**setup_galaxy_config_kwds
)
+
+ isolate_galaxy_config = getattr(config_object, "isolate_galaxy_config", False)
+ if isolate_galaxy_config:
+ galaxy_config["config_dir"] = tempdir
+
self._saved_galaxy_config = galaxy_config
if galaxy_config is not None:
diff --git a/test/base/integration_util.py b/test/base/integration_util.py
index 24724825829..37a16a33383 100644
--- a/test/base/integration_util.py
+++ b/test/base/integration_util.py
@@ -10,7 +10,7 @@ from unittest import skip, SkipTest, TestCase
import pytest
from galaxy.tool_util.deps.commands import which
-from galaxy.tools.verify.test_data import TestDataResolver
+from galaxy.tool_util.verify.test_data import TestDataResolver
from .api import UsesApiTestCaseMixin
from .driver_util import GalaxyTestDriver
@@ -60,6 +60,10 @@ class IntegrationInstance(UsesApiTestCaseMixin):
# Subclasses can override this to force uwsgi for tests.
require_uwsgi = False
+ # Don't pull in default configs for un-configured things from Galaxy's
+ # config directory and such.
+ isolate_galaxy_config = True
+
@classmethod
def setUpClass(cls):
"""Configure and start Galaxy for a test."""
diff --git a/test/base/interactor.py b/test/base/interactor.py
index 7ccb068cad9..b8166375302 100644
--- a/test/base/interactor.py
+++ b/test/base/interactor.py
@@ -1,4 +1,4 @@
-from galaxy.tools.verify.interactor import GalaxyInteractorApi
+from galaxy.tool_util.verify.interactor import GalaxyInteractorApi
class TestCaseGalaxyInteractor(GalaxyInteractorApi):
diff --git a/test/base/populators.py b/test/base/populators.py
index 0ee8b19d416..46169a4d715 100644
--- a/test/base/populators.py
+++ b/test/base/populators.py
@@ -23,7 +23,7 @@ from gxformat2 import (
from pkg_resources import resource_string
from six import StringIO
-from galaxy.tools.verify.test_data import TestDataResolver
+from galaxy.tool_util.verify.test_data import TestDataResolver
from galaxy.util import unicodify
from . import api_asserts
diff --git a/test/base/testcase.py b/test/base/testcase.py
index c73824250f6..3e063148fc0 100644
--- a/test/base/testcase.py
+++ b/test/base/testcase.py
@@ -5,7 +5,7 @@ import os
import unittest
from galaxy.security import idencoding
-from galaxy.tools.verify.test_data import TestDataResolver
+from galaxy.tool_util.verify.test_data import TestDataResolver
from .driver_util import GalaxyTestDriver, setup_keep_outdir, target_url_parts
log = logging.getLogger(__name__)
diff --git a/test/functional/test_toolbox.py b/test/functional/test_toolbox.py
index 7531e68b4a4..6dd7a3cda58 100644
--- a/test/functional/test_toolbox.py
+++ b/test/functional/test_toolbox.py
@@ -11,8 +11,8 @@ except ImportError:
from base.driver_util import setup_keep_outdir, target_url_parts
from base.instrument import register_job_data
from base.testcase import FunctionalTestCase # noqa: I100,I201,I202
+from galaxy.tool_util.verify.interactor import GalaxyInteractorApi, verify_tool # noqa: I201
from galaxy.tools import DataManagerTool # noqa: I201
-from galaxy.tools.verify.interactor import GalaxyInteractorApi, verify_tool # noqa: I201
log = logging.getLogger(__name__)
diff --git a/test/integration/test_kubernetes_runner.py b/test/integration/test_kubernetes_runner.py
index 6546ac3a20a..2880f8e0e46 100644
--- a/test/integration/test_kubernetes_runner.py
+++ b/test/integration/test_kubernetes_runner.py
@@ -90,6 +90,12 @@ def job_config(jobs_directory):
$k8s_config_path
gx-short-id
+
+ jobs-directory-claim:$jobs_directory,tool-directory-claim:$tool_directory
+ $k8s_config_path
+ gx-short-id
+ 10
+
@@ -99,11 +105,19 @@ def job_config(jobs_directory):
busybox:ubuntu-14.04
42
+
+ 1.9
+ 10M
+ true
+ busybox:ubuntu-14.04
+ 42
+
+
""")
@@ -255,3 +269,19 @@ class BaseKubernetesIntegrationTestCase(BaseJobEnvironmentIntegrationTestCase, M
MEM = '10'
MEM_PER_SLOT = '5'
assert [CPU, MEM, MEM_PER_SLOT] == dataset_content.split('\n'), dataset_content
+
+ @skip_without_tool('create_2')
+ def test_walltime_limit(self):
+ running_response = self.dataset_populator.run_tool(
+ 'create_2',
+ {'sleep_time': 60},
+ self.history_id,
+ assert_ok=False
+ )
+ result = self.dataset_populator.wait_for_tool_run(run_response=running_response,
+ history_id=self.history_id,
+ assert_ok=False).json()
+ details = self.dataset_populator.get_job_details(result['jobs'][0]['id'], full=True).json()
+ assert details['state'] == 'error'
+ hda_details = self.dataset_populator.get_history_dataset_details(self.history_id, assert_ok=False)
+ assert hda_details['misc_info'] == 'Job was active longer than specified deadline'
diff --git a/test/integration/test_pulsar_embedded_copy_working.py b/test/integration/test_pulsar_embedded_copy_working.py
new file mode 100644
index 00000000000..814d0086aa5
--- /dev/null
+++ b/test/integration/test_pulsar_embedded_copy_working.py
@@ -0,0 +1,24 @@
+"""Integration tests for the Pulsar embedded runner with outputs to working directory."""
+
+import os
+
+from base import integration_util
+
+SCRIPT_DIRECTORY = os.path.abspath(os.path.dirname(__file__))
+EMBEDDED_PULSAR_JOB_CONFIG_FILE = os.path.join(SCRIPT_DIRECTORY, "embedded_pulsar_job_conf.yml")
+
+
+class EmbeddedCopyWorkingPulsarIntegrationInstance(integration_util.IntegrationInstance):
+ """Describe a Galaxy test instance with embedded pulsar configured."""
+
+ framework_tool_and_types = True
+
+ @classmethod
+ def handle_galaxy_config_kwds(cls, config):
+ config["job_config_file"] = EMBEDDED_PULSAR_JOB_CONFIG_FILE
+ config["outputs_to_working_directory"] = True
+
+
+instance = integration_util.integration_module_instance(EmbeddedCopyWorkingPulsarIntegrationInstance)
+
+test_tools = integration_util.integration_tool_runner(["output_format"])
diff --git a/test/integration/test_pulsar_embedded_metadata.py b/test/integration/test_pulsar_embedded_metadata.py
index 5fcafe73dd9..66412144021 100644
--- a/test/integration/test_pulsar_embedded_metadata.py
+++ b/test/integration/test_pulsar_embedded_metadata.py
@@ -1,4 +1,4 @@
-"""Integration tests for the Pulsar embedded runner."""
+"""Integration tests for the Pulsar embedded runner with remote metadata."""
import os
@@ -8,7 +8,7 @@ SCRIPT_DIRECTORY = os.path.abspath(os.path.dirname(__file__))
EMBEDDED_PULSAR_JOB_CONFIG_FILE = os.path.join(SCRIPT_DIRECTORY, "embedded_pulsar_metadata_job_conf.yml")
-class EmbeddedPulsarIntegrationInstance(integration_util.IntegrationInstance):
+class EmbeddedMetadataPulsarIntegrationInstance(integration_util.IntegrationInstance):
"""Describe a Galaxy test instance with embedded pulsar configured."""
framework_tool_and_types = True
@@ -18,6 +18,6 @@ class EmbeddedPulsarIntegrationInstance(integration_util.IntegrationInstance):
config["job_config_file"] = EMBEDDED_PULSAR_JOB_CONFIG_FILE
-instance = integration_util.integration_module_instance(EmbeddedPulsarIntegrationInstance)
+instance = integration_util.integration_module_instance(EmbeddedMetadataPulsarIntegrationInstance)
test_tools = integration_util.integration_tool_runner(["simple_constructs"])
diff --git a/test/selenium_tests/framework.py b/test/selenium_tests/framework.py
index 853c2a04ad1..3ad89b820c5 100644
--- a/test/selenium_tests/framework.py
+++ b/test/selenium_tests/framework.py
@@ -24,10 +24,10 @@ from base import populators # noqa: I100,I202
from base.api import UsesApiTestCaseMixin # noqa: I100
from base.driver_util import classproperty, DEFAULT_WEB_HOST, get_ip_address # noqa: I100
from base.testcase import FunctionalTestCase # noqa: I100
-from galaxy_selenium import ( # noqa: I100,I201
+from galaxy.selenium import ( # noqa: I100,I201
driver_factory,
)
-from galaxy_selenium.navigates_galaxy import ( # noqa: I100
+from galaxy.selenium.navigates_galaxy import ( # noqa: I100
NavigatesGalaxy,
retry_during_transitions
)
diff --git a/test/selenium_tests/test_navigates_galaxy.py b/test/selenium_tests/test_navigates_galaxy.py
index 5fa9c3355ff..c7906791ac2 100644
--- a/test/selenium_tests/test_navigates_galaxy.py
+++ b/test/selenium_tests/test_navigates_galaxy.py
@@ -1,8 +1,7 @@
-from galaxy_selenium.navigates_galaxy import (
+from galaxy.selenium.navigates_galaxy import (
exception_indicates_not_clickable,
exception_seems_to_indicate_transition,
)
-
from .framework import (
selenium_test,
SeleniumTestCase,
diff --git a/test/selenium_tests/test_tool_form.py b/test/selenium_tests/test_tool_form.py
index cf2c909a3da..f8aef81abf2 100644
--- a/test/selenium_tests/test_tool_form.py
+++ b/test/selenium_tests/test_tool_form.py
@@ -2,8 +2,8 @@ import json
from base import rules_test_data
from base.populators import flakey, load_data_dict
-from galaxy_selenium.navigates_galaxy import retry_call_during_transitions
+from galaxy.selenium.navigates_galaxy import retry_call_during_transitions
from .framework import (
managed_history,
retry_assertion_during_transitions,
diff --git a/test/unit/test_compression_util.py b/test/unit/test_compression_util.py
index 582190d5def..c35c8f5ce95 100644
--- a/test/unit/test_compression_util.py
+++ b/test/unit/test_compression_util.py
@@ -2,7 +2,12 @@ import shutil
import tempfile
import unittest
-from galaxy.util.compression_utils import CompressedFile
+import six
+
+from galaxy.util.compression_utils import (
+ CompressedFile,
+ get_fileobj_raw
+)
class CompressionUtilTestCase(unittest.TestCase):
@@ -16,6 +21,20 @@ class CompressionUtilTestCase(unittest.TestCase):
self.assert_safety("test-data/safetar_with_symlink.tar", True)
self.assert_safety("test-data/safe_relative_symlink.tar", True)
+ def test_get_fileobj_raw(self):
+ self.assert_format_detected("test-data/4.bed.zip", "zip")
+ self.assert_format_detected(
+ "test-data/4.bed.zip", None, ["bz2", "gzip"]
+ )
+ self.assert_format_detected("test-data/4.bed.gz", "gzip")
+ self.assert_format_detected(
+ "test-data/4.bed.gz", None, ["bz2", "zip"]
+ )
+ self.assert_format_detected("test-data/4.bed.bz2", "bz2")
+ self.assert_format_detected(
+ "test-data/4.bed.bz2", None, ["gzip", "zip"]
+ )
+
def assert_safety(self, path, expected_to_be_safe):
temp_dir = tempfile.mkdtemp()
try:
@@ -26,3 +45,13 @@ class CompressionUtilTestCase(unittest.TestCase):
CompressedFile(path).extract(temp_dir)
finally:
shutil.rmtree(temp_dir, ignore_errors=True)
+
+ def assert_format_detected(self, path, expected_fmt, allowed_fmts=None):
+ for mode in ['r', 'rb', 'rt', 'U']:
+ if 'b' in mode:
+ expected_type = six.binary_type
+ else:
+ expected_type = six.text_type
+ fmt, fh = get_fileobj_raw(path, mode, allowed_fmts)
+ assert fmt == expected_fmt
+ assert isinstance(fh.read(0), expected_type)
diff --git a/test/unit/test_verify.py b/test/unit/test_verify.py
index 8de580cec5b..54a234590ee 100644
--- a/test/unit/test_verify.py
+++ b/test/unit/test_verify.py
@@ -4,7 +4,7 @@ import tempfile
import pytest
-from galaxy.tools.verify import (
+from galaxy.tool_util.verify import (
files_contains,
files_diff,
files_re_match,
diff --git a/test/unit/tool_util/__init__.py b/test/unit/tool_util/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/test/unit/tool_util/sample_data.py b/test/unit/tool_util/sample_data.py
new file mode 120000
index 00000000000..3b4ed484f80
--- /dev/null
+++ b/test/unit/tool_util/sample_data.py
@@ -0,0 +1 @@
+../unittest_utils/sample_data.py
\ No newline at end of file
diff --git a/test/unit/tools/test_conda_resolution.py b/test/unit/tool_util/test_conda_resolution.py
similarity index 100%
rename from test/unit/tools/test_conda_resolution.py
rename to test/unit/tool_util/test_conda_resolution.py
diff --git a/test/unit/tools/test_output_checker.py b/test/unit/tool_util/test_output_checker.py
similarity index 100%
rename from test/unit/tools/test_output_checker.py
rename to test/unit/tool_util/test_output_checker.py
diff --git a/test/unit/tools/test_parsing.py b/test/unit/tool_util/test_parsing.py
similarity index 100%
rename from test/unit/tools/test_parsing.py
rename to test/unit/tool_util/test_parsing.py
diff --git a/test/unit/tools/test_tool_deps.py b/test/unit/tool_util/test_tool_deps.py
similarity index 97%
rename from test/unit/tools/test_tool_deps.py
rename to test/unit/tool_util/test_tool_deps.py
index c28818bd526..1f15d880a0c 100644
--- a/test/unit/tools/test_tool_deps.py
+++ b/test/unit/tool_util/test_tool_deps.py
@@ -3,7 +3,6 @@ import tempfile
from contextlib import contextmanager
from os import (
chmod,
- environ,
makedirs,
stat,
symlink,
@@ -22,6 +21,7 @@ from galaxy.tool_util.deps.resolvers.galaxy_packages import GalaxyPackageDepende
from galaxy.tool_util.deps.resolvers.lmod import LmodDependency, LmodDependencyResolver
from galaxy.tool_util.deps.resolvers.modules import ModuleDependency, ModuleDependencyResolver
from galaxy.util.bunch import Bunch
+from .util import modify_environ
# If true, test created DependencyManager objects by serializing out to json and re-constituting.
ROUND_TRIP_TEST_DEPENDENCY_MANAGER_SERIALIZATION = True
@@ -582,7 +582,7 @@ def test_config_modulepath():
def test_config_MODULEPATH():
# Test reads and splits MODULEPATH if modulepath is not specified.
- with __environ({"MODULEPATH": "/opt/modules/modulefiles:/usr/local/modules/modulefiles"}):
+ with modify_environ({"MODULEPATH": "/opt/modules/modulefiles:/usr/local/modules/modulefiles"}):
with __parse_resolvers('''
@@ -593,7 +593,7 @@ def test_config_MODULEPATH():
def test_config_MODULESHOME():
# Test fallbacks to read MODULESHOME if modulepath is not specified and
# neither is MODULEPATH.
- with __environ({"MODULESHOME": "/opt/modules"}, remove="MODULEPATH"):
+ with modify_environ({"MODULESHOME": "/opt/modules"}, keys_to_remove=["MODULEPATH"]):
with __parse_resolvers('''
@@ -718,28 +718,6 @@ def _first_conda_resolver_options(dm):
return [r for r in dm.to_dict()["resolvers"] if r["resolver_type"] == "conda"][0]
-@contextmanager
-def __environ(values, remove=[]):
- """
- Modify the environment for a test, adding/updating values in dict `values` and
- removing any environment variables mentioned in list `remove`.
- """
- new_keys = set(environ.keys()) - set(values.keys())
- old_environ = environ.copy()
- try:
- environ.update(values)
- for to_remove in remove:
- try:
- del environ[remove]
- except KeyError:
- pass
- yield
- finally:
- environ.update(old_environ)
- for key in new_keys:
- del environ[key]
-
-
@contextmanager
def __parse_resolvers(file_content, extension=".xml"):
with __dependency_manager(file_content, extension=extension) as dm:
diff --git a/test/unit/tools/test_tool_loader.py b/test/unit/tool_util/test_tool_loader.py
similarity index 94%
rename from test/unit/tools/test_tool_loader.py
rename to test/unit/tool_util/test_tool_loader.py
index f07c1e8c2b5..ce644a510ef 100644
--- a/test/unit/tools/test_tool_loader.py
+++ b/test/unit/tool_util/test_tool_loader.py
@@ -1,27 +1,10 @@
import os
from shutil import rmtree
-from string import Template
from tempfile import mkdtemp
from galaxy.tool_util.loader import load_tool, template_macro_params
from galaxy.util import parse_xml
-
-
-SIMPLE_TOOL_WITH_MACRO = """
-
-
- external.xml
-
-"""
-
-SIMPLE_MACRO = Template("""
-
- $tool_version
-
-
-
-
-""")
+from .sample_data import SIMPLE_MACRO, SIMPLE_TOOL_WITH_MACRO
def test_loader():
diff --git a/test/unit/tool_util/test_util.py b/test/unit/tool_util/test_util.py
new file mode 100644
index 00000000000..e2778fbf74e
--- /dev/null
+++ b/test/unit/tool_util/test_util.py
@@ -0,0 +1,86 @@
+from os import environ
+
+import pytest
+
+from .util import modify_environ
+
+
+@pytest.fixture
+def load_keyval(request):
+ """
+ Create key/value pair and load it into os.environ. Delete on teardown.
+ """
+ keys = [] # preserve keys for teardown
+
+ def _load_keyval(key='a unique key', val='a value'):
+ # If this is called twice with default values within the same test function,
+ # it will raise a KeyError. This is intentional: os.environ cannot have duplicate keys.
+ keys.append(key)
+ environ[key] = val
+ return key, val
+
+ def _teardown():
+ for k in keys:
+ del environ[k]
+
+ request.addfinalizer(_teardown)
+ return _load_keyval
+
+
+def test_modify_environ__restore(load_keyval):
+ key, val = load_keyval()
+ with modify_environ({}):
+ assert environ[key] == val # key/val unchanged
+ assert environ[key] == val # key/val unchanged
+
+
+def test_modify_environ__add_and_restore(load_keyval):
+ key1, val1 = load_keyval()
+ key2, val2 = 'key to add', 'value to add'
+ to_update = {key2: val2}
+
+ assert key2 not in environ # ensure key to add does not exist
+ with modify_environ(to_update):
+ assert environ[key1] == val1 # key/val unchanged
+ assert environ[key2] == val2 # new key/val added
+ assert environ[key1] == val1 # key/val unchanged
+ assert key2 not in environ # new key removed
+
+
+def test_modify_environ__update_and_restore(load_keyval):
+ key1, val1 = load_keyval()
+ key2, val2 = load_keyval('key to update', 'value to update')
+ val2_updated = 'updated'
+ to_update = {key2: val2_updated}
+
+ with modify_environ(to_update):
+ assert environ[key1] == val1 # key/val unchanged
+ assert environ[key2] == val2_updated # value updated
+ assert environ[key1] == val1 # key/val unchanged
+ assert environ[key2] == val2 # value restored
+
+
+def test_modify_environ__remove_and_restore(load_keyval):
+ key1, val1 = load_keyval()
+ key2, val2 = load_keyval('key to remove', 'value to remove')
+ to_update = {}
+ to_remove = [key2]
+
+ with modify_environ(to_update, to_remove):
+ assert environ[key1] == val1 # key/val unchanged
+ assert key2 not in environ # key removed
+ assert environ[key1] == val1 # key/val unchanged
+ assert environ[key2] == val2 # key/value restored
+
+
+def test_modify_environ__remove_nonexistant_key(load_keyval):
+ # Test that removing wrong key does not raise an error
+ key1, val1 = load_keyval()
+ key_nonexistant = 'no such key'
+ to_update = {}
+ to_remove = [key_nonexistant]
+
+ assert key_nonexistant not in environ # ensure key to remove does not exist
+ with modify_environ(to_update, to_remove):
+ assert environ[key1] == val1 # key/val unchanged
+ assert environ[key1] == val1 # key/val unchanged
diff --git a/test/unit/tool_util/util.py b/test/unit/tool_util/util.py
new file mode 100644
index 00000000000..2bc0340711c
--- /dev/null
+++ b/test/unit/tool_util/util.py
@@ -0,0 +1,22 @@
+from contextlib import contextmanager
+from os import environ
+
+
+@contextmanager
+def modify_environ(values, keys_to_remove=None):
+ """
+ Modify the environment for a test, adding/updating values in dict `values` and
+ removing any environment variables mentioned in list `keys_to_remove`.
+ """
+ old_environ = environ.copy()
+ try:
+ if values:
+ environ.update(values)
+ if keys_to_remove:
+ for key in keys_to_remove:
+ if key in environ:
+ del environ[key]
+ yield
+ finally:
+ environ.clear()
+ environ.update(old_environ)
diff --git a/test/unit/tools/test_column_parameters.py b/test/unit/tools/test_column_parameters.py
index 19fc9ea4029..4cbb39d131f 100644
--- a/test/unit/tools/test_column_parameters.py
+++ b/test/unit/tools/test_column_parameters.py
@@ -3,7 +3,7 @@ test_select_parameters.py.
"""
from galaxy import model
from galaxy.util import bunch
-from .test_parameter_parsing import BaseParameterTestCase
+from .util import BaseParameterTestCase
from ..tools_support import datatypes_registry
diff --git a/test/unit/tools/test_data_parameters.py b/test/unit/tools/test_data_parameters.py
index 6d18fe3458a..a89425c03b6 100644
--- a/test/unit/tools/test_data_parameters.py
+++ b/test/unit/tools/test_data_parameters.py
@@ -1,5 +1,5 @@
from galaxy import model
-from .test_parameter_parsing import BaseParameterTestCase
+from .util import BaseParameterTestCase
from ..unittest_utils import galaxy_mock
diff --git a/test/unit/tools/test_parameter_parsing.py b/test/unit/tools/test_parameter_parsing.py
index f858ca00e40..bdf9c9de65d 100644
--- a/test/unit/tools/test_parameter_parsing.py
+++ b/test/unit/tools/test_parameter_parsing.py
@@ -1,11 +1,7 @@
from unittest import TestCase
-from xml.etree.ElementTree import XML
-from galaxy import model
-from galaxy.tools.parameters import basic
from galaxy.tools.parameters.meta import process_key
-from galaxy.util import bunch
-from ..tools_support import UsesApp
+from .util import BaseParameterTestCase
class ProcessKeyTestCase(TestCase):
@@ -46,22 +42,6 @@ class ProcessKeyTestCase(TestCase):
self.assertEqual(nested_dict, expected_dict)
-class BaseParameterTestCase(TestCase, UsesApp):
-
- def setUp(self):
- self.setup_app()
- self.mock_tool = bunch.Bunch(
- app=self.app,
- tool_type="default",
- valid_input_states=model.Dataset.valid_input_states,
- )
-
- def _parameter_for(self, **kwds):
- content = kwds["xml"]
- param_xml = XML(content)
- return basic.ToolParameter.build(self.mock_tool, param_xml)
-
-
class ParameterParsingTestCase(BaseParameterTestCase):
""" Test the parsing of XML for most parameter types - in many
ways these are not very good tests since they break the abstraction
diff --git a/test/unit/tools/test_select_parameters.py b/test/unit/tools/test_select_parameters.py
index 28cfe50e33d..f00e64d6f40 100644
--- a/test/unit/tools/test_select_parameters.py
+++ b/test/unit/tools/test_select_parameters.py
@@ -1,7 +1,7 @@
from galaxy import model
from galaxy.tools.parameters import basic
from galaxy.util import bunch
-from .test_parameter_parsing import BaseParameterTestCase
+from .util import BaseParameterTestCase
class SelectToolParameterTestCase(BaseParameterTestCase):
diff --git a/test/unit/tools/test_toolbox.py b/test/unit/tools/test_toolbox.py
index e592f8e43d2..1073b5145cb 100644
--- a/test/unit/tools/test_toolbox.py
+++ b/test/unit/tools/test_toolbox.py
@@ -14,12 +14,9 @@ from galaxy.model import tool_shed_install
from galaxy.model.tool_shed_install import mapping
from galaxy.tools import ToolBox
from galaxy.tools.cache import ToolCache
-from .test_tool_loader import (
- SIMPLE_MACRO,
- SIMPLE_TOOL_WITH_MACRO
-)
from .test_toolbox_filters import mock_trans
from ..tools_support import UsesApp, UsesTools
+from ..unittest_utils.sample_data import SIMPLE_MACRO, SIMPLE_TOOL_WITH_MACRO
log = logging.getLogger(__name__)
diff --git a/test/unit/tools/util.py b/test/unit/tools/util.py
new file mode 100644
index 00000000000..384de1052de
--- /dev/null
+++ b/test/unit/tools/util.py
@@ -0,0 +1,23 @@
+from unittest import TestCase
+from xml.etree.ElementTree import XML
+
+from galaxy import model
+from galaxy.tools.parameters import basic
+from galaxy.util import bunch
+from ..tools_support import UsesApp
+
+
+class BaseParameterTestCase(TestCase, UsesApp):
+
+ def setUp(self):
+ self.setup_app()
+ self.mock_tool = bunch.Bunch(
+ app=self.app,
+ tool_type="default",
+ valid_input_states=model.Dataset.valid_input_states,
+ )
+
+ def _parameter_for(self, **kwds):
+ content = kwds["xml"]
+ param_xml = XML(content)
+ return basic.ToolParameter.build(self.mock_tool, param_xml)
diff --git a/test/unit/unittest_utils/sample_data.py b/test/unit/unittest_utils/sample_data.py
new file mode 100644
index 00000000000..dc0bcb02093
--- /dev/null
+++ b/test/unit/unittest_utils/sample_data.py
@@ -0,0 +1,17 @@
+from string import Template
+
+SIMPLE_TOOL_WITH_MACRO = """
+
+
+ external.xml
+
+"""
+
+SIMPLE_MACRO = Template("""
+
+ $tool_version
+
+
+
+
+""")
diff --git a/tool-data/icn3d_simple_display.loc.sample b/tool-data/icn3d_simple_display.loc.sample
new file mode 100644
index 00000000000..a0d3d91277b
--- /dev/null
+++ b/tool-data/icn3d_simple_display.loc.sample
@@ -0,0 +1,3 @@
+# Table used for listing simple iCn3D Structure Viewer servers
+#
+ncbi_icn3d NCBI https://www.ncbi.nlm.nih.gov/Structure/icn3d/full.html?type=%(icn3d_file_type)s&url=%(icn3d_file_url_qp)s