diff --git a/Code/Mantid/docs/runsphinx.py.in b/Code/Mantid/docs/runsphinx.py.in
index b613a9095fa82d9c297976408cf53117c7dd0cb7..6bffe814996ab2db5749e92cceb60d0c25065366 100644
--- a/Code/Mantid/docs/runsphinx.py.in
+++ b/Code/Mantid/docs/runsphinx.py.in
@@ -2,57 +2,172 @@
    module. This script calls the sphinx entry point with the necessary
    arguments
 """
+from optparse import OptionParser
 import os
+import re
 import sys
 
-#-----------------------------------------------------------------------------------------------
-def pathjoin(left, *args):
+DOC_EXT = ".rst"
+
+###############################################################################
+# CMake-populated variables
+###############################################################################
+BUILDER = "@BUILDER@"
+SRC_DIR = "@SPHINX_SRC_DIR@"
+CONF_DIR = "@SPHINX_CONF_DIR@"
+SPHINX_BUILD_DIR = "@SPHINX_BUILD_DIR@"
+SCREENSHOTS_DIR = "@SCREENSHOTS_DIR@"
+
+###############################################################################
+# Main
+###############################################################################
+
+def main(sysarg):
     """
-    Similar to os.path.join but just uses "/" as it's populated with CMake-style paths that are
-    always "/" separated, even on Windows.
+    Execute the Sphinx build.
+
+    Args:
+      sysarg (list): A list of strings giving arguments to the script,
+                     where it is assumed that the path to the script is the
+                     first argument
     """
-    return left + "/" + "/".join(args)
+    opts, args = parseargs(sysarg)
+    if len(args) > 0:
+        raise RuntimeError("Unexpected command line arguments: %s. "
+                           "Use -h for help" % ' '.join(args))
 
-#-----------------------------------------------------------------------------------------------
+    # Update sys path if we need to
+    update_path(opts.mantidpath)
 
-def main():
-    # Update path to find mantid
-    package_dir = "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@"
-    runtime_config = os.environ.get("RUNTIME_CONFIG", "") # for visual studio and xcode
-    if runtime_config != "":
-        package_dir = pathjoin(package_dir, runtime_config)
-    sys.path.insert(0, package_dir)
-
-    # Update environment with screenshots path
-    screenshots_dir = "@SCREENSHOTS_DIR@"
-    if screenshots_dir != "":
-        os.environ["SCREENSHOTS_DIR"] = screenshots_dir
-
-    # All paths are cmake style so are "/" separated, even on Windows
-    builder = "@BUILDER@"
-    src_dir = "@SPHINX_SRC_DIR@"
-    conf_dir = "@SPHINX_CONF_DIR@"
-    sphinx_build_dir = "@SPHINX_BUILD_DIR@"
-    output_dir = pathjoin(sphinx_build_dir, builder)
-    doctree_dir = pathjoin(sphinx_build_dir, "doctrees")
+    # Find test files
+    testpaths = find_test_files(SRC_DIR, opts.testinclude)
+
+    # Update environment with screenshots path if necessary
+    if SCREENSHOTS_DIR != "":
+        os.environ["SCREENSHOTS_DIR"] = SCREENSHOTS_DIR
 
     # Arguments for main
+    output_dir = pathjoin(SPHINX_BUILD_DIR, BUILDER)
+    doctree_dir = pathjoin(SPHINX_BUILD_DIR, "doctrees")
     argv = [sys.executable,
-            "-b", builder,
+            "-b", BUILDER,
             "-d", doctree_dir,
-            "-c", conf_dir,
-            src_dir, output_dir]
+            "-c", CONF_DIR,
+            SRC_DIR, output_dir]
 
-    # See if we have been told to only process a particular file
-    src_file = os.environ.get("SPHINX_SRC_FILE", None)
-    if src_file is not None:
-        argv.append(src_file)
+    if testpaths is not None:
+        if len(testpaths) > 0:
+            argv.extend(testpaths)
+        else:
+            raise RuntimeError("No tests matched regex '%s'"
+                                % opts.testinclude)
 
     # Run
     import sphinx
     sys.exit(sphinx.main(argv))
 
+#-----------------------------------------------------------------------------------------------
+
+def parseargs(arglist):
+    """
+    Split script arguments into options and arguments.
+
+    Args:
+      arglist: List of strings to control program
+    """
+    parser = OptionParser(usage="Usage: %prog [options]",
+                          conflict_handler='error')
+    parser.add_option("-m", "--mantidpath", dest="mantidpath",
+                      help="Location of mantid package. Has no effect if run inside MantidPlot")
+    parser.add_option("-R", "--tests-regex", dest="testinclude",
+                      help="Regex specifying which tests to run. It is matched against the "
+                      "filename when considering whether to run a test.")
+    return parser.parse_args(arglist[1:]) # hack off filename
+
+#-----------------------------------------------------------------------------------------------
+
+def update_path(mantidpath):
+    """
+    If not inside MantidPlot (current check is whether we can import _qti)
+    then insert given path as first directory in sys.path
+
+    Args:
+      mantidpath (str): A string giving the location of the mantid module
+    """
+    try:
+        import _qti
+        gui = True
+    except ImportError:
+        gui = False
+
+    # If it's MantidPlot then we already know what our paths should be so ignore it
+    if gui:
+        return
+
+    # check for directory
+    if not os.path.isdir(os.path.join(mantidpath, "mantid")):
+        raise ValueError("Unable to find mantid package in '%s'" % mantidpath)
+    # is package valid
+    if not os.path.isfile(os.path.join(mantidpath, "mantid", "__init__.py")):
+        raise ValueError("Invalid mantid package. No __init__ found in '%s' %s")
+
+    # Update sys.path
+    sys.path.insert(0, mantidpath)
+
+#-----------------------------------------------------------------------------------------------
+
+def find_test_files(src_dir, name_re):
+    """
+    Find the test files that should be run based on a source directory
+    and regex.
+
+    Args:
+      src_dir (str): A string giving the source directory of doc files
+      name_re (str): A regex to match against a test filename.
+    Returns:
+      A list of paths to the chosen test files.
+    """
+    name_re_comp = re.compile(name_re)
+    testpaths = []
+    for dirpath, dirnames, filenames in os.walk(src_dir):
+        testfiles = find_matching_tests(filenames, name_re_comp)
+        # Join each filename with the current path and extend the list
+        testpaths.extend(map(lambda x: os.path.join(dirpath, x), testfiles))
+
+    return testpaths
+
+def find_matching_tests(filenames, name_re):
+    """
+    For a list of filenames, return the list that matches the given
+    regex
+
+    Args:
+      filenames: A list of filenames
+      name_re (re.regex): A compiled regex object
+    Returns:
+      A list of matching test names
+    """
+    testfiles = []
+    for filename in filenames:
+        if not filename.endswith(DOC_EXT):
+            continue
+        if name_re.match(filename.rstrip(DOC_EXT)):
+            testfiles.append(filename)
+
+    return testfiles
+
+#-----------------------------------------------------------------------------------------------
+def pathjoin(left, *args):
+    """
+    Similar to os.path.join but just uses "/" as it's populated with CMake-style paths that are
+    always "/" separated, even on Windows.
+    """
+    return left + "/" + "/".join(args)
+
+#-----------------------------------------------------------------------------------------------
+
+
 ##################################################################################
 
 if __name__ == "__main__":
-    main()
+    main(sys.argv)