def testing_job(progress_steps=None, retval=None, fail=False, skip=False, log_messages=None, step_duration=0):
    '\n    Job used for testing purposes.\n\n    :param progress_steps:\n        A list of tuples: ``(<group_name>, <steps>)``, where "group_name"\n        is a tuple of name "levels", "steps" an integer representing how\n        many steps should that level have.\n\n        Progress reports will be sent in randomized order.\n\n    :param retval:\n        The return value for the job.\n\n    :param fail:\n        Whether this job should fail.\n\n    :param skip:\n        Whether this job should be skipped.\n\n    :param log_messages:\n        A list of tuples: ``(level, message)``\n\n    :param step_duration:\n        The time to sleep between steps, in milliseconds.\n    '
    from jobcontrol.globals import execution_context
    logger = logging.getLogger('jobcontrol.utils.testing_job')
    log_messages = list((log_messages or []))
    if (progress_steps is None):
        progress_steps = [(None, 10)]
    totals = {}
    counters = {}
    progress_report_items = []
    for (name, steps) in progress_steps:
        if isinstance(name, list):
            name = tuple(name)
        if (not ((name is None) or isinstance(name, tuple))):
            raise TypeError('Name must be a tuple or None')
        for i in xrange(steps):
            progress_report_items.append(name)
        totals[name] = steps
        counters[name] = 0
    random.shuffle(progress_report_items)
    sleep_time = ((step_duration * 1.0) / 1000)

    def report_progress(name, cur, tot, status=None):
        app = execution_context.current_app
        app.report_progress(group_name=name, current=cur, total=tot, status_line=status)

    def _should_fail():
        return (random.randint(0, len(progress_report_items)) == 0)
    for item in progress_report_items:
        counters[item] += 1
        report_progress(item, counters[item], totals[item], 'Doing action {0} [{1}/{2}]'.format(item, counters[item], totals[item]))
        if len(log_messages):
            (lev, msg) = log_messages.pop(0)
            logger.log(lev, msg)
        if (fail and _should_fail()):
            raise RuntimeError('This is a simulated exception in the middle of the loop')
        if (skip and _should_fail()):
            raise SkipBuild('This is a simulated skip in the middle of the loop')
        if sleep_time:
            time.sleep(sleep_time)
    if skip:
        raise SkipBuild('This build should be skipped!')
    if fail:
        raise RuntimeError('This is a simulated exception')
    return retval
Job used for testing purposes.

:param progress_steps:
    A list of tuples: ``(<group_name>, <steps>)``, where "group_name"
    is a tuple of name "levels", "steps" an integer representing how
    many steps should that level have.

    Progress reports will be sent in randomized order.

:param retval:
    The return value for the job.

:param fail:
    Whether this job should fail.

:param skip:
    Whether this job should be skipped.

:param log_messages:
    A list of tuples: ``(level, message)``

:param step_duration:
    The time to sleep between steps, in milliseconds.
def testing_job(progress_steps=None, retval=None, fail=False, skip=False, log_messages=None, step_duration=0):
    '\n    Job used for testing purposes.\n\n    :param progress_steps:\n        A list of tuples: ``(<group_name>, <steps>)``, where "group_name"\n        is a tuple of name "levels", "steps" an integer representing how\n        many steps should that level have.\n\n        Progress reports will be sent in randomized order.\n\n    :param retval:\n        The return value for the job.\n\n    :param fail:\n        Whether this job should fail.\n\n    :param skip:\n        Whether this job should be skipped.\n\n    :param log_messages:\n        A list of tuples: ``(level, message)``\n\n    :param step_duration:\n        The time to sleep between steps, in milliseconds.\n    '
    from jobcontrol.globals import execution_context
    logger = logging.getLogger('jobcontrol.utils.testing_job')
    log_messages = list((log_messages or []))
    if (progress_steps is None):
        progress_steps = [(None, 10)]
    totals = {}
    counters = {}
    progress_report_items = []
    for (name, steps) in progress_steps:
        if isinstance(name, list):
            name = tuple(name)
        if (not ((name is None) or isinstance(name, tuple))):
            raise TypeError('Name must be a tuple or None')
        for i in xrange(steps):
            progress_report_items.append(name)
        totals[name] = steps
        counters[name] = 0
    random.shuffle(progress_report_items)
    sleep_time = ((step_duration * 1.0) / 1000)

    def report_progress(name, cur, tot, status=None):
        app = execution_context.current_app
        app.report_progress(group_name=name, current=cur, total=tot, status_line=status)

    def _should_fail():
        return (random.randint(0, len(progress_report_items)) == 0)
    for item in progress_report_items:
        counters[item] += 1
        report_progress(item, counters[item], totals[item], 'Doing action {0} [{1}/{2}]'.format(item, counters[item], totals[item]))
        if len(log_messages):
            (lev, msg) = log_messages.pop(0)
            logger.log(lev, msg)
        if (fail and _should_fail()):
            raise RuntimeError('This is a simulated exception in the middle of the loop')
        if (skip and _should_fail()):
            raise SkipBuild('This is a simulated skip in the middle of the loop')
        if sleep_time:
            time.sleep(sleep_time)
    if skip:
        raise SkipBuild('This build should be skipped!')
    if fail:
        raise RuntimeError('This is a simulated exception')
    return retval