Best Python code snippet using tavern
steps.py
Source:steps.py
...173 @when('I run "{command}"')174 Function: step_i_run_command()175 Location: behave4cmd0/command_steps.py:80176 Run a command as subprocess, collect its output and returncode.177 @step('a file named "{filename}" exists')178 Function: step_file_named_filename_exists()179 Location: behave4cmd0/command_steps.py:305180 Verifies that a file with this filename exists.181 .. code-block:: gherkin182 Given a file named "abc.txt" exists183 When a file named "abc.txt" exists184 ...185 .. note::186 Supports behave dry-run mode.187 """188 name = "steps.doc"189 description = "Shows documentation for step definitions."190 shows_location = True191 shows_function_name = True192 ordered_by_location = True193 doc_prefix = make_indentation(4)194 # -- REPORT SPECIFIC-API:195 def report(self):196 self.report_step_definition_docs()197 self.stream.write("\n")198 def report_step_definition_docs(self):199 step_definitions = []200 for step_type in self.step_types:201 for step_definition in self.step_registry.steps[step_type]:202 # step_definition.step_type = step_type203 assert step_definition.step_type is not None204 step_definitions.append(step_definition)205 if self.ordered_by_location:206 step_definitions = sorted(step_definitions,207 key=attrgetter("location"))208 for step_definition in step_definitions:209 self.write_step_definition(step_definition)210 def write_step_definition(self, step_definition):211 step_definition_text = self.describe_step_definition(step_definition)212 self.stream.write(u"%s\n" % step_definition_text)213 doc = inspect.getdoc(step_definition.func)214 func_name = step_definition.func.__name__215 if self.shows_function_name and func_name not in ("step", "impl"):216 self.stream.write(u" Function: %s()\n" % func_name)217 if self.shows_location:218 self.stream.write(u" Location: %s\n" % step_definition.location)219 if doc:220 doc = doc.strip()221 self.stream.write(indent(doc, self.doc_prefix))222 self.stream.write("\n")223 self.stream.write("\n")224# -----------------------------------------------------------------------------225# CLASS: StepsCatalogFormatter226# -----------------------------------------------------------------------------227class StepsCatalogFormatter(StepsDocFormatter):228 """229 Provides formatter class that shows the documentation of all registered230 step definitions. The primary purpose is to provide help for a test writer.231 In order to ease work for non-programmer testers, the technical details of232 the steps (i.e. function name, source location) are ommited and the233 steps are shown as they would apprear in a feature file (no noisy '@',234 or '(', etc.).235 Also, the output is sorted by step type (Given, When, Then)236 Generic step definitions are listed with all three step types.237 EXAMPLE:238 $ behave --dry-run -f steps.catalog features/239 Given a file named "{filename}" with240 Creates a textual file with the content provided as docstring.241 When I run "{command}"242 Run a command as subprocess, collect its output and returncode.243 Given a file named "{filename}" exists244 When a file named "{filename}" exists245 Then a file named "{filename}" exists246 Verifies that a file with this filename exists.247 .. code-block:: gherkin248 Given a file named "abc.txt" exists249 When a file named "abc.txt" exists250 ...251 .. note::252 Supports behave dry-run mode.253 """254 name = "steps.catalog"255 description = "Shows non-technical documentation for step definitions."256 shows_location = False257 shows_function_name = False258 ordered_by_location = False259 doc_prefix = make_indentation(4)260 def describe_step_definition(self, step_definition, step_type=None):261 if not step_type:262 step_type = step_definition.step_type263 assert step_type264 desc = []265 if step_type == 'step':266 for step_type in self.step_types[:-1]:267 text = u"%5s %s" % (step_type.title(), step_definition.pattern)268 desc.append(text)269 else:270 desc.append(u"%s %s" % (step_type.title(), step_definition.pattern))271 return '\n'.join(desc)272# -----------------------------------------------------------------------------273# CLASS: StepsUsageFormatter274# -----------------------------------------------------------------------------275class StepsUsageFormatter(AbstractStepsFormatter):276 """277 Provides formatter class that shows how step definitions are used by steps.278 EXAMPLE:279 $ behave --dry-run -f steps.usage features/280 ...281 .. note::282 Supports behave dry-run mode.283 """284 name = "steps.usage"285 description = "Shows how step definitions are used by steps."286 doc_prefix = make_indentation(4)287 min_location_column = 40288 def __init__(self, stream_opener, config):289 super(StepsUsageFormatter, self).__init__(stream_opener, config)290 self.step_usage_database = {}291 self.undefined_steps = []292 def reset(self):293 super(StepsUsageFormatter, self).reset()294 self.step_usage_database = {}295 self.undefined_steps = []296 # pylint: disable=invalid-name297 def get_step_type_for_step_definition(self, step_definition):298 step_type = step_definition.step_type299 if not step_type:300 # -- DETERMINE STEP-TYPE FROM STEP-REGISTRY:301 assert self.step_registry302 for step_type, values in self.step_registry.steps.items():303 if step_definition in values:304 return step_type305 # -- OTHERWISE:306 step_type = "step"307 return step_type308 # pylint: enable=invalid-name309 def select_unused_step_definitions(self):310 step_definitions = set()311 for step_type, values in self.step_registry.steps.items():312 step_definitions.update(values)313 used_step_definitions = set(self.step_usage_database.keys())314 unused_step_definitions = step_definitions - used_step_definitions315 return unused_step_definitions316 def update_usage_database(self, step_definition, step):317 matching_steps = self.step_usage_database.get(step_definition, None)318 if matching_steps is None:319 assert step_definition.step_type is not None320 matching_steps = self.step_usage_database[step_definition] = []321 # -- AVOID DUPLICATES: From Scenario Outlines322 if not steps_contain(matching_steps, step):323 matching_steps.append(step)324 def update_usage_database_for_step(self, step):325 step_definition = self.step_registry.find_step_definition(step)326 if step_definition:327 self.update_usage_database(step_definition, step)328 # elif step not in self.undefined_steps:329 elif not steps_contain(self.undefined_steps, step):330 # -- AVOID DUPLICATES: From Scenario Outlines331 self.undefined_steps.append(step)332 # pylint: disable=invalid-name333 def update_usage_database_for_feature(self, feature):334 # -- PROCESS BACKGROUND (if exists): Use Background steps only once.335 if feature.background:336 for step in feature.background.steps:337 self.update_usage_database_for_step(step)338 # -- PROCESS SCENARIOS: Without background steps.339 for scenario in feature.walk_scenarios():340 for step in scenario.steps:341 self.update_usage_database_for_step(step)342 # pylint: enable=invalid-name343 # -- FORMATTER API:344 def feature(self, feature):345 super(StepsUsageFormatter, self).feature(feature)346 self.update_usage_database_for_feature(feature)347 # -- REPORT API:348 def report(self):349 self.report_used_step_definitions()350 self.report_unused_step_definitions()351 self.report_undefined_steps()352 self.stream.write("\n")353 # -- REPORT SPECIFIC-API:354 def report_used_step_definitions(self):355 # -- STEP: Used step definitions....
sphinx_steps.py
Source:sphinx_steps.py
1# -*- coding: utf-8 -*-2"""3Provides a formatter that generates Sphinx-based documentation4of available step definitions (step implementations).5TODO:6 * Post-processor for step docstrings.7 * Solution for requires: table, text8 * i18n keywords9.. seealso::10 http://sphinx-doc.org/11.. note:: REQUIRES docutils12 :mod:`docutils` are needed to generate step-label for step references.13"""14from __future__ import absolute_import, print_function15from operator import attrgetter16import inspect17import os.path18import sys19from behave.formatter.steps import AbstractStepsFormatter20from behave.formatter import sphinx_util21from behave.model import Table22try:23 # -- NEEDED FOR: step-labels (and step-refs)24 from docutils.nodes import fully_normalize_name25 has_docutils = True26except ImportError:27 has_docutils = False28# -----------------------------------------------------------------------------29# HELPER CLASS:30# -----------------------------------------------------------------------------31class StepsModule(object):32 """33 Value object to keep track of step definitions that belong to same module.34 """35 def __init__(self, module_name, step_definitions=None):36 self.module_name = module_name37 self.step_definitions = step_definitions or []38 self._name = None39 self._filename = None40 @property41 def name(self):42 if self._name is None:43 # -- DISCOVER ON DEMAND: From step definitions (module).44 # REQUIRED: To discover complete canonical module name.45 module = self.module46 if module:47 # -- USED-BY: Imported step libraries.48 module_name = self.module.__name__49 else:50 # -- USED-BY: features/steps/*.py (without __init__.py)51 module_name = self.module_name52 self._name = module_name53 return self._name54 @property55 def filename(self):56 if not self._filename:57 if self.step_definitions:58 filename = inspect.getfile(self.step_definitions[0].func)59 self._filename = os.path.relpath(filename)60 return self._filename61 @property62 def module(self):63 if self.step_definitions:64 return inspect.getmodule(self.step_definitions[0].func)65 return sys.modules.get(self.module_name)66 @property67 def module_doc(self):68 module = self.module69 if module:70 return inspect.getdoc(module)71 return None72 def append(self, step_definition):73 self.step_definitions.append(step_definition)74# -----------------------------------------------------------------------------75# CLASS: SphinxStepsDocumentGenerator76# -----------------------------------------------------------------------------77class SphinxStepsDocumentGenerator(object):78 """79 Provides document generator class that generates Sphinx-based80 documentation for step definitions. The primary purpose is to:81 * help the step-library provider/writer82 * simplify self-documentation of step-libraries83 EXAMPLE:84 step_definitions = ... # Collect from step_registry85 doc_generator = SphinxStepsDocumentGenerator(step_definitions, "output")86 doc_generator.write_docs()87 .. seealso:: http://sphinx-doc.org/88 """89 default_step_definition_doc = """\90.. todo::91 Step definition description is missing.92"""93 shows_step_module_info = True94 shows_step_module_overview = True95 make_step_index_entries = True96 make_step_labels = has_docutils97 document_separator = "# -- DOCUMENT-END " + "-" * 6098 step_document_prefix = "step_module."99 step_heading_prefix = "**Step:** "100 def __init__(self, step_definitions, destdir=None, stream=None):101 self.step_definitions = step_definitions102 self.destdir = destdir103 self.stream = stream104 self.document = None105 @property106 def stdout_mode(self):107 """108 Indicates that output towards stdout should be used.109 """110 return self.stream is not None111 @staticmethod112 def describe_step_definition(step_definition, step_type=None):113 if not step_type:114 step_type = step_definition.step_type or "step"115 if step_type == "step":116 step_type_text = "Given/When/Then"117 else:118 step_type_text = step_type.capitalize()119 # -- ESCAPE: Some chars required for ReST documents (like backticks)120 step_text = step_definition.pattern121 if "`" in step_text:122 step_text = step_text.replace("`", r"\`")123 return u"%s %s" % (step_type_text, step_text)124 def ensure_destdir_exists(self):125 assert self.destdir126 if os.path.isfile(self.destdir):127 print("OOPS: remove %s" % self.destdir)128 os.remove(self.destdir)129 if not os.path.exists(self.destdir):130 os.makedirs(self.destdir)131 def ensure_document_is_closed(self):132 if self.document and not self.stdout_mode:133 self.document.close()134 self.document = None135 def discover_step_modules(self):136 step_modules_map = {}137 for step_definition in self.step_definitions:138 assert step_definition.step_type is not None139 step_filename = step_definition.location.filename140 step_module = step_modules_map.get(step_filename, None)141 if not step_module:142 filename = inspect.getfile(step_definition.func)143 module_name = inspect.getmodulename(filename)144 assert module_name, \145 "step_definition: %s" % step_definition.location146 step_module = StepsModule(module_name)147 step_modules_map[step_filename] = step_module148 step_module.append(step_definition)149 step_modules = sorted(step_modules_map.values(), key=attrgetter("name"))150 for module in step_modules:151 step_definitions = sorted(module.step_definitions,152 key=attrgetter("location"))153 module.step_definitions = step_definitions154 return step_modules155 def create_document(self, filename):156 if not (filename.endswith(".rst") or filename.endswith(".txt")):157 filename += ".rst"158 if self.stdout_mode:159 stream = self.stream160 document = sphinx_util.DocumentWriter(stream, should_close=False)161 else:162 self.ensure_destdir_exists()163 filename = os.path.join(self.destdir, filename)164 document = sphinx_util.DocumentWriter.open(filename)165 return document166 def write_docs(self):167 step_modules = self.discover_step_modules()168 self.write_step_module_index(step_modules)169 for step_module in step_modules:170 self.write_step_module(step_module)171 return len(step_modules)172 def write_step_module_index(self, step_modules, filename="index.rst"):173 document = self.create_document(filename)174 document.write(".. _docid.steps:\n\n")175 document.write_heading("Step Definitions")176 document.write("""\177The following step definitions are provided here.178----179""")180 entries = sorted([self.step_document_prefix + module.name181 for module in step_modules])182 document.write_toctree(entries, maxdepth=1)183 document.close()184 if self.stdout_mode:185 sys.stdout.write("\n%s\n" % self.document_separator)186 def write_step_module(self, step_module):187 self.ensure_document_is_closed()188 document_name = self.step_document_prefix + step_module.name189 self.document = self.create_document(document_name)190 self.document.write(".. _docid.steps.%s:\n" % step_module.name)191 self.document.write_heading(step_module.name, index_id=step_module.name)192 if self.shows_step_module_info:193 self.document.write(":Module: %s\n" % step_module.name)194 self.document.write(":Filename: %s\n" % step_module.filename)195 self.document.write("\n")196 if step_module.module_doc:197 module_doc = step_module.module_doc.strip()198 self.document.write("%s\n\n" % module_doc)199 if self.shows_step_module_overview:200 self.document.write_heading("Step Overview", level=1)201 self.write_step_module_overview(step_module.step_definitions)202 self.document.write_heading("Step Definitions", level=1)203 for step_definition in step_module.step_definitions:204 self.write_step_definition(step_definition)205 # -- FINALLY: Clean up resources.206 self.document.close()207 self.document = None208 if self.stdout_mode:209 sys.stdout.write("\n%s\n" % self.document_separator)210 def write_step_module_overview(self, step_definitions):211 assert self.document212 headings = [u"Step Definition", u"Given", u"When", u"Then", u"Step"]213 table = Table(headings)214 step_type_cols = {215 # -- pylint: disable=bad-whitespace216 "given": [u" x", u" ", u" ", u" "],217 "when": [u" ", u" x", u" ", u" "],218 "then": [u" ", u" ", u" x", u" "],219 "step": [u" x", u" x", u" x", u" x"],220 }221 for step_definition in step_definitions:222 row = [self.describe_step_definition(step_definition)]223 row.extend(step_type_cols[step_definition.step_type])224 table.add_row(row)225 self.document.write_table(table)226 @staticmethod227 def make_step_definition_index_id(step):228 if step.step_type == "step":229 index_kinds = ("Given", "When", "Then", "Step")230 else:231 keyword = step.step_type.capitalize()232 index_kinds = (keyword,)233 schema = "single: %s%s; %s %s"234 index_parts = []235 for index_kind in index_kinds:236 keyword = index_kind237 word = " step"238 if index_kind == "Step":239 keyword = "Given/When/Then"240 word = ""241 part = schema % (index_kind, word, keyword, step.pattern)242 index_parts.append(part)243 joiner = "\n "244 return joiner + joiner.join(index_parts)245 def make_step_definition_doc(self, step):246 doc = inspect.getdoc(step.func)247 if not doc:248 doc = self.default_step_definition_doc249 doc = doc.strip()250 return doc251 def write_step_definition(self, step):252 assert self.document253 step_text = self.describe_step_definition(step)254 if step_text.startswith("* "):255 step_text = step_text[2:]256 index_id = None257 if self.make_step_index_entries:258 index_id = self.make_step_definition_index_id(step)259 heading = step_text260 step_label = None261 if self.step_heading_prefix:262 heading = self.step_heading_prefix + step_text263 if has_docutils and self.make_step_labels:264 # -- ADD STEP-LABEL (supports: step-refs by name)265 # EXAMPLE: See also :ref:`When my step does "{something}"`.266 step_label = fully_normalize_name(step_text)267 # SKIP-HERE: self.document.write(".. _%s:\n\n" % step_label)268 self.document.write_heading(heading, level=2, index_id=index_id,269 label=step_label)270 step_definition_doc = self.make_step_definition_doc(step)271 self.document.write("%s\n" % step_definition_doc)272 self.document.write("\n")273# -----------------------------------------------------------------------------274# CLASS: SphinxStepsFormatter275# -----------------------------------------------------------------------------276class SphinxStepsFormatter(AbstractStepsFormatter):277 """278 Provides formatter class that generates Sphinx-based documentation279 for all registered step definitions. The primary purpose is to:280 * help the step-library provider/writer281 * simplify self-documentation of step-libraries282 .. note::283 Supports dry-run mode.284 Supports destination directory mode to write multiple documents.285 """286 name = "sphinx.steps"287 description = "Generate sphinx-based documentation for step definitions."288 doc_generator_class = SphinxStepsDocumentGenerator289 def __init__(self, stream_opener, config):290 super(SphinxStepsFormatter, self).__init__(stream_opener, config)291 self.destdir = stream_opener.name292 @property293 def step_definitions(self):294 """Derive step definitions from step-registry."""295 steps = []296 for step_type, step_definitions in self.step_registry.steps.items():297 for step in step_definitions:298 step.step_type = step_type299 steps.append(step)300 return steps301 # -- FORMATTER-API:302 def close(self):303 """Called at end of test run."""304 if not self.step_registry:305 self.discover_step_definitions()306 self.report()307 # -- SPECIFIC-API:308 def create_document_generator(self):309 generator_class = self.doc_generator_class310 if self.stdout_mode:311 return generator_class(self.step_definitions, stream=self.stream)312 else:313 return generator_class(self.step_definitions, destdir=self.destdir)314 def report(self):315 document_generator = self.create_document_generator()316 document_counts = document_generator.write_docs()317 if not self.stdout_mode:318 msg = "%s: Written %s document(s) into directory '%s'.\n"...
_stepimport.py
Source:_stepimport.py
1# -*- coding: UTF-8 -*-2"""3This module provides low-level helper functionality during step imports.4.. warn:: Do not use directly5 It should not be used directly except in behave Runner classes6 that need to provide the correct context (step_registry, matchers, etc.)7 instead of using the global module specific variables.8"""9from __future__ import absolute_import10from contextlib import contextmanager11from threading import Lock12from types import ModuleType13import os.path14import sys15from behave import step_registry as _step_registry16# from behave import matchers as _matchers17import six18# -----------------------------------------------------------------------------19# UTILITY FUNCTIONS:20# -----------------------------------------------------------------------------21def setup_api_with_step_decorators(module, step_registry):22 _step_registry.setup_step_decorators(module, step_registry)23def setup_api_with_matcher_functions(module, matcher_factory):24 module.use_step_matcher = matcher_factory.use_step_matcher25 module.step_matcher = matcher_factory.use_step_matcher26 module.register_type = matcher_factory.register_type27# -----------------------------------------------------------------------------28# FAKE MODULE CLASSES: For step imports29# -----------------------------------------------------------------------------30# class FakeModule(object):31class FakeModule(ModuleType):32 ensure_fake = True33 # -- SUPPORT FOR: behave.step_registry.setup_step_decorators()34 def __setitem__(self, name, value):35 assert "." not in name36 setattr(self, name, value)37class StepRegistryModule(FakeModule):38 """Provides a fake :mod:`behave.step_registry` module39 that can be used during step imports.40 """41 __all__ = [42 "given", "when", "then", "step",43 "Given", "When", "Then", "Step",44 ]45 def __init__(self, step_registry):46 super(StepRegistryModule, self).__init__("behave.step_registry")47 self.registry = step_registry48 setup_api_with_step_decorators(self, step_registry)49class StepMatchersModule(FakeModule):50 __all__ = ["use_step_matcher", "register_type", "step_matcher"]51 def __init__(self, matcher_factory):52 super(StepMatchersModule, self).__init__("behave.matchers")53 self.matcher_factory = matcher_factory54 setup_api_with_matcher_functions(self, matcher_factory)55 self.use_default_step_matcher = matcher_factory.use_default_step_matcher56 self.get_matcher = matcher_factory.make_matcher57 # self.matcher_mapping = matcher_mapping or _matchers.matcher_mapping.copy()58 # self.current_matcher = current_matcher or _matchers.current_matcher59 # -- INJECT PYTHON PACKAGE META-DATA:60 # REQUIRED-FOR: Non-fake submodule imports (__path__).61 here = os.path.dirname(__file__)62 self.__file__ = os.path.abspath(os.path.join(here, "matchers.py"))63 self.__name__ = "behave.matchers"64 # self.__path__ = [os.path.abspath(here)]65 # def use_step_matcher(self, name):66 # self.matcher_factory.use_step_matcher(name)67 # # self.current_matcher = self.matcher_mapping[name]68 #69 # def use_default_step_matcher(self, name=None):70 # self.matcher_factory.use_default_step_matcher(name=None)71 #72 # def get_matcher(self, func, pattern):73 # # return self.current_matcher74 # return self.matcher_factory.make_matcher(func, pattern)75 #76 # def register_type(self, **kwargs):77 # # _matchers.register_type(**kwargs)78 # self.matcher_factory.register_type(**kwargs)79 #80 # step_matcher = use_step_matcher81class BehaveModule(FakeModule):82 __all__ = StepRegistryModule.__all__ + StepMatchersModule.__all__83 def __init__(self, step_registry, matcher_factory=None):84 if matcher_factory is None:85 matcher_factory = step_registry.step_matcher_factory86 assert matcher_factory is not None87 super(BehaveModule, self).__init__("behave")88 setup_api_with_step_decorators(self, step_registry)89 setup_api_with_matcher_functions(self, matcher_factory)90 self.use_default_step_matcher = matcher_factory.use_default_step_matcher91 assert step_registry.matcher_factory == matcher_factory92 # -- INJECT PYTHON PACKAGE META-DATA:93 # REQUIRED-FOR: Non-fake submodule imports (__path__).94 here = os.path.dirname(__file__)95 self.__file__ = os.path.abspath(os.path.join(here, "__init__.py"))96 self.__name__ = "behave"97 self.__path__ = [os.path.abspath(here)]98 self.__package__ = None99class StepImportModuleContext(object):100 def __init__(self, step_container):101 self.step_registry = step_container.step_registry102 self.matcher_factory = step_container.matcher_factory103 assert self.step_registry.matcher_factory == self.matcher_factory104 self.step_registry.matcher_factory = self.matcher_factory105 step_registry_module = StepRegistryModule(self.step_registry)106 step_matchers_module = StepMatchersModule(self.matcher_factory)107 behave_module = BehaveModule(self.step_registry, self.matcher_factory)108 self.modules = {109 "behave": behave_module,110 "behave.matchers": step_matchers_module,111 "behave.step_registry": step_registry_module,112 }113 # self.default_matcher = self.step_matchers_module.current_matcher114 def reset_current_matcher(self):115 self.matcher_factory.use_default_step_matcher()116_step_import_lock = Lock()117unknown = object()118@contextmanager119def use_step_import_modules(step_container):120 """Redirect any step/type registration to the runner's step-context object121 during step imports by using fake modules (instead of using module-globals).122 This allows that multiple runners can be used without polluting the123 global variables in problematic modules124 (:mod:`behave.step_registry`, mod:`behave.matchers`).125 .. sourcecode:: python126 # -- RUNNER-IMPLEMENTATION:127 def load_step_definitions(self, ...):128 step_container = self.step_container129 with use_step_import_modules(step_container) as import_context:130 # -- USE: Fake modules during step imports131 ...132 import_context.reset_current_matcher()133 :param step_container: Step context object with step_registry, matcher_factory.134 """135 orig_modules = {}136 import_context = StepImportModuleContext(step_container)137 with _step_import_lock:138 # -- CRITICAL-SECTION (multi-threading protected)139 try:140 # -- SCOPE-GUARD SETUP: Replace original modules with fake ones.141 for module_name, fake_module in six.iteritems(import_context.modules):142 orig_module = sys.modules.get(module_name, unknown)143 orig_modules[module_name] = orig_module144 sys.modules[module_name] = fake_module145 # -- USE: Fake modules for step imports.146 yield import_context147 finally:148 # -- SCOPE-GUARD CLEANUP: Restore original modules.149 for module_name, orig_module in six.iteritems(orig_modules):150 if orig_module is unknown:151 del sys.modules[module_name]152 else:...
behave.step_durations.py
Source:behave.step_durations.py
...27 self.max_duration = 028 self.durations = []29 self.step = step30 if step:31 self.process_step(step)32 @staticmethod33 def make_step_name(step):34 step_name = "%s %s" % (step.step_type.capitalize(), step.name)35 return step_name36 def process_step(self, step):37 step_name = self.make_step_name(step)38 if not self.step_name:39 self.step_name = step_name40 if self.min_duration > step.duration:41 self.min_duration = step.duration42 if self.max_duration < step.duration:43 self.max_duration = step.duration44 self.durations.append(step.duration)45class BehaveDurationData(object):46 def __init__(self):47 self.step_registry = {}48 self.all_steps = []49 self.all_scenarios = []50 def process_features(self, features):51 for feature in features:52 self.process_feature(feature)53 def process_feature(self, feature):54 if feature.background:55 self.process_background(feature.background)56 for scenario in feature.scenarios:57 if isinstance(scenario, ScenarioOutline):58 self.process_scenario_outline(scenario)59 else:60 self.process_scenario(scenario)61 def process_step(self, step):62 step_name = StepDurationData.make_step_name(step)63 known_step = self.step_registry.get(step_name, None)64 if known_step:65 known_step.process_step(step)66 else:67 step_data = StepDurationData(step)68 self.step_registry[step_name] = step_data69 self.all_steps.append(step)70 def process_background(self, scenario):71 for step in scenario:72 self.process_step(step)73 def process_scenario(self, scenario):74 for step in scenario:75 self.process_step(step)76 def process_scenario_outline(self, scenario_outline):77 for scenario in scenario_outline:78 self.process_scenario(scenario)79 def report_step_durations(self, limit=None, min_duration=None, ostream=sys.stdout):80 step_datas = list(self.step_registry.values())81 steps_size = len(step_datas)82 steps_by_longest_duration_first = sorted(step_datas,83 key=attrgetter("max_duration"),84 reverse=True)85 ostream.write("STEP DURATIONS (longest first, size=%d):\n" % steps_size)86 ostream.write("-" * 80)87 ostream.write("\n")88 for index, step in enumerate(steps_by_longest_duration_first):89 ostream.write("% 4d. %9.6fs %s" % \...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!