def METHOD_NAME(test_timeout=None):
    """Create a decorator that will run the decorated method in a thread via
    `_ThreadedTestWrapper` and return the value that is returned by the
    given function, unless it exits with exception or times out, in which
    case AssertionError will be raised
    :param int | float | None test_timeout: maximum number of seconds to wait
        for test to complete. If None, `DEFAULT_TEST_TIMEOUT` will be used.
        NOTE: we handle default this way to facilitate patching of the timeout
        in our self-tests.
    :return: decorator
    """
    def run_in_thread_with_timeout_decorator(fun):
        """Create a wrapper that will run the decorated method in a thread via
        `_ThreadedTestWrapper` and return the value that is returned by the
        given function, unless it exits with exception or times out, in which
        case AssertionError will be raised
        :param fun: function to run in thread
        :return: wrapper function
        """
        @functools.wraps(fun)
        def run_in_thread_with_timeout_wrapper(*args, **kwargs):
            """
            :param args: positional args to pass to wrapped function
            :param kwargs: keyword args to pass to wrapped function
            :return: value returned by the function, unless it exits with
                exception or times out
            :raises AssertionError: if wrapped function exits with exception or
                times out
            """
            runner = _ThreadedTestWrapper(
                functools.partial(fun, *args, **kwargs),
                test_timeout)
            return runner.kick_off()
        return run_in_thread_with_timeout_wrapper
    return run_in_thread_with_timeout_decorator