diff --git a/setup.cfg b/setup.cfg
index 989b6fc378d37625ab788c27b6e5b6613bf880a1..591cd65648df855238f8e4ee50a08c20888b1fd7 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,8 +5,17 @@ test=pytest
 universal=1
 
 [tool:pytest]
+# Available test markers:
+#   - fsltest:   Requires FSL
+#   - wxtest:    Requires wxPython
+#   - dicomtest: Requires dcm2niix
+#   - meshtest:  Requires trimesh and rtree
+#   - igziptest: Requires indexed_gzip
+#   - longtest:  Takes a long time
+#
+
 testpaths = tests
-addopts   = -v --niters=50 --cov=fsl
+addopts   = -v --niters=50 --cov=fsl -m "not longtest"
 
 [flake8]
 ignore = E127,E201,E203,E221,E222,E241,E271,E272,E301,E302,E303,E701
\ No newline at end of file
diff --git a/tests/test_atlases.py b/tests/test_atlases.py
index b20b06602878c0467326cf54d8e450a6f3cf6afb..9853c5a73a2b6d73cede0606638906f9f817a40d 100644
--- a/tests/test_atlases.py
+++ b/tests/test_atlases.py
@@ -11,7 +11,6 @@
 
 import              os
 import os.path   as op
-import itertools as it
 import numpy     as np
 
 import mock
@@ -26,6 +25,9 @@ import fsl.data.image      as fslimage
 datadir = op.join(op.dirname(__file__), 'testdata')
 
 
+pytestmark = pytest.mark.fsltest
+
+
 def setup_module():
     if os.environ.get('FSLDIR', None) is None:
         raise Exception('FSLDIR is not set - atlas tests cannot be run')
diff --git a/tests/test_atlases_query.py b/tests/test_atlases_query.py
index 1bdb28a7ada825558f03a218bbf041402010e763..d512f400f92aad64a750f3c90ddcb9992bb0e184 100644
--- a/tests/test_atlases_query.py
+++ b/tests/test_atlases_query.py
@@ -7,7 +7,6 @@
 
 import                    os
 import itertools       as it
-from   collections import defaultdict
 import numpy           as np
 import                    pytest
 
@@ -20,6 +19,9 @@ import fsl.utils.cache     as cache
 from . import (testdir, make_random_mask)
 
 
+pytestmark = pytest.mark.fsltest
+
+
 def setup_module():
     if os.environ.get('FSLDIR', None) is None:
         raise Exception('FSLDIR is not set - atlas tests cannot be run')
diff --git a/tests/test_atlasq_list_summary.py b/tests/test_atlasq_list_summary.py
index 7eba70fe1d8fa4f03d1fb1e44539230f5e4a10f9..310ef9212af987dd96f81b6340a9c8307d7031fa 100644
--- a/tests/test_atlasq_list_summary.py
+++ b/tests/test_atlasq_list_summary.py
@@ -8,12 +8,17 @@
 import              os
 import itertools as it
 
+import              pytest
+
 import fsl.data.atlases   as fslatlases
 import fsl.scripts.atlasq as fslatlasq
 
 from . import CaptureStdout
 
 
+pytestmark = pytest.mark.fsltest
+
+
 def setup_module():
     if os.environ.get('FSLDIR', None) is None:
         raise Exception('FSLDIR is not set - atlas tests cannot be run')
diff --git a/tests/test_atlasq_ohi.py b/tests/test_atlasq_ohi.py
index 2204b08f5e525470d65f4c167bdcff1d91ec03fe..0f36eb20c9567d0ff4215b65a5e8f1e67e68e02a 100644
--- a/tests/test_atlasq_ohi.py
+++ b/tests/test_atlasq_ohi.py
@@ -11,6 +11,8 @@ import os.path as op
 import            os
 import            shlex
 
+import            pytest
+
 import numpy as np
 
 import fsl.scripts.atlasq as fslatlasq
@@ -21,6 +23,9 @@ from . import (tempdir,
                CaptureStdout)
 
 
+pytestmark = pytest.mark.fsltest
+
+
 def setup_module():
     if os.environ.get('FSLDIR', None) is None:
         raise Exception('FSLDIR is not set - atlas tests cannot be run')
diff --git a/tests/test_atlasq_query.py b/tests/test_atlasq_query.py
index 1fb887a1a32e69a093f8d6d0c1f97aede29b69cc..427815405e810f9ba04d9250f1e72410574794c7 100644
--- a/tests/test_atlasq_query.py
+++ b/tests/test_atlasq_query.py
@@ -10,10 +10,11 @@ import                  os
 import os.path       as op
 import                  re
 import itertools     as it
-import                  six
 import numpy         as np
 import scipy.ndimage as ndi
 
+import                  pytest
+
 import fsl.utils.transform as transform
 import fsl.data.atlases    as fslatlases
 import fsl.data.image      as fslimage
@@ -24,6 +25,9 @@ from . import (tempdir,
                CaptureStdout)
 
 
+pytestmark = pytest.mark.fsltest
+
+
 def setup_module():
     if os.environ.get('FSLDIR', None) is None:
         raise Exception('FSLDIR is not set - atlas tests cannot be run')
diff --git a/tests/test_callfsl.py b/tests/test_callfsl.py
index 85176b2124e565a0ad13df3131ce75cd535eb55f..25c156f8783aa8e5dca554af7d0454a3d58a0ca7 100644
--- a/tests/test_callfsl.py
+++ b/tests/test_callfsl.py
@@ -20,6 +20,10 @@ from   fsl.utils.platform import platform as fslplatform
 
 import tests
 
+
+pytestmark = pytest.mark.fsltest
+
+
 def setup_module():
     fsldir = os.environ.get('FSLDIR', None)
     if fsldir is None or not op.exists(fsldir):
diff --git a/tests/test_dicom.py b/tests/test_dicom.py
index a728c0b46db32ec39f2cb9bada40dc5fd8a05cac..325a15b4a8cc94b172998e8712a4d87318a8b100 100644
--- a/tests/test_dicom.py
+++ b/tests/test_dicom.py
@@ -18,6 +18,9 @@ import fsl.utils.tempdir as tempdir
 datadir = op.join(op.dirname(__file__), 'testdata')
 
 
+pytestmark = pytest.mark.dicomtest
+
+
 def setup_module():
 
     if not fsldcm.enabled():
diff --git a/tests/test_idle.py b/tests/test_idle.py
index 96bc3c022178db32fa3ef1459ef952735b7444d1..18b2c4420efb5d9780fb87295dbcb452be1da456 100644
--- a/tests/test_idle.py
+++ b/tests/test_idle.py
@@ -18,6 +18,7 @@ import mock
 import fsl.utils.idle as idle
 from fsl.utils.platform import platform as fslplatform
 
+
 def _run_with_wx(func, *args, **kwargs):
 
     gc.collect()
@@ -91,6 +92,7 @@ def _wait_for_idle_loop_to_clear():
             wx.Yield()
 
 
+@pytest.mark.wxtest
 def  test_run_with_gui():    _run_with_wx(   _test_run)
 def  test_run_without_gui(): _run_without_wx(_test_run)
 def _test_run():
@@ -143,7 +145,7 @@ def _test_run():
     assert     onErrorCalled[ 0]
 
 
-
+@pytest.mark.wxtest
 def test_idleTimeout_with_gui():    _run_with_wx(   _test_idleTimeout)
 def test_idleTimeout_without_gui(): _run_without_wx(_test_idleTimeout)
 def _test_idleTimeout():
@@ -155,6 +157,7 @@ def _test_idleTimeout():
     assert idle.getIdleTimeout() == default
 
 
+@pytest.mark.wxtest
 def test_idle():
 
     called = [False]
@@ -185,6 +188,7 @@ def test_idle():
     _run_with_wx(idle.idle, errtask, 1, kwarg1=2)
 
 
+@pytest.mark.wxtest
 def test_inidle():
 
     called = [False]
@@ -203,6 +207,7 @@ def test_inidle():
     assert called[0]
 
 
+@pytest.mark.wxtest
 def test_cancelidle():
 
     called = [False]
@@ -221,6 +226,7 @@ def test_cancelidle():
     assert not called[0]
 
 
+@pytest.mark.wxtest
 def test_idle_skipIfQueued():
 
     task1called = [False]
@@ -244,6 +250,7 @@ def test_idle_skipIfQueued():
     assert not task2called[0]
 
 
+@pytest.mark.wxtest
 def test_idle_dropIfQueued():
 
     task1called = [False]
@@ -278,6 +285,7 @@ def test_idle_dropIfQueued():
     assert     task2called[0]
 
 
+@pytest.mark.wxtest
 def test_idle_alwaysQueue1():
 
     # Test scheduling the task before
@@ -304,6 +312,7 @@ def test_idle_alwaysQueue1():
     assert called[0]
 
 
+@pytest.mark.wxtest
 def test_idle_alwaysQueue2():
 
     # Test scheduling the task
@@ -323,6 +332,7 @@ def test_idle_alwaysQueue2():
     assert called[0]
 
 
+@pytest.mark.wxtest
 def test_idle_alwaysQueue3():
 
     # Test scheduling the task
@@ -343,6 +353,7 @@ def test_idle_alwaysQueue3():
     assert called[0]
 
 
+@pytest.mark.wxtest
 def test_idle_alwaysQueue4():
 
     # Test scheduling the task when
@@ -370,6 +381,7 @@ def test_idle_alwaysQueue4():
     assert called[0]
 
 
+@pytest.mark.wxtest
 def test_idle_timeout():
 
     called = [False]
@@ -382,7 +394,7 @@ def test_idle_timeout():
     assert not called[0]
 
 
-
+@pytest.mark.wxtest
 def test_idleWhen():
 
     called      = [False]
@@ -403,6 +415,7 @@ def test_idleWhen():
     assert timesPolled[0] == 50
 
 
+@pytest.mark.wxtest
 def  test_wait_with_gui(): _run_with_wx(_test_wait, finishingDelay=1100)
 def  test_wait_without_gui(): _test_wait()
 def _test_wait():
diff --git a/tests/test_image_advanced.py b/tests/test_image_advanced.py
index a05f5d521995363df77012ed85cdc02c5f217198..69756278781902081f2b8c3250d7eb6d40319a96 100644
--- a/tests/test_image_advanced.py
+++ b/tests/test_image_advanced.py
@@ -9,6 +9,7 @@ import os.path as op
 import            time
 
 import mock
+import pytest
 
 import numpy   as np
 import nibabel as nib
@@ -22,15 +23,22 @@ from . import make_random_image
 
 # make sure Image(indexed=True) works
 # even if indexed_gzip is not present
+@pytest.mark.longtest
 def test_image_indexed_no_igzip_threaded():
     with mock.patch.dict('sys.modules', indexed_gzip=None):
         _test_image_indexed(True)
 
+@pytest.mark.longtest
 def test_image_indexed_no_igzip_unthreaded():
     with mock.patch.dict('sys.modules', indexed_gzip=None):
         _test_image_indexed(False)
 
+
+@pytest.mark.longtest
+@pytest.mark.igziptest
 def test_image_indexed_threaded(  ): _test_image_indexed(True)
+@pytest.mark.longtest
+@pytest.mark.igziptest
 def test_image_indexed_unthreaded(): _test_image_indexed(False)
 def _test_image_indexed(threaded):
 
@@ -74,8 +82,12 @@ def _test_image_indexed(threaded):
         assert (end1 - start1) > (end2 - start2)
 
 
+@pytest.mark.longtest
+@pytest.mark.igziptest
 def test_image_indexed_read4D_threaded(seed):
     _test_image_indexed_read4D(True)
+@pytest.mark.longtest
+@pytest.mark.igziptest
 def test_image_indexed_read4D_unthreaded(seed):
     _test_image_indexed_read4D(False)
 def _test_image_indexed_read4D(threaded):
@@ -115,7 +127,11 @@ def _test_image_indexed_read4D(threaded):
             assert np.all(data == np.arange(nvols))
 
 
+@pytest.mark.igziptest
+@pytest.mark.longtest
 def test_image_indexed_save_threaded(  ): _test_image_indexed_save(True)
+@pytest.mark.longtest
+@pytest.mark.igziptest
 def test_image_indexed_save_unthreaded(): _test_image_indexed_save(False)
 def _test_image_indexed_save(threaded):
 
@@ -186,7 +202,11 @@ def _test_image_indexed_save(threaded):
         assert np.all(img[..., 40] == 45)
 
 
+@pytest.mark.longtest
+@pytest.mark.igziptest
 def test_image_no_calcRange_threaded():   _test_image_no_calcRange(True)
+@pytest.mark.longtest
+@pytest.mark.igziptest
 def test_image_no_calcRange_unthreaded(): _test_image_no_calcRange(False)
 def _test_image_no_calcRange(threaded):
 
@@ -217,7 +237,11 @@ def _test_image_no_calcRange(threaded):
         assert img.dataRange == (0, i)
 
 
+@pytest.mark.longtest
+@pytest.mark.igziptest
 def test_image_calcRange_threaded():   _test_image_calcRange(True)
+@pytest.mark.longtest
+@pytest.mark.igziptest
 def test_image_calcRange_unthreaded(): _test_image_calcRange(False)
 def _test_image_calcRange(threaded):
 
diff --git a/tests/test_imagewrapper.py b/tests/test_imagewrapper.py
index 3c89d435042896527d603ff1f1714bb42ecd68c2..c481ada3158b475846ba7bd17d57a4f91abf2297 100644
--- a/tests/test_imagewrapper.py
+++ b/tests/test_imagewrapper.py
@@ -13,6 +13,7 @@ import              time
 import itertools as it
 import numpy     as np
 import nibabel   as nib
+import              pytest
 
 
 import fsl.data.image        as image
@@ -566,12 +567,16 @@ def _ImageWraper_busy_wait(wrapper, v=0):
     if tt is not None:
         tt.waitUntilIdle()
 
+@pytest.mark.longtest
 def test_ImageWrapper_read_threaded(niters, seed):
     _test_ImageWrapper_read(niters, seed, True)
+@pytest.mark.longtest
 def test_ImageWrapper_read_unthreaded(niters, seed):
     _test_ImageWrapper_read(niters, seed, False)
+@pytest.mark.longtest
 def test_ImageWrapper_read_nans_threaded(niters, seed):
     _test_ImageWrapper_read(niters, seed, True, True)
+@pytest.mark.longtest
 def test_ImageWrapper_read_nans_unthreaded(niters, seed):
     _test_ImageWrapper_read(niters, seed, False, True)
 
@@ -658,9 +663,10 @@ def _test_ImageWrapper_read(niters, seed, threaded, addnans=False):
                 else:             assert     wrapper.covered
 
 
-
+@pytest.mark.longtest
 def test_ImageWrapper_write_out_threaded(niters, seed):
     _test_ImageWrapper_write_out(niters, seed, True)
+@pytest.mark.longtest
 def test_ImageWrapper_write_out_unthreaded(niters, seed):
     _test_ImageWrapper_write_out(niters, seed, False)
 def _test_ImageWrapper_write_out(niters, seed, threaded):
@@ -799,8 +805,10 @@ def _test_ImageWrapper_write_out(niters, seed, threaded):
             # print('--------------')
 
 
+@pytest.mark.longtest
 def test_ImageWrapper_write_in_overlap_threaded(niters, seed):
     _test_ImageWrapper_write_in_overlap(niters, seed, True)
+@pytest.mark.longtest
 def test_ImageWrapper_write_in_overlap_unthreaded(niters, seed):
     _test_ImageWrapper_write_in_overlap(niters, seed, False)
 def _test_ImageWrapper_write_in_overlap(niters, seed, threaded):
@@ -910,8 +918,10 @@ def _test_ImageWrapper_write_in_overlap(niters, seed, threaded):
                 assert np.isclose(newHi, expHi)
 
 
+@pytest.mark.longtest
 def test_ImageWrapper_write_different_volume_threaded(niters, seed):
     _test_ImageWrapper_write_different_volume(niters, seed, True)
+@pytest.mark.longtest
 def test_ImageWrapper_write_different_volume_unthreaded(niters, seed):
     _test_ImageWrapper_write_different_volume(niters, seed, False)
 def _test_ImageWrapper_write_different_volume(niters, seed, threaded):
diff --git a/tests/test_mesh.py b/tests/test_mesh.py
index 5dca80f2140c6f48540caa09a3e529cccf4d119a..97f2c9b2f3eb63b02a2c06fec81c508e53f5e713 100644
--- a/tests/test_mesh.py
+++ b/tests/test_mesh.py
@@ -279,6 +279,7 @@ def test_trimesh_no_trimesh():
             assert faces.size == 0
 
 
+@pytest.mark.meshtest
 def test_trimesh():
 
     import trimesh
@@ -290,6 +291,7 @@ def test_trimesh():
     assert isinstance(mesh.trimesh, trimesh.Trimesh)
 
 
+@pytest.mark.meshtest
 def test_rayIntersection():
 
     verts     = np.array(CUBE_VERTICES)
@@ -318,6 +320,7 @@ def test_rayIntersection():
     assert tri.size == 0
 
 
+@pytest.mark.meshtest
 def test_nearestVertex():
 
     verts     = np.array(CUBE_VERTICES)
@@ -331,6 +334,7 @@ def test_nearestVertex():
     assert np.all(np.isclose(ndists, np.sqrt(3)))
 
 
+@pytest.mark.meshtest
 def test_planeIntersection():
 
     verts     = np.array(CUBE_VERTICES)
diff --git a/tests/test_platform.py b/tests/test_platform.py
index addddbc24cffce0df8a6ca566fa2420dfd7e0347..6088009ef09628523e62157e05f47806517ea807 100644
--- a/tests/test_platform.py
+++ b/tests/test_platform.py
@@ -11,6 +11,7 @@ import os.path as op
 import            sys
 import            shutil
 import            tempfile
+import            pytest
 
 import mock
 
@@ -35,6 +36,7 @@ def test_atts():
     p.glIsSoftwareRenderer
 
 
+@pytest.mark.wxtest
 def test_haveGui():
 
     import wx
@@ -207,6 +209,7 @@ def test_detect_ssh():
         assert not p.inVNCSession
 
 
+@pytest.mark.wxtest
 def test_IsWidgetAlive():
 
     import wx