diff --git a/.travis.yml b/.travis.yml
index c13fc1db18a7f72ac49937ea8ae9693a956713e1..11d0d8315bb960f4ca26b02a52f0364a6f01f0e4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -44,5 +44,4 @@ script:
   # download data and models, then run tests
   - mhcflurry-downloads fetch data_curated models_class1 models_class1_pan allele_sequences
   - mhcflurry-downloads info  # just to test this command works
-  #- travis_wait 30 nosetests --with-timer -sv
-  - bash -c 'for i in $(ls test/test_*.py) ; do echo "Invoking test: $i" ; nosetests -sv $i ; done'
+  - nosetests --with-timer -sv test
diff --git a/mhcflurry/testing_utils.py b/mhcflurry/testing_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..862369c615cfa480f2138ea534de1be378f82517
--- /dev/null
+++ b/mhcflurry/testing_utils.py
@@ -0,0 +1,5 @@
+
+
+def module_cleanup():
+    import keras.backend as K
+    K.clear_session()
diff --git a/test/test_calibrate_percentile_ranks_command.py b/test/test_calibrate_percentile_ranks_command.py
index 2a891cb49d621381f86088c96db23ff50f913016..4c97e80c04e5d47c6b3ff9872bce5c32d015f602 100644
--- a/test/test_calibrate_percentile_ranks_command.py
+++ b/test/test_calibrate_percentile_ranks_command.py
@@ -14,6 +14,9 @@ from mhcflurry.downloads import get_path
 
 os.environ["CUDA_VISIBLE_DEVICES"] = ""
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 
 def run_and_check(n_jobs=0, delete=True, additional_args=[]):
     source_models_dir = get_path("models_class1_pan", "models.with_mass_spec")
diff --git a/test/test_changing_allele_representations.py b/test/test_changing_allele_representations.py
index 84492fad51b2b1dca59d0ddc81a5e80efb68f15d..7c70048d0ed9ab6924cd184ac554a31a91cdae1f 100644
--- a/test/test_changing_allele_representations.py
+++ b/test/test_changing_allele_representations.py
@@ -8,6 +8,9 @@ from mhcflurry.downloads import get_path
 
 from numpy.testing import assert_equal
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 ALLELE_TO_SEQUENCE = pandas.read_csv(
     get_path(
         "allele_sequences", "allele_sequences.csv"),
diff --git a/test/test_class1_affinity_predictor.py b/test/test_class1_affinity_predictor.py
index 024d4a6a9c3babf3ff65d8241d889952ad8ae697..277e78cb95ee761fe30c7c8d2d6e9f3a10252e1e 100644
--- a/test/test_class1_affinity_predictor.py
+++ b/test/test_class1_affinity_predictor.py
@@ -16,6 +16,10 @@ from numpy import testing
 
 from mhcflurry.downloads import get_path
 
+import mhcflurry.testing_utils
+teardown = mhcflurry.testing_utils.module_cleanup
+
+
 DOWNLOADED_PREDICTOR = Class1AffinityPredictor.load()
 
 logging.basicConfig(level=logging.DEBUG)
@@ -252,3 +256,4 @@ def test_predict_implementations_equivalent():
                 peptides=peptides,
                 centrality_measure=centrality_measure).prediction.values
             testing.assert_almost_equal(pred1, pred2, decimal=2)
+
diff --git a/test/test_class1_neural_network.py b/test/test_class1_neural_network.py
index 8baaded0a02d88d43d6e77ad7551a687adc3528f..e614d602b576d4c4a9ecbeec14029eea8bcc1195 100644
--- a/test/test_class1_neural_network.py
+++ b/test/test_class1_neural_network.py
@@ -13,6 +13,9 @@ from mhcflurry.class1_neural_network import Class1NeuralNetwork
 from mhcflurry.downloads import get_path
 from mhcflurry.common import random_peptides
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 
 def test_class1_neural_network_a0205_training_accuracy():
     # Memorize the dataset.
diff --git a/test/test_class1_pan.py b/test/test_class1_pan.py
index 76a7a9297ddea20784a0953efd004654ded14deb..cdb483cf17260d93a59ba9ad940727393f9785bd 100644
--- a/test/test_class1_pan.py
+++ b/test/test_class1_pan.py
@@ -11,6 +11,9 @@ from mhcflurry import Class1AffinityPredictor,Class1NeuralNetwork
 from mhcflurry.allele_encoding import AlleleEncoding
 from mhcflurry.downloads import get_path
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 
 HYPERPARAMETERS = {
     'activation': 'tanh',
diff --git a/test/test_custom_loss.py b/test/test_custom_loss.py
index 55bfa7b523dd3d61f9a4619481cda579504ec268..4c177666f378284ed99960224cd8376a297ed387 100644
--- a/test/test_custom_loss.py
+++ b/test/test_custom_loss.py
@@ -11,6 +11,9 @@ import keras.backend as K
 
 from mhcflurry.custom_loss import CUSTOM_LOSSES
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 
 def evaluate_loss(loss, y_true, y_pred):
     y_true = numpy.array(y_true)
diff --git a/test/test_download_models_class1.py b/test/test_download_models_class1.py
index be36e44fec6a8d6a5ba97a84a2543a2c12d21bd0..23b25c3dff10344eb8804dc0eb74784a4cadfdb9 100644
--- a/test/test_download_models_class1.py
+++ b/test/test_download_models_class1.py
@@ -5,6 +5,9 @@ from numpy.testing import assert_equal
 
 from mhcflurry import Class1AffinityPredictor, Class1NeuralNetwork
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 
 DOWNLOADED_PREDICTOR = Class1AffinityPredictor.load()
 
diff --git a/test/test_multi_output.py b/test/test_multi_output.py
index 2e1261549127bc4598049beb9d4015a175e0182b..efbcccf0f9331239219133018e9043a548c2038f 100644
--- a/test/test_multi_output.py
+++ b/test/test_multi_output.py
@@ -12,6 +12,9 @@ logging.getLogger('tensorflow').disabled = True
 from mhcflurry.class1_neural_network import Class1NeuralNetwork
 from mhcflurry.common import random_peptides
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 
 def test_multi_output():
     hyperparameters = dict(
diff --git a/test/test_network_merging.py b/test/test_network_merging.py
index 6021652baf64dbe5c1c9d881e7ce51682cf3f93b..a180df49670460e370b7f067908c80aec3548ee8 100644
--- a/test/test_network_merging.py
+++ b/test/test_network_merging.py
@@ -5,6 +5,9 @@ from mhcflurry import Class1AffinityPredictor, Class1NeuralNetwork
 from mhcflurry.common import random_peptides
 from mhcflurry.downloads import get_path
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 logging.getLogger('tensorflow').disabled = True
 
 PAN_ALLELE_PREDICTOR = Class1AffinityPredictor.load(
diff --git a/test/test_predict_command.py b/test/test_predict_command.py
index b85e7202284a34eca31743c635577e3bd3b17cae..7d4d93406ae72715e6ac56e473c4178fb19f4a89 100644
--- a/test/test_predict_command.py
+++ b/test/test_predict_command.py
@@ -6,6 +6,9 @@ from numpy.testing import assert_equal
 
 from mhcflurry import predict_command
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 TEST_CSV = '''
 Allele,Peptide,Experiment
 HLA-A0201,SYNFEKKL,17
diff --git a/test/test_released_predictors_on_hpv_dataset.py b/test/test_released_predictors_on_hpv_dataset.py
index 525f06c201201f75d87abcdf100326cb9c9d5809..10f0fc23f6ccf945c1c5c42d1b7dd97b648ea693 100644
--- a/test/test_released_predictors_on_hpv_dataset.py
+++ b/test/test_released_predictors_on_hpv_dataset.py
@@ -13,6 +13,9 @@ from nose.tools import eq_, assert_less, assert_greater, assert_almost_equal
 from mhcflurry import Class1AffinityPredictor
 from mhcflurry.downloads import get_path
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 
 def data_path(name):
     '''
diff --git a/test/test_released_predictors_well_correlated.py b/test/test_released_predictors_well_correlated.py
index 395a6e80b54c699c664d5b5ddbb9ff5990743648..6b8a6a7e2b71818b4e7a50ec9ea49d4e764f52b9 100644
--- a/test/test_released_predictors_well_correlated.py
+++ b/test/test_released_predictors_well_correlated.py
@@ -15,6 +15,9 @@ from mhcflurry.encodable_sequences import EncodableSequences
 from mhcflurry.downloads import get_path
 from mhcflurry.common import random_peptides
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 
 PREDICTORS = {
     'allele-specific': Class1AffinityPredictor.load(
diff --git a/test/test_speed.py b/test/test_speed.py
index e9c342a6b3ca50b78caca4bbcde2fe7d3fbef441..b35327fea2ca8e92dfc7486102e65cdd00ee74fc 100644
--- a/test/test_speed.py
+++ b/test/test_speed.py
@@ -18,6 +18,9 @@ from mhcflurry.encodable_sequences import EncodableSequences
 from mhcflurry.common import random_peptides
 from mhcflurry.downloads import get_path
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 ALLELE_SPECIFIC_PREDICTOR = Class1AffinityPredictor.load(
     get_path("models_class1", "models"))
 
diff --git a/test/test_train_and_related_commands.py b/test/test_train_and_related_commands.py
index f6abfd2630108274beb8a2529a94a3bb98fb21fb..09ae60e569b9423fc92dc995777f23e8ffa5fde1 100644
--- a/test/test_train_and_related_commands.py
+++ b/test/test_train_and_related_commands.py
@@ -14,6 +14,9 @@ from numpy.testing import assert_array_less, assert_equal
 from mhcflurry import Class1AffinityPredictor
 from mhcflurry.downloads import get_path
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 os.environ["CUDA_VISIBLE_DEVICES"] = ""
 
 HYPERPARAMETERS = [
diff --git a/test/test_train_pan_allele_models_command.py b/test/test_train_pan_allele_models_command.py
index ea5261ec65d8c2f480956fb847dd5890e1d1a5a8..dd69e81053420e35a4588dfa848a8ef87190ab14 100644
--- a/test/test_train_pan_allele_models_command.py
+++ b/test/test_train_pan_allele_models_command.py
@@ -15,6 +15,9 @@ from numpy.testing import assert_equal, assert_array_less
 from mhcflurry import Class1AffinityPredictor,Class1NeuralNetwork
 from mhcflurry.downloads import get_path
 
+from mhcflurry.testing_utils import module_cleanup
+teardown = module_cleanup
+
 os.environ["CUDA_VISIBLE_DEVICES"] = ""