def assert_equal_steps(test_case, expected, actual):
    """
    Assert that the list of provided steps are the same.
    If they are not, display the differences intelligently.

    :param test_case: The ``TestCase`` whose assert methods will be called.
    :param expected: The expected build step instance.
    :param actual: The actual build step instance.
    :raises: ``TestFailure`` if the build steps are not equal, showing the
        unequal or missing steps.
    """
    expected_steps = getattr(expected, 'steps')
    actual_steps = getattr(actual, 'steps')
    if None in (expected_steps, actual_steps):
        test_case.assertEqual(expected, actual)
    else:
        mismatch_steps = []
        missing_steps = []
        index = 0
        for index, expected_step in enumerate(expected_steps):
            try:
                actual_step = actual_steps[index]
            except __HOLE__:
                missing_steps = expected_steps[index:]
                break
            if expected_step != actual_step:
                mismatch_steps.append(
                    '* expected: {} !=\n'
                    '  actual:   {}'.format(
                        expected_step, actual_step))
        extra_steps = actual_steps[index+1:]
        if mismatch_steps or missing_steps or extra_steps:
            test_case.fail(
                'Step Mismatch\n'
                'Mismatch:\n{}\n'
                'Missing:\n{}\n'
                'Extra:\n{}'.format(
                    '\n'.join(mismatch_steps), missing_steps, extra_steps)
            )
dataset/ETHPy150Open ClusterHQ/flocker/admin/test/test_packaging.py/assert_equal_steps