Source code for testplan.testing.bdd.bdd_tools

import os
import re

from testplan.testing.bdd.suite import (
    GherkinTestSuiteBase,
    NonTestplanSafeNameError,
)

from boltons.iterutils import get_path

from testplan.testing.bdd.parsers import RegExParser
from testplan.testing.bdd.testloader import load_features
from testplan.testing.bdd.step_registry import StepRegistry

FEATURE_FILE_EXTENSION = ".feature"


[docs]class NoopContextResolver:
[docs] def resolve(self, context, resolvable): return resolvable
[docs]class ContextResolver: def __init__(self, start_tag="{{", end_tag="}}"): self.start_tag = start_tag self.end_tag = end_tag @property def regexp(self): return ( "({start_tag}((.(?!({start_tag}|{end_tag})))*.){end_tag})".format( start_tag=self.start_tag, end_tag=self.end_tag ) )
[docs] def resolve(self, context, text): result = text for marker, name, _, _ in re.findall(self.regexp, text): result = result.replace( marker, str(get_path(context, name, marker)) ) return result
BDD_CONTEXT_KEY = "__BDD_CONTEXT__"
[docs]def create_linked_registry(feature, default_parser_class): registry = StepRegistry() definition_file = "{}.steps.py".format(os.path.splitext(feature.file)[0]) registry.load_steps(definition_file, default_parser_class) return registry
[docs]class BDDTestSuiteFactory: """ Factory class which can create TestSuits from a directory of feature files :param features_path: is the path to the directory containing the feature and step definition :param resolver: context resolver can be used to refer context values from steps :param default_parser: the default parser used in step matching default use regex :param feature_linked_steps: assumes per feature step definition files :param common_step_dirs: list of paths to common step files """ def __init__( self, features_path, resolver=NoopContextResolver(), default_parser=RegExParser, feature_linked_steps=False, common_step_dirs=None, ): self.features_path = features_path self.resolver = resolver self.default_step_parser_class = default_parser self.feature_linked_steps = feature_linked_steps features = load_features(features_path) self.common_step_dirs = common_step_dirs or [] self.features = self._load_steps(features)
[docs] def create_suites(self): """ This is the factory function when can be used tyo obtain Multitest compatible TestSuites :return: a list of suites inherited from :py:class:`GherkinTestSuiteBase <testplan.testing.bdd.suite.GherkinTestSuiteBase>`. """ suits = [] for feature, step_registry in self.features: try: suite = self._create_suite(feature, step_registry) suits.append(suite) except NonTestplanSafeNameError as error: raise NonTestplanSafeNameError( "{} in file: {}".format(str(error), feature.file) ) return suits
def _create_suite(self, feature, step_registry): suite = GherkinTestSuiteBase.get_suite_class(feature)( feature, step_registry, self.resolver ) return suite def _load_steps(self, features): if self.feature_linked_steps: return [ ( feature, create_linked_registry( feature, self.default_step_parser_class ), ) for feature in features ] else: registry = StepRegistry() steps_lookup_locations = [ os.path.join(self.features_path, "steps") ] steps_lookup_locations.extend(self.common_step_dirs) for steps_location in steps_lookup_locations: for dirname, dirs, files in os.walk(steps_location): for definition_file in [ os.path.join(dirname, featurefile) for featurefile in files if os.path.splitext(featurefile)[1] == ".py" ]: registry.load_steps( definition_file, self.default_step_parser_class ) return [(feature, registry) for feature in features]