'Find and load step definitions, and them find and load
features under `base_path` specified on constructor'

def run(self):

    results = []
    if self.single_feature:
        features_files = [self.single_feature]
    else:
        features_files = self.loader.find_feature_files()
        if self.random:
            random.shuffle(features_files)
    if (not features_files):
        self.output.print_no_features_found(self.loader.base_dir)
        return
    try:
        self.loader.find_and_load_step_definitions()
    except StepLoadingError as e:
        print 'Error    loading    step    definitions:\n', e
        return
    call_hook('before', 'all')
    failed = False
    try:
        for filename in features_files:
            feature = Feature.from_file(filename)
            results.append(feature.run(self.scenarios, tags=self.tags, random=self.random, failfast=self.failfast))
    except exceptions.LettuceSyntaxError as e:
        sys.stderr.write(e.msg)
        failed = True
    except exceptions.NoDefinitionFound as e:
        sys.stderr.write(e.msg)
        failed = True
    except:
        if (not self.failfast):
            e = sys.exc_info()[1]
            print ('Died    with    %s' % str(e))
            traceback.print_exc()
        else:
            print
            print 'Lettuce    aborted    running    any    more    tests    because    was    called    with    the    `--failfast`    option'
        failed = True
    finally:
        total = TotalResult(results)
        total.output_format()
        call_hook('after', 'all', total)
        if failed:
            raise LettuceRunnerError('Test    failed.')
        return total
