├── Makefile ├── README.md ├── behave-parallel ├── .coveragerc ├── .editorconfig ├── .gitignore ├── .pycheckrc ├── .travis.yml ├── CHANGES.rst ├── LICENSE ├── MANIFEST.in ├── PROJECT_INFO.rst ├── README.md ├── README.rst ├── VERSION.txt ├── behave.ini ├── behave │ ├── __init__.py │ ├── __main__.py │ ├── compat │ │ ├── __init__.py │ │ ├── collections.py │ │ ├── importlib.py │ │ └── os_path.py │ ├── configuration.py │ ├── formatter │ │ ├── __init__.py │ │ ├── ansi_escapes.py │ │ ├── base.py │ │ ├── filter_formatter.py │ │ ├── filters.py │ │ ├── formatters.py │ │ ├── json.py │ │ ├── null.py │ │ ├── plain.py │ │ ├── pretty.py │ │ ├── progress.py │ │ ├── rerun.py │ │ ├── sphinx_steps.py │ │ ├── sphinx_util.py │ │ ├── steps.py │ │ └── tags.py │ ├── i18n.py │ ├── importer.py │ ├── json_parser.py │ ├── log_capture.py │ ├── matchers.py │ ├── model.py │ ├── model_describe.py │ ├── parser.py │ ├── reporter │ │ ├── __init__.py │ │ ├── base.py │ │ ├── junit.py │ │ └── summary.py │ ├── runner.py │ ├── runner_util.py │ ├── step_registry.py │ ├── tag_expression.py │ └── textutil.py ├── behave4cmd0 │ ├── __all_steps__.py │ ├── __init__.py │ ├── __setup.py │ ├── command_shell.py │ ├── command_steps.py │ ├── command_util.py │ ├── failing_steps.py │ ├── log │ │ ├── __init__.py │ │ └── steps.py │ ├── note_steps.py │ ├── passing_steps.py │ ├── pathutil.py │ └── textutil.py ├── bin │ ├── behave │ ├── behave.cmd │ ├── behave.step_durations.py │ ├── json.format.py │ ├── jsonschema_validate.py │ ├── make_localpi.py │ ├── toxcmd.py │ └── toxcmd3.py ├── docs │ ├── Makefile │ ├── _static │ │ ├── agogo.css │ │ ├── behave_logo.png │ │ ├── behave_logo1.png │ │ ├── behave_logo2.png │ │ └── behave_logo3.png │ ├── _themes │ │ ├── LICENSE │ │ ├── kr │ │ │ ├── layout.html │ │ │ ├── relations.html │ │ │ ├── static │ │ │ │ ├── flasky.css_t │ │ │ │ └── small_flask.css │ │ │ └── theme.conf │ │ └── kr_small │ │ │ ├── layout.html │ │ │ ├── static │ │ │ └── flasky.css_t │ │ │ └── theme.conf │ ├── api.rst │ ├── appendix.rst │ ├── behave.rst │ ├── behave.rst-template │ ├── behave_ecosystem.rst │ ├── comparison.rst │ ├── conf.py │ ├── context_attributes.rst │ ├── django.rst │ ├── formatters.rst │ ├── gherkin.rst │ ├── index.rst │ ├── install.rst │ ├── parse_builtin_types.rst │ ├── philosophy.rst │ ├── regular_expressions.rst │ ├── related.rst │ ├── requirements.txt │ ├── test_domains.rst │ ├── tutorial.rst │ └── update_behave_rst.py ├── etc │ ├── json │ │ └── behave.json-schema │ └── junit.xml │ │ ├── behave_junit.xsd │ │ └── junit-4.xsd ├── features │ ├── README.txt │ ├── background.feature │ ├── capture_stderr.feature │ ├── capture_stdout.feature │ ├── configuration.default_paths.feature │ ├── context.global_params.feature │ ├── context.local_params.feature │ ├── directory_layout.advanced.feature │ ├── directory_layout.basic.feature │ ├── directory_layout.basic2.feature │ ├── environment.py │ ├── exploratory_testing.with_table.feature │ ├── feature.description.feature │ ├── formatter.help.feature │ ├── formatter.json.feature │ ├── formatter.progress3.feature │ ├── formatter.rerun.feature │ ├── formatter.steps.feature │ ├── formatter.steps_doc.feature │ ├── formatter.steps_usage.feature │ ├── formatter.tags.feature │ ├── formatter.tags_location.feature │ ├── logcapture.clear_handlers.feature │ ├── logcapture.feature │ ├── logcapture.filter.feature │ ├── logging.no_capture.feature │ ├── logging.setup_format.feature │ ├── logging.setup_level.feature │ ├── logging.setup_with_configfile.feature │ ├── parallel_ability.feature │ ├── parser.background.sad_cases.feature │ ├── parser.feature.sad_cases.feature │ ├── runner.abort_by_user.feature │ ├── runner.default_format.feature │ ├── runner.dry_run.feature │ ├── runner.feature_listfile.feature │ ├── runner.multiple_formatters.feature │ ├── runner.select_files_by_regexp.example.feature │ ├── runner.select_files_by_regexp.feature │ ├── runner.select_scenarios_by_file_location.feature │ ├── runner.select_scenarios_by_name.feature │ ├── runner.select_scenarios_by_tag.feature │ ├── runner.stop_after_failure.feature │ ├── runner.unknown_formatter.feature │ ├── scenario.description.feature │ ├── scenario_outline.basics.feature │ ├── step.duplicated_step.feature │ ├── step.execute_steps.feature │ ├── step.execute_steps.with_table.feature │ ├── step.import_other_step_module.feature │ ├── step.undefined_steps.feature │ ├── step.use_step_library.feature │ ├── step_dialect.generic_steps.feature │ ├── step_dialect.given_when_then.feature │ ├── step_param.builtin_types.with_float.feature │ ├── step_param.builtin_types.with_integer.feature │ ├── steps │ │ ├── behave_select_files_steps.py │ │ ├── behave_steps.py │ │ ├── context_steps.py │ │ └── use_steplib_behave4cmd.py │ └── summary.undefined_steps.feature ├── issue.features │ ├── README.txt │ ├── issue0030.feature │ ├── issue0031.feature │ ├── issue0032.feature │ ├── issue0035.feature │ ├── issue0040.feature │ ├── issue0041.feature │ ├── issue0042.feature │ ├── issue0044.feature │ ├── issue0046.feature │ ├── issue0052.feature │ ├── issue0059.feature │ ├── issue0063.feature │ ├── issue0064.feature │ ├── issue0065.feature │ ├── issue0066.feature │ ├── issue0067.feature │ ├── issue0069.feature │ ├── issue0072.feature │ ├── issue0073.feature │ ├── issue0075.feature │ ├── issue0077.feature │ ├── issue0080.feature │ ├── issue0081.feature │ ├── issue0083.feature │ ├── issue0084.feature │ ├── issue0085.feature │ ├── issue0092.feature │ ├── issue0096.feature │ ├── issue0099.feature │ ├── issue0109.feature │ ├── issue0111.feature │ ├── issue0112.feature │ ├── issue0114.feature │ ├── issue0116.feature │ ├── issue0125.feature │ ├── issue0127.feature │ ├── issue0139.feature │ ├── issue0142.feature │ ├── issue0143.feature │ ├── issue0145.feature │ ├── issue0148.feature │ ├── issue0152.feature │ ├── issue0159.feature │ ├── issue0162.feature │ ├── issue0171.feature │ ├── issue0172.feature │ ├── issue0175.feature │ ├── issue0177.feature │ ├── issue0184.feature │ ├── issue0186.feature │ ├── issue0188.feature │ ├── issue0191.feature │ ├── requirements.txt │ └── steps │ │ ├── behave_hooks_steps.py │ │ └── use_steplib_behave4cmd.py ├── more.features │ ├── formatter.json.validate_output.feature │ └── steps │ │ └── use_steplib_behave4cmd.py ├── pylintrc ├── requirements │ ├── README.txt │ ├── all.txt │ ├── basic.txt │ ├── develop.txt │ ├── docs.txt │ ├── json.txt │ ├── more_py25.txt │ └── optional.txt ├── setup.cfg ├── setup.py ├── setuptools_behave.py ├── test │ ├── __init__.py │ ├── reporters │ │ ├── __init__.py │ │ └── test_summary.py │ ├── test_ansi_escapes.py │ ├── test_configuration.py │ ├── test_formatter.py │ ├── test_formatter_progress.py │ ├── test_formatter_rerun.py │ ├── test_formatter_tags.py │ ├── test_importer.py │ ├── test_log_capture.py │ ├── test_matchers.py │ ├── test_model.py │ ├── test_parser.py │ ├── test_runner.py │ ├── test_step_registry.py │ └── test_tag_expression.py ├── tools │ ├── convert_i18n_yaml.py │ ├── i18n.yml │ ├── runtests.sh │ └── test-features │ │ ├── background.feature │ │ ├── environment.py │ │ ├── french.feature │ │ ├── outline.feature │ │ ├── parse.feature │ │ ├── step-data.feature │ │ ├── steps │ │ └── steps.py │ │ └── tags.feature └── tox.ini └── features ├── __init__.py ├── environment.py ├── steps └── steps.py └── test.feature /Makefile: -------------------------------------------------------------------------------- 1 | run_all_in_parallel: 2 | make -j android_emulator samsung_galaxy_s4_emulator 3 | 4 | android_emulator: 5 | deviceName="Android Emulator" behave-parallel/bin/behave --processes 12 --parallel-element scenario 6 | 7 | samsung_galaxy_s4_emulator: 8 | deviceName="Samsung Galaxy S4 Emulator" behave-parallel/bin/behave --processes 12 --parallel-element scenario 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Python-Behave-Appium-Android 2 | 3 | This code is provided on an "AS-IS” basis without warranty of any kind, either express or implied, including without limitation any implied warranties of condition, uninterrupted use, merchantability, fitness for a particular purpose, or non-infringement. Your tests and testing environments may require you to modify this framework. Issues regarding this framework should be submitted through GitHub. For questions regarding Sauce Labs integration, please see the Sauce Labs documentation at https://wiki.saucelabs.com/. This framework is not maintained by Sauce Labs Support. 4 | 5 | ### Environment Setup 6 | 7 | 1. Global Dependencies 8 | * [Install Python](https://www.python.org/downloads/) 9 | * Or Install Python with [Homebrew](http://brew.sh/) 10 | ``` 11 | $ brew install python 12 | ``` 13 | * Install [pip](https://pip.pypa.io/en/stable/installing/) to install packages 14 | 15 | 2. Sauce Credentials 16 | * In the terminal export your Sauce Labs Credentials as environmental variables: 17 | ``` 18 | $ export SAUCE_USERNAME= 19 | $ export SAUCE_ACCESS_KEY= 20 | ``` 21 | 3. Project Dependencies 22 | * Install packages (Use sudo if necessary) 23 | ``` 24 | $ pip install behave Appium-Python-Client sauceclient 25 | ``` 26 | ### Running Tests 27 | 28 | Tests in Parallel: 29 | ``` 30 | $ make run_all_in_parallel 31 | ``` 32 | 33 | [Sauce Labs Dashboard](https://saucelabs.com/beta/dashboard/) 34 | 35 | ### Advice/Troubleshooting 36 | 37 | 1. There may be additional latency when using a remote webdriver to run tests on Sauce Labs. Timeouts or Waits may need to be increased. 38 | * [Selenium tips regarding explicit waits](https://wiki.saucelabs.com/display/DOCS/Best+Practice%3A+Use+Explicit+Waits) 39 | 40 | ### Resources 41 | ##### [Sauce Labs Documentation](https://wiki.saucelabs.com/) 42 | 43 | ##### [Appium Documentation](http://appium.io/slate/en/master/) 44 | 45 | ##### [Behave Documentation](http://pythonhosted.org/behave/) 46 | 47 | ##### [Python Documentation](https://docs.python.org/2.7/) 48 | 49 | ##### [Stack Overflow](http://stackoverflow.com/) 50 | * A great resource to search for issues not explicitly covered by documentation. 51 | -------------------------------------------------------------------------------- /behave-parallel/.coveragerc: -------------------------------------------------------------------------------- 1 | # ========================================================================= 2 | # COVERAGE CONFIGURATION FILE: .coveragerc 3 | # ========================================================================= 4 | # LANGUAGE: Python 5 | # SEE ALSO: 6 | # * http://nedbatchelder.com/code/coverage/ 7 | # * http://nedbatchelder.com/code/coverage/config.html 8 | # ========================================================================= 9 | 10 | [run] 11 | append = .coverage 12 | include = behave* 13 | branch = True 14 | parallel = True 15 | 16 | [report] 17 | # Regexes for lines to exclude from consideration 18 | exclude_lines = 19 | # Have to re-enable the standard pragma 20 | pragma: no cover 21 | 22 | # Don't complain about missing debug-only code: 23 | def __repr__ 24 | if self\.debug 25 | 26 | # Don't complain if tests don't hit defensive assertion code: 27 | raise AssertionError 28 | raise NotImplementedError 29 | 30 | # Don't complain if non-runnable code isn't run: 31 | if 0: 32 | if False: 33 | if __name__ == .__main__.: 34 | 35 | ignore_errors = True 36 | 37 | [html] 38 | directory = build/coverage.html 39 | 40 | [xml] 41 | outfile = build/coverage.xml 42 | 43 | -------------------------------------------------------------------------------- /behave-parallel/.editorconfig: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # EDITOR CONFIGURATION: http://editorconfig.org 3 | # ============================================================================= 4 | 5 | root = true 6 | 7 | # -- DEFAULT: Unix-style newlines with a newline ending every file. 8 | [*] 9 | charset = utf-8 10 | end_of_line = lf 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | 14 | [*.{py,rst,ini,txt}] 15 | indent_style = space 16 | indent_size = 4 17 | 18 | [*.feature] 19 | indent_style = space 20 | indent_size = 2 21 | 22 | [**/makefile] 23 | indent_style = tab 24 | 25 | [*.{cmd,bat}] 26 | end_of_line = crlf 27 | -------------------------------------------------------------------------------- /behave-parallel/.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info 2 | *.log 3 | *.pyc 4 | *.pyo 5 | *$py.class 6 | build/ 7 | dist/ 8 | __pycache__/ 9 | __WORKDIR__/ 10 | _build/ 11 | _WORKSPACE/ 12 | .cache/ 13 | .idea/ 14 | .tox/ 15 | .DS_Store 16 | .coverage 17 | .ropeproject 18 | nosetests.xml 19 | tools/virtualenvs 20 | -------------------------------------------------------------------------------- /behave-parallel/.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - 2.6 4 | - 2.7 5 | - pypy 6 | 7 | install: 8 | - pip install --use-mirrors -q mock nose PyHamcrest 9 | - python setup.py -q install 10 | script: 11 | - python --version 12 | - nosetests 13 | - behave -f progress --junit --tags=~@xfail features/ 14 | - behave -f progress --junit --tags=~@xfail tools/test-features/ 15 | - behave -f progress --junit --tags=~@xfail issue.features/ 16 | -------------------------------------------------------------------------------- /behave-parallel/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2013 Benno Rice, Richard Jones, Jens Engel and others, except where noted. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /behave-parallel/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | include CHANGES.rst 3 | include MANIFEST.in 4 | include LICENSE 5 | include .coveragerc 6 | include .pycheckrc 7 | include pylintrc 8 | include *.cfg 9 | include *.ini 10 | include *.rst 11 | include *.txt 12 | include bin/behave* 13 | recursive-include bin *.py *.cmd *.zip 14 | recursive-include behave4cmd0 *.py 15 | recursive-include etc *.xsd *.txt *.json-schema 16 | recursive-include docs *.rst *.txt *.css *.py *.html *.rst-* *.png Makefile 17 | recursive-include docs/_themes *.html *.conf *.css *.css_t LICENSE* 18 | recursive-include test *.py 19 | recursive-include tools *.feature *.py *.yml *.sh 20 | recursive-include features *.feature *.py *.txt 21 | recursive-include issue.features *.feature *.py *.txt 22 | recursive-include requirements *.txt 23 | prune .tox 24 | -------------------------------------------------------------------------------- /behave-parallel/PROJECT_INFO.rst: -------------------------------------------------------------------------------- 1 | Project Info 2 | =============================================================================== 3 | 4 | =============== =============================================================== 5 | Category Hyperlink 6 | =============== =============================================================== 7 | Documentation: http://pythonhosted.org/behave/ 8 | (or: https://behave.readthedocs.org/) 9 | Download: http://pypi.python.org/pypi/behave (or: `github archive`_) 10 | Development: https://github.com/behave/behave 11 | Issue Tracker: https://github.com/behave/behave/issues 12 | Changelog: `CHANGES.rst `_ 13 | =============== =============================================================== 14 | 15 | .. hint:: 16 | 17 | The PyPI version is the latest stable version. 18 | Otherwise, use the latest stable tag or the "bleeding edge" from Github. 19 | 20 | .. _`github archive`: https://github.com/behave/behave/tags 21 | -------------------------------------------------------------------------------- /behave-parallel/VERSION.txt: -------------------------------------------------------------------------------- 1 | 1.2.4a1 2 | -------------------------------------------------------------------------------- /behave-parallel/behave.ini: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # BEHAVE CONFIGURATION 3 | # ============================================================================= 4 | # FILE: .behaverc, behave.ini 5 | # 6 | # SEE ALSO: 7 | # * http://packages.python.org/behave/behave.html#configuration-files 8 | # * https://github.com/behave/behave 9 | # * http://pypi.python.org/pypi/behave/ 10 | # ============================================================================= 11 | 12 | [behave] 13 | show_skipped = false 14 | format = rerun 15 | outfiles = rerun.featureset 16 | # logging_level = INFO 17 | # logging_format = LOG.%(levelname)-8s %(name)-10s: %(message)s 18 | # logging_format = LOG.%(levelname)-8s %(asctime)s %(name)-10s: %(message)s 19 | -------------------------------------------------------------------------------- /behave-parallel/behave/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | '''behave is behaviour-driven development, Python style 3 | 4 | Behavior-driven development (or BDD) is an agile software development 5 | technique that encourages collaboration between developers, QA and 6 | non-technical or business participants in a software project. 7 | 8 | *behave* uses tests written in a natural language style, backed up by Python 9 | code. 10 | 11 | To get started, we recommend the `tutorial`_ and then the `test language`_ and 12 | `api`_ references. 13 | 14 | .. _`tutorial`: tutorial.html 15 | .. _`test language`: gherkin.html 16 | .. _`api`: api.html 17 | ''' 18 | 19 | __version__ = '1.2.4a1' 20 | 21 | from behave.step_registry import * 22 | from behave.matchers import step_matcher 23 | 24 | names = 'given when then step' 25 | names = names + ' ' + names.title() 26 | names = names + ' step_matcher' 27 | __all__ = names.split() 28 | -------------------------------------------------------------------------------- /behave-parallel/behave/compat/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Used for behave as compatibility layer between different Python versions 4 | and implementations. 5 | """ -------------------------------------------------------------------------------- /behave-parallel/behave/compat/collections.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Compatibility of :module:`collections` between different Python versions. 4 | """ 5 | 6 | from __future__ import absolute_import 7 | import warnings 8 | 9 | try: 10 | # -- SINCE: Python2.7 11 | from collections import OrderedDict 12 | except ImportError: # pragma: no cover 13 | try: 14 | # -- BACK-PORTED FOR: Python 2.4 .. 2.6 15 | from ordereddict import OrderedDict 16 | except ImportError: 17 | message = "collections.OrderedDict is missing: Install 'ordereddict'." 18 | warnings.warn(message) 19 | # -- BACKWARD-COMPATIBLE: Better than nothing (for behave use case). 20 | OrderedDict = dict 21 | -------------------------------------------------------------------------------- /behave-parallel/behave/compat/importlib.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | importlib was introduced in python2.7, python3.2... 4 | """ 5 | 6 | try: 7 | from importlib import import_module 8 | except ImportError: 9 | """Backport of importlib.import_module from 3.x.""" 10 | # While not critical (and in no way guaranteed!), it would be nice to keep this 11 | # code compatible with Python 2.3. 12 | import sys 13 | 14 | def _resolve_name(name, package, level): 15 | """Return the absolute name of the module to be imported.""" 16 | if not hasattr(package, 'rindex'): 17 | raise ValueError("'package' not set to a string") 18 | dot = len(package) 19 | for x in xrange(level, 1, -1): 20 | try: 21 | dot = package.rindex('.', 0, dot) 22 | except ValueError: 23 | raise ValueError("attempted relative import beyond top-level " 24 | "package") 25 | return "%s.%s" % (package[:dot], name) 26 | 27 | 28 | def import_module(name, package=None): 29 | """Import a module. 30 | 31 | The 'package' argument is required when performing a relative import. It 32 | specifies the package to use as the anchor point from which to resolve the 33 | relative import to an absolute import. 34 | 35 | """ 36 | if name.startswith('.'): 37 | if not package: 38 | raise TypeError("relative imports require the 'package' argument") 39 | level = 0 40 | for character in name: 41 | if character != '.': 42 | break 43 | level += 1 44 | name = _resolve_name(name[level:], package, level) 45 | __import__(name) 46 | return sys.modules[name] 47 | -------------------------------------------------------------------------------- /behave-parallel/behave/compat/os_path.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Compatibility of :module:`os.path` between different Python versions. 4 | """ 5 | 6 | import os.path 7 | 8 | relpath = getattr(os.path, "relpath", None) 9 | if relpath is None: # pragma: no cover 10 | # -- Python2.5 doesn't know about relpath 11 | def relpath(path, start=os.path.curdir): 12 | """ 13 | Return a relative version of a path 14 | BASED-ON: Python2.7 15 | """ 16 | if not path: 17 | raise ValueError("no path specified") 18 | 19 | start_list = [x for x in os.path.abspath(start).split(os.path.sep) if x] 20 | path_list = [x for x in os.path.abspath(path).split(os.path.sep) if x] 21 | # Work out how much of the filepath is shared by start and path. 22 | i = len(os.path.commonprefix([start_list, path_list])) 23 | 24 | rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:] 25 | if not rel_list: 26 | return os.path.curdir 27 | return os.path.join(*rel_list) 28 | -------------------------------------------------------------------------------- /behave-parallel/behave/formatter/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sauce-archives/Python-Behave-Appium-Android/8477d99c14dc8331d2f8b1824f0b02fcc9c82b42/behave-parallel/behave/formatter/__init__.py -------------------------------------------------------------------------------- /behave-parallel/behave/formatter/ansi_escapes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Provides ANSI escape sequences for coloring/formatting output in ANSI terminals. 4 | """ 5 | 6 | import os 7 | import re 8 | 9 | colors = { 10 | 'black': u"\x1b[30m", 11 | 'red': u"\x1b[31m", 12 | 'green': u"\x1b[32m", 13 | 'yellow': u"\x1b[33m", 14 | 'blue': u"\x1b[34m", 15 | 'magenta': u"\x1b[35m", 16 | 'cyan': u"\x1b[36m", 17 | 'white': u"\x1b[37m", 18 | 'grey': u"\x1b[90m", 19 | 'bold': u"\x1b[1m", 20 | } 21 | 22 | aliases = { 23 | 'undefined': 'yellow', 24 | 'pending': 'yellow', 25 | 'executing': 'grey', 26 | 'failed': 'red', 27 | 'passed': 'green', 28 | 'outline': 'cyan', 29 | 'skipped': 'cyan', 30 | 'comments': 'grey', 31 | 'tag': 'cyan', 32 | } 33 | 34 | escapes = { 35 | 'reset': u'\x1b[0m', 36 | 'up': u'\x1b[1A', 37 | } 38 | 39 | if 'GHERKIN_COLORS' in os.environ: 40 | new_aliases = [p.split('=') for p in os.environ['GHERKIN_COLORS'].split(':')] 41 | aliases.update(dict(new_aliases)) 42 | 43 | for alias in aliases: 44 | escapes[alias] = ''.join([colors[c] for c in aliases[alias].split(',')]) 45 | arg_alias = alias + '_arg' 46 | arg_seq = aliases.get(arg_alias, aliases[alias] + ',bold') 47 | escapes[arg_alias] = ''.join([colors[c] for c in arg_seq.split(',')]) 48 | 49 | 50 | def up(n): 51 | return u"\x1b[%dA" % n 52 | 53 | _ANSI_ESCAPE_PATTERN = re.compile(u"\x1b\[\d+[mA]", re.UNICODE) 54 | def strip_escapes(text): 55 | """ 56 | Removes ANSI escape sequences from text (if any are contained). 57 | 58 | :param text: Text that may or may not contain ANSI escape sequences. 59 | :return: Text without ANSI escape sequences. 60 | """ 61 | return _ANSI_ESCAPE_PATTERN.sub("", text) 62 | 63 | 64 | def use_ansi_escape_colorbold_composites(): # pragma: no cover 65 | """ 66 | Patch for "sphinxcontrib-ansi" to process the following ANSI escapes 67 | correctly (set-color set-bold sequences): 68 | 69 | ESC[{color}mESC[1m => ESC[{color};1m 70 | 71 | Reapply aliases to ANSI escapes mapping. 72 | """ 73 | global escapes 74 | color_codes = {} 75 | for color_name, color_escape in colors.items(): 76 | color_code = color_escape.replace(u"\x1b[", u"").replace(u"m", u"") 77 | color_codes[color_name] = color_code 78 | 79 | for alias in aliases: 80 | parts = [ color_codes[c] for c in aliases[alias].split(',') ] 81 | composite_escape = u"\x1b[{0}m".format(u";".join(parts)) 82 | escapes[alias] = composite_escape 83 | 84 | arg_alias = alias + '_arg' 85 | arg_seq = aliases.get(arg_alias, aliases[alias] + ',bold') 86 | parts = [ color_codes[c] for c in arg_seq.split(',') ] 87 | composite_escape = u"\x1b[{0}m".format(u";".join(parts)) 88 | escapes[arg_alias] = composite_escape 89 | -------------------------------------------------------------------------------- /behave-parallel/behave/formatter/filters.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # FIXME: 3 | __status__ = "DEAD, BROKEN" 4 | 5 | from gherkin.tag_expression import TagExpression 6 | 7 | 8 | class LineFilter(object): 9 | def __init__(self, lines): 10 | self.lines = lines 11 | 12 | def eval(self, tags, names, ranges): 13 | for r in ranges: 14 | for line in self.lines: 15 | if r[0] <= line <= r[1]: 16 | return True 17 | return False 18 | 19 | def filter_table_body_rows(self, rows): 20 | body = [r for r in rows[1:] if r.line in self.lines] 21 | return [rows[0]] + body 22 | 23 | 24 | class RegexpFilter(object): 25 | def __init__(self, regexen): 26 | self.regexen = regexen 27 | 28 | def eval(self, tags, names, ranges): 29 | for regex in self.regexen: 30 | for name in names: 31 | if regex.search(name): 32 | return True 33 | return False 34 | 35 | def filter_table_body_rows(self, rows): 36 | return rows 37 | 38 | 39 | class TagFilter(object): 40 | def __init__(self, tags): 41 | self.tag_expression = TagExpression(tags) 42 | 43 | def eval(self, tags, names, ranges): 44 | return self.tag_expression.eval([tag.name for tag in set(tags)]) 45 | 46 | def filter_table_body_rows(self, rows): 47 | return rows 48 | -------------------------------------------------------------------------------- /behave-parallel/behave/formatter/formatters.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import sys 4 | from behave.formatter.base import StreamOpener 5 | from behave.textutil import compute_words_maxsize 6 | from behave.importer import LazyDict, LazyObject 7 | 8 | 9 | # ----------------------------------------------------------------------------- 10 | # FORMATTER REGISTRY: 11 | # ----------------------------------------------------------------------------- 12 | formatters = LazyDict() 13 | 14 | 15 | def register_as(formatter_class, name): 16 | """ 17 | Register formatter class with given name. 18 | 19 | :param formatter_class: Formatter class to register. 20 | :param name: Name for this formatter (as identifier). 21 | """ 22 | formatters[name] = formatter_class 23 | 24 | def register(formatter_class): 25 | register_as(formatter_class, formatter_class.name) 26 | 27 | 28 | def list_formatters(stream): 29 | """ 30 | Writes a list of the available formatters and their description to stream. 31 | 32 | :param stream: Output stream to use. 33 | """ 34 | formatter_names = sorted(formatters) 35 | column_size = compute_words_maxsize(formatter_names) 36 | schema = u" %-"+ str(column_size) +"s %s\n" 37 | for name in formatter_names: 38 | stream.write(schema % (name, formatters[name].description)) 39 | 40 | 41 | def get_formatter(config, stream_openers): 42 | # -- BUILD: Formatter list 43 | default_stream_opener = StreamOpener(stream=sys.stdout) 44 | formatter_list = [] 45 | for i, name in enumerate(config.format): 46 | stream_opener = default_stream_opener 47 | if i < len(stream_openers): 48 | stream_opener = stream_openers[i] 49 | formatter_list.append(formatters[name](stream_opener, config)) 50 | return formatter_list 51 | 52 | 53 | # ----------------------------------------------------------------------------- 54 | # SETUP: 55 | # ----------------------------------------------------------------------------- 56 | def setup_formatters(): 57 | # -- NOTE: Use lazy imports for formatters (to speed up start-up time). 58 | _L = LazyObject 59 | register_as(_L("behave.formatter.plain:PlainFormatter"), "plain") 60 | register_as(_L("behave.formatter.pretty:PrettyFormatter"), "pretty") 61 | register_as(_L("behave.formatter.json:JSONFormatter"), "json") 62 | register_as(_L("behave.formatter.json:PrettyJSONFormatter"), "json.pretty") 63 | register_as(_L("behave.formatter.null:NullFormatter"), "null") 64 | register_as(_L("behave.formatter.progress:ScenarioProgressFormatter"), 65 | "progress") 66 | register_as(_L("behave.formatter.progress:StepProgressFormatter"), 67 | "progress2") 68 | register_as(_L("behave.formatter.progress:ScenarioStepProgressFormatter"), 69 | "progress3") 70 | register_as(_L("behave.formatter.rerun:RerunFormatter"), "rerun") 71 | register_as(_L("behave.formatter.tags:TagsFormatter"), "tags") 72 | register_as(_L("behave.formatter.tags:TagsLocationFormatter"), 73 | "tags.location") 74 | register_as(_L("behave.formatter.steps:StepsFormatter"), "steps") 75 | register_as(_L("behave.formatter.steps:StepsDocFormatter"), "steps.doc") 76 | register_as(_L("behave.formatter.steps:StepsUsageFormatter"), "steps.usage") 77 | register_as(_L("behave.formatter.sphinx_steps:SphinxStepsFormatter"), 78 | "sphinx.steps") 79 | 80 | 81 | # ----------------------------------------------------------------------------- 82 | # MODULE-INIT: 83 | # ----------------------------------------------------------------------------- 84 | setup_formatters() 85 | -------------------------------------------------------------------------------- /behave-parallel/behave/formatter/null.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from behave.formatter.base import Formatter 4 | 5 | class NullFormatter(Formatter): 6 | """ 7 | Provides formatter that does not output anything. 8 | Implements the NULL pattern for a formatter (similar like: /dev/null). 9 | """ 10 | name = "null" 11 | description = "Provides formatter that does not output anything." 12 | -------------------------------------------------------------------------------- /behave-parallel/behave/importer.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Importer module for lazy-loading/importing modules and objects. 4 | 5 | REQUIRES: importlib (provided in Python2.7, Python3.2...) 6 | """ 7 | 8 | from behave.compat import importlib 9 | 10 | 11 | class Unknown(object): 12 | pass 13 | 14 | 15 | class LazyObject(object): 16 | """ 17 | Provides a placeholder for an object that should be loaded lazily. 18 | """ 19 | 20 | def __init__(self, module_name, object_name=None): 21 | if ":" in module_name and not object_name: 22 | module_name, object_name = module_name.split(":") 23 | assert ":" not in module_name 24 | self.module_name = module_name 25 | self.object_name = object_name 26 | self.obj = None 27 | 28 | @staticmethod 29 | def load_module(module_name): 30 | return importlib.import_module(module_name) 31 | 32 | def __get__(self, obj=None, type=None): 33 | """ 34 | Implement descriptor protocol, 35 | useful if this class is used as attribute. 36 | :return: Real object (lazy-loaded if necessary). 37 | :raise ImportError: If module or object cannot be imported. 38 | """ 39 | __pychecker__ = "unusednames=obj,type" 40 | if not self.obj: 41 | # -- SETUP-ONCE: Lazy load the real object. 42 | module = self.load_module(self.module_name) 43 | obj = getattr(module, self.object_name, Unknown) 44 | if obj is Unknown: 45 | msg = "%s: %s is Unknown" % (self.module_name, self.object_name) 46 | raise ImportError(msg) 47 | self.obj = obj 48 | return obj 49 | 50 | def __set__(self, obj, value): 51 | """ 52 | Implement descriptor protocol. 53 | """ 54 | __pychecker__ = "unusednames=obj" 55 | self.obj = value 56 | 57 | def get(self): 58 | return self.__get__() 59 | 60 | 61 | class LazyDict(dict): 62 | """ 63 | Provides a dict that supports lazy loading of objects. 64 | A LazyObject is provided as placeholder for a value that should be 65 | loaded lazily. 66 | """ 67 | 68 | def __getitem__(self, key): 69 | """ 70 | Provides access to stored dict values. 71 | Implements lazy loading of item value (if necessary). 72 | When lazy object is loaded, its value with the dict is replaced 73 | with the real value. 74 | 75 | :param key: Key to access the value of an item in the dict. 76 | :return: value 77 | :raises: KeyError if item is not found 78 | :raises: ImportError for a LazyObject that cannot be imported. 79 | """ 80 | value = dict.__getitem__(self, key) 81 | if isinstance(value, LazyObject): 82 | # -- LAZY-LOADING MECHANISM: Load object and replace with lazy one. 83 | value = value.__get__() 84 | self[key] = value 85 | return value 86 | -------------------------------------------------------------------------------- /behave-parallel/behave/reporter/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sauce-archives/Python-Behave-Appium-Android/8477d99c14dc8331d2f8b1824f0b02fcc9c82b42/behave-parallel/behave/reporter/__init__.py -------------------------------------------------------------------------------- /behave-parallel/behave/reporter/base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | class Reporter(object): 4 | """ 5 | Base class for all reporters. 6 | A reporter provides an extension point (variant point) for the runner logic. 7 | A reporter is called after a model element is processed 8 | (and its result status is known). 9 | Otherwise, a reporter is similar to a formatter, but it has a simpler API. 10 | 11 | Processing Logic (simplified):: 12 | 13 | config.reporters = ... #< Configuration (and provision). 14 | runner.run(): 15 | for feature in runner.features: 16 | feature.run() # And feature scenarios, too. 17 | for reporter in config.reporters: 18 | reporter.feature(feature) 19 | # -- FINALLY: 20 | for reporter in config.reporters: 21 | reporter.end() 22 | 23 | An existing formatter can be reused as reporter by using 24 | :class:`behave.report.formatter_reporter.FormatterAsReporter`. 25 | """ 26 | def __init__(self, config): 27 | self.config = config 28 | 29 | def feature(self, feature): 30 | """ 31 | Called after a feature was processed. 32 | 33 | :param feature: Feature object (as :class:`behave.model.Feature`) 34 | """ 35 | assert feature.status in ("skipped", "passed", "failed") 36 | raise NotImplementedError 37 | 38 | def end(self): 39 | """ 40 | Called after all model elements are processed (optional-hook). 41 | """ 42 | pass 43 | -------------------------------------------------------------------------------- /behave-parallel/behave/reporter/summary.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | """ 3 | Provides a summary after each test run. 4 | """ 5 | 6 | import sys 7 | from behave.model import ScenarioOutline 8 | from behave.reporter.base import Reporter 9 | 10 | 11 | # -- DISABLED: optional_steps = ('untested', 'undefined') 12 | optional_steps = ('untested',) 13 | 14 | 15 | def format_summary(statement_type, summary): 16 | parts = [] 17 | for status in ('passed', 'failed', 'skipped', 'undefined', 'untested'): 18 | if status not in summary: 19 | continue 20 | counts = summary[status] 21 | if status in optional_steps and counts == 0: 22 | # -- SHOW-ONLY: For relevant counts, suppress: untested items, etc. 23 | continue 24 | 25 | if not parts: 26 | # -- FIRST ITEM: Add statement_type to counter. 27 | label = statement_type 28 | if counts != 1: 29 | label += 's' 30 | part = '%d %s %s' % (counts, label, status) 31 | else: 32 | part = '%d %s' % (counts, status) 33 | parts.append(part) 34 | return ', '.join(parts) + '\n' 35 | 36 | 37 | class SummaryReporter(Reporter): 38 | show_failed_scenarios = True 39 | output_stream_name = "stdout" 40 | 41 | def __init__(self, config): 42 | super(SummaryReporter, self).__init__(config) 43 | self.stream = getattr(sys, self.output_stream_name, sys.stderr) 44 | self.feature_summary = {'passed': 0, 'failed': 0, 'skipped': 0, 45 | 'untested': 0} 46 | self.scenario_summary = {'passed': 0, 'failed': 0, 'skipped': 0, 47 | 'untested': 0} 48 | self.step_summary = {'passed': 0, 'failed': 0, 'skipped': 0, 49 | 'undefined': 0, 'untested': 0} 50 | self.duration = 0.0 51 | self.failed_scenarios = [] 52 | 53 | def feature(self, feature): 54 | self.feature_summary[feature.status or 'skipped'] += 1 55 | self.duration += feature.duration 56 | for scenario in feature: 57 | if isinstance(scenario, ScenarioOutline): 58 | self.process_scenario_outline(scenario) 59 | else: 60 | self.process_scenario(scenario) 61 | 62 | def end(self): 63 | # -- SHOW FAILED SCENARIOS (optional): 64 | if self.show_failed_scenarios and self.failed_scenarios: 65 | self.stream.write("\nFailing scenarios:\n") 66 | for scenario in self.failed_scenarios: 67 | self.stream.write(" %s %s\n" % ( 68 | scenario.location, scenario.name)) 69 | self.stream.write("\n") 70 | 71 | # -- SHOW SUMMARY COUNTS: 72 | self.stream.write(format_summary('feature', self.feature_summary)) 73 | self.stream.write(format_summary('scenario', self.scenario_summary)) 74 | self.stream.write(format_summary('step', self.step_summary)) 75 | timings = int(self.duration / 60), self.duration % 60 76 | self.stream.write('Took %dm%02.3fs\n' % timings) 77 | 78 | def process_scenario(self, scenario): 79 | if scenario.status == 'failed': 80 | self.failed_scenarios.append(scenario) 81 | self.scenario_summary[scenario.status or 'skipped'] += 1 82 | for step in scenario: 83 | self.step_summary[step.status or 'skipped'] += 1 84 | 85 | def process_scenario_outline(self, scenario_outline): 86 | for scenario in scenario_outline.scenarios: 87 | self.process_scenario(scenario) 88 | -------------------------------------------------------------------------------- /behave-parallel/behave/tag_expression.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | class TagExpression(object): 5 | def __init__(self, tag_expressions): 6 | self.ands = [] 7 | self.limits = {} 8 | 9 | for expr in tag_expressions: 10 | self.add([e.strip() for e in expr.strip().split(',')]) 11 | 12 | def check(self, tags): 13 | if not self.ands: 14 | return True 15 | 16 | params = set(tags) 17 | 18 | def test_tag(tag): 19 | if tag.startswith('-') or tag.startswith('~'): 20 | return tag[1:] not in params 21 | return tag in params 22 | 23 | return all(any(test_tag(tag) for tag in ors) for ors in self.ands) 24 | 25 | def add(self, tags): 26 | negatives = [] 27 | positives = [] 28 | 29 | for tag in tags: 30 | if tag.startswith('@'): 31 | positives.append(tag[1:]) 32 | elif tag.startswith('-@') or tag.startswith('~@'): 33 | negatives.append('-' + tag[2:]) 34 | elif tag.startswith('-') or tag.startswith('~'): 35 | negatives.append(tag) 36 | else: 37 | positives.append(tag) 38 | 39 | self.store_and_extract_limits(negatives, True) 40 | self.store_and_extract_limits(positives, False) 41 | 42 | def store_and_extract_limits(self, tags, negated): 43 | tags_with_negation = [] 44 | 45 | for tag in tags: 46 | tag = tag.split(':') 47 | tag_with_negation = tag.pop(0) 48 | tags_with_negation.append(tag_with_negation) 49 | 50 | if tag: 51 | limit = int(tag[0]) 52 | if negated: 53 | tag_without_negation = tag_with_negation[1:] 54 | else: 55 | tag_without_negation = tag_with_negation 56 | limited = tag_without_negation in self.limits 57 | if limited and self.limits[tag_without_negation] != limit: 58 | msg = "Inconsistent tag limits for {0}: {1:d} and {2:d}" 59 | msg = msg.format(tag_without_negation, 60 | self.limits[tag_without_negation], limit) 61 | raise Exception(msg) 62 | self.limits[tag_without_negation] = limit 63 | 64 | if tags_with_negation: 65 | self.ands.append(tags_with_negation) 66 | 67 | def __len__(self): 68 | return len(self.ands) 69 | -------------------------------------------------------------------------------- /behave-parallel/behave/textutil.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Provides some utility functions related to text processing. 4 | """ 5 | 6 | 7 | def make_indentation(indent_size, part=u" "): 8 | """ 9 | Creates an indentation prefix string of the given size. 10 | """ 11 | return indent_size * part 12 | 13 | 14 | def indent(text, prefix): 15 | """ 16 | Indent text or a number of text lines (with newline). 17 | 18 | :param lines: Text lines to indent (as string or list of strings). 19 | :param prefix: Line prefix to use (as string). 20 | :return: Indented text (as unicode string). 21 | """ 22 | lines = text 23 | newline = u"" 24 | if isinstance(text, basestring): 25 | lines = text.splitlines(True) 26 | elif lines and not lines[0].endswith("\n"): 27 | # -- TEXT LINES: Without trailing new-line. 28 | newline = u"\n" 29 | return newline.join([prefix + unicode(line) for line in lines]) 30 | 31 | 32 | def compute_words_maxsize(words): 33 | """ 34 | Compute the maximum word size from a list of words (or strings). 35 | 36 | :param words: List of words (or strings) to use. 37 | :return: Maximum size of all words. 38 | """ 39 | max_size = 0 40 | for word in words: 41 | if len(word) > max_size: 42 | max_size = len(word) 43 | return max_size 44 | -------------------------------------------------------------------------------- /behave-parallel/behave4cmd0/__all_steps__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Import all step definitions of this step-library. 4 | Step definitions are automatically registered in "behave.step_registry". 5 | """ 6 | 7 | # -- IMPORT STEP-LIBRARY: behave4cmd0 8 | import behave4cmd0.command_steps 9 | import behave4cmd0.note_steps 10 | import behave4cmd0.log.steps 11 | -------------------------------------------------------------------------------- /behave-parallel/behave4cmd0/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Predecessor of behave4cmd library. 4 | Currently used to provide self-tests for behave. 5 | """ 6 | -------------------------------------------------------------------------------- /behave-parallel/behave4cmd0/__setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os.path 4 | 5 | # ----------------------------------------------------------------------------- 6 | # CONSTANTS: 7 | # ----------------------------------------------------------------------------- 8 | HERE = os.path.dirname(__file__) 9 | TOP = os.path.join(HERE, "..") 10 | TOPA = os.path.abspath(TOP) 11 | -------------------------------------------------------------------------------- /behave-parallel/behave4cmd0/failing_steps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Generic failing steps. 4 | Often needed in examples. 5 | 6 | EXAMPLES: 7 | 8 | Given a step fails 9 | When another step fails 10 | Then a step fails 11 | 12 | Given ... 13 | When ... 14 | Then it should fail because "the person is unknown". 15 | """ 16 | 17 | from behave import step, then 18 | 19 | # ----------------------------------------------------------------------------- 20 | # STEPS FOR: failing 21 | # ----------------------------------------------------------------------------- 22 | @step('{word:w} step fails') 23 | def step_fails(context, word): 24 | """ 25 | Step that always fails, mostly needed in examples. 26 | """ 27 | assert False, "EXPECT: Failing step" 28 | 29 | @then(u'it should fail because "{reason}"') 30 | def then_it_should_fail_because(context, reason): 31 | """ 32 | Self documenting step that indicates why this step should fail. 33 | """ 34 | assert False, "FAILED: %s" % reason 35 | 36 | # @step(u'an error should fail because "{reason}"') 37 | # def then_it_should_fail_because(context, reason): 38 | # """ 39 | # Self documenting step that indicates why this step should fail. 40 | # """ 41 | # assert False, reason -------------------------------------------------------------------------------- /behave-parallel/behave4cmd0/log/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'jens' 2 | -------------------------------------------------------------------------------- /behave-parallel/behave4cmd0/note_steps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Step definitions for providing notes/hints. 4 | The note steps explain what was important in the last few steps of 5 | this scenario (for a test reader). 6 | """ 7 | 8 | from behave import step 9 | 10 | 11 | # ----------------------------------------------------------------------------- 12 | # STEPS FOR: remarks/comments 13 | # ----------------------------------------------------------------------------- 14 | @step(u'note that "{remark}"') 15 | def step_note_that(context, remark): 16 | """ 17 | Used as generic step that provides an additional remark/hint 18 | and enhance the readability/understanding without performing any check. 19 | 20 | .. code-block:: gherkin 21 | 22 | Given that today is "April 1st" 23 | But note that "April 1st is Fools day (and beware)" 24 | """ 25 | log = getattr(context, "log", None) 26 | if log: 27 | log.info(u"NOTE: %s;" % remark) 28 | 29 | -------------------------------------------------------------------------------- /behave-parallel/behave4cmd0/passing_steps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Passing steps. 4 | Often needed in examples. 5 | 6 | EXAMPLES: 7 | 8 | Given a step passes 9 | When another step passes 10 | Then a step passes 11 | 12 | Given ... 13 | When ... 14 | Then it should pass because "the answer is correct". 15 | """ 16 | 17 | from behave import step, then 18 | 19 | # ----------------------------------------------------------------------------- 20 | # STEPS FOR: passing 21 | # ----------------------------------------------------------------------------- 22 | @step('{word:w} step passes') 23 | def step_passes(context, word): 24 | """ 25 | Step that always fails, mostly needed in examples. 26 | """ 27 | pass 28 | 29 | @then('it should pass because "{reason}"') 30 | def then_it_should_pass_because(context, reason): 31 | """ 32 | Self documenting step that indicates some reason. 33 | """ 34 | pass 35 | 36 | -------------------------------------------------------------------------------- /behave-parallel/bin/behave: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # -- ENSURE: Use local path during development. 4 | import sys 5 | import os.path 6 | 7 | # ---------------------------------------------------------------------------- 8 | # SETUP PATHS: 9 | # ---------------------------------------------------------------------------- 10 | NAME = "behave" 11 | HERE = os.path.dirname(__file__) 12 | TOP = os.path.join(HERE, "..") 13 | if os.path.isdir(os.path.join(TOP, NAME)): 14 | sys.path.insert(0, os.path.abspath(TOP)) 15 | 16 | # ---------------------------------------------------------------------------- 17 | # BEHAVE-TWEAKS: 18 | # ---------------------------------------------------------------------------- 19 | def setup_behave(): 20 | """ 21 | Apply tweaks, extensions and patches to "behave". 22 | """ 23 | from behave.configuration import Configuration 24 | # -- DISABLE: Timings to simplify issue.features/ tests. 25 | # Configuration.defaults["format0"] = "pretty" 26 | # Configuration.defaults["format0"] = "progress" 27 | Configuration.defaults["show_timings"] = False 28 | 29 | def behave_main0(): 30 | # from behave.configuration import Configuration 31 | from behave.__main__ import main as behave_main 32 | setup_behave() 33 | return behave_main() 34 | 35 | # ---------------------------------------------------------------------------- 36 | # MAIN: 37 | # ---------------------------------------------------------------------------- 38 | if __name__ == "__main__": 39 | if os.environ.has_key("COVERAGE_PROCESS_START"): 40 | import coverage 41 | coverage.process_startup() 42 | sys.exit(behave_main0()) 43 | -------------------------------------------------------------------------------- /behave-parallel/bin/behave.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM ========================================================================== 3 | REM BEHAVE 4 | REM ========================================================================== 5 | 6 | setlocal 7 | set HERE=%~dp0 8 | if not defined PYTHON set PYTHON=python 9 | 10 | %PYTHON% %HERE%behave %* 11 | -------------------------------------------------------------------------------- /behave-parallel/docs/_static/behave_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sauce-archives/Python-Behave-Appium-Android/8477d99c14dc8331d2f8b1824f0b02fcc9c82b42/behave-parallel/docs/_static/behave_logo.png -------------------------------------------------------------------------------- /behave-parallel/docs/_static/behave_logo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sauce-archives/Python-Behave-Appium-Android/8477d99c14dc8331d2f8b1824f0b02fcc9c82b42/behave-parallel/docs/_static/behave_logo1.png -------------------------------------------------------------------------------- /behave-parallel/docs/_static/behave_logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sauce-archives/Python-Behave-Appium-Android/8477d99c14dc8331d2f8b1824f0b02fcc9c82b42/behave-parallel/docs/_static/behave_logo2.png -------------------------------------------------------------------------------- /behave-parallel/docs/_static/behave_logo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sauce-archives/Python-Behave-Appium-Android/8477d99c14dc8331d2f8b1824f0b02fcc9c82b42/behave-parallel/docs/_static/behave_logo3.png -------------------------------------------------------------------------------- /behave-parallel/docs/_themes/LICENSE: -------------------------------------------------------------------------------- 1 | Modifications: 2 | 3 | Copyright (c) 2011 Kenneth Reitz. 4 | 5 | 6 | Original Project: 7 | 8 | Copyright (c) 2010 by Armin Ronacher. 9 | 10 | 11 | Some rights reserved. 12 | 13 | Redistribution and use in source and binary forms of the theme, with or 14 | without modification, are permitted provided that the following conditions 15 | are met: 16 | 17 | * Redistributions of source code must retain the above copyright 18 | notice, this list of conditions and the following disclaimer. 19 | 20 | * Redistributions in binary form must reproduce the above 21 | copyright notice, this list of conditions and the following 22 | disclaimer in the documentation and/or other materials provided 23 | with the distribution. 24 | 25 | * The names of the contributors may not be used to endorse or 26 | promote products derived from this software without specific 27 | prior written permission. 28 | 29 | We kindly ask you to only use these themes in an unmodified manner just 30 | for Flask and Flask-related products, not for unrelated projects. If you 31 | like the visual style and want to use it for your own projects, please 32 | consider making some larger changes to the themes (such as changing 33 | font faces, sizes, colors or margins). 34 | 35 | THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 36 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 39 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 40 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 41 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 42 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 43 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 | ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE 45 | POSSIBILITY OF SUCH DAMAGE. 46 | -------------------------------------------------------------------------------- /behave-parallel/docs/_themes/kr/layout.html: -------------------------------------------------------------------------------- 1 | {%- extends "basic/layout.html" %} 2 | {%- block extrahead %} 3 | {{ super() }} 4 | {% if theme_touch_icon %} 5 | 6 | {% endif %} 7 | 8 | {% endblock %} 9 | {%- block relbar2 %}{% endblock %} 10 | {%- block footer %} 11 | 14 | 15 | Fork me on GitHub 16 | 17 | {%- endblock %} 18 | -------------------------------------------------------------------------------- /behave-parallel/docs/_themes/kr/relations.html: -------------------------------------------------------------------------------- 1 |

Related Topics

2 | 20 | -------------------------------------------------------------------------------- /behave-parallel/docs/_themes/kr/static/small_flask.css: -------------------------------------------------------------------------------- 1 | /* 2 | * small_flask.css_t 3 | * ~~~~~~~~~~~~~~~~~ 4 | * 5 | * :copyright: Copyright 2010 by Armin Ronacher. 6 | * :license: Flask Design License, see LICENSE for details. 7 | */ 8 | 9 | body { 10 | margin: 0; 11 | padding: 20px 30px; 12 | } 13 | 14 | div.documentwrapper { 15 | float: none; 16 | background: white; 17 | } 18 | 19 | div.sphinxsidebar { 20 | display: block; 21 | float: none; 22 | width: 102.5%; 23 | margin: 50px -30px -20px -30px; 24 | padding: 10px 20px; 25 | background: #333; 26 | color: white; 27 | } 28 | 29 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, 30 | div.sphinxsidebar h3 a { 31 | color: white; 32 | } 33 | 34 | div.sphinxsidebar a { 35 | color: #aaa; 36 | } 37 | 38 | div.sphinxsidebar p.logo { 39 | display: none; 40 | } 41 | 42 | div.document { 43 | width: 100%; 44 | margin: 0; 45 | } 46 | 47 | div.related { 48 | display: block; 49 | margin: 0; 50 | padding: 10px 0 20px 0; 51 | } 52 | 53 | div.related ul, 54 | div.related ul li { 55 | margin: 0; 56 | padding: 0; 57 | } 58 | 59 | div.footer { 60 | display: none; 61 | } 62 | 63 | div.bodywrapper { 64 | margin: 0; 65 | } 66 | 67 | div.body { 68 | min-height: 0; 69 | padding: 0; 70 | } 71 | 72 | .rtd_doc_footer { 73 | display: none; 74 | } 75 | 76 | .document { 77 | width: auto; 78 | } 79 | 80 | .footer { 81 | width: auto; 82 | } 83 | 84 | .footer { 85 | width: auto; 86 | } 87 | 88 | .github { 89 | display: none; 90 | } -------------------------------------------------------------------------------- /behave-parallel/docs/_themes/kr/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | stylesheet = flasky.css 4 | pygments_style = flask_theme_support.FlaskyStyle 5 | 6 | [options] 7 | touch_icon = 8 | -------------------------------------------------------------------------------- /behave-parallel/docs/_themes/kr_small/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "basic/layout.html" %} 2 | {% block header %} 3 | {{ super() }} 4 | {% if pagename == 'index' %} 5 |
6 | {% endif %} 7 | {% endblock %} 8 | {% block footer %} 9 | {% if pagename == 'index' %} 10 |
11 | {% endif %} 12 | {% endblock %} 13 | {# do not display relbars #} 14 | {% block relbar1 %}{% endblock %} 15 | {% block relbar2 %} 16 | {% if theme_github_fork %} 17 | Fork me on GitHub 19 | {% endif %} 20 | {% endblock %} 21 | {% block sidebar1 %}{% endblock %} 22 | {% block sidebar2 %}{% endblock %} 23 | -------------------------------------------------------------------------------- /behave-parallel/docs/_themes/kr_small/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | stylesheet = flasky.css 4 | nosidebar = true 5 | pygments_style = flask_theme_support.FlaskyStyle 6 | 7 | [options] 8 | index_logo = '' 9 | index_logo_height = 120px 10 | github_fork = '' 11 | -------------------------------------------------------------------------------- /behave-parallel/docs/appendix.rst: -------------------------------------------------------------------------------- 1 | .. _id.appendix: 2 | 3 | ============================================================================== 4 | Appendix 5 | ============================================================================== 6 | 7 | **Contents:** 8 | 9 | .. toctree:: 10 | :maxdepth: 1 11 | 12 | formatters 13 | context_attributes 14 | parse_builtin_types 15 | regular_expressions 16 | test_domains 17 | behave_ecosystem 18 | related 19 | 20 | -------------------------------------------------------------------------------- /behave-parallel/docs/behave.rst-template: -------------------------------------------------------------------------------- 1 | ============== 2 | *behave* usage 3 | ============== 4 | 5 | The command-line tool *behave* has a bunch of `command-line arguments`_ and is 6 | also configurable using `configuration files`_. 7 | 8 | Values defined in the configuration files are used as defaults which the 9 | command-line arguments may override. 10 | 11 | 12 | Command-Line Arguments 13 | ====================== 14 | 15 | You may see the same information presented below at any time using ``behave 16 | -h``. 17 | 18 | {cmdline} 19 | 20 | 21 | Tag Expression 22 | -------------- 23 | 24 | {tag_expression} 25 | 26 | 27 | Configuration Files 28 | =================== 29 | 30 | Configuration files for *behave* are called either ".behaverc" or 31 | "behave.ini" (your preference) and are located in one of three places: 32 | 33 | 1. the current working directory (good for per-project settings), 34 | 2. your home directory ($HOME), or 35 | 3. on Windows, in the %APPDATA% directory. 36 | 37 | If you are wondering where *behave* is getting its configuration defaults 38 | from you can use the "-v" command-line argument and it'll tell you. 39 | 40 | Confuguration files **must** start with the label "[behave]" and are 41 | formatted in the Windows INI style, for example: 42 | 43 | .. code-block:: ini 44 | 45 | [behave] 46 | format=plain 47 | logging_clear_handlers=yes 48 | logging_filter=-suds 49 | 50 | The types possible are: 51 | 52 | **text** 53 | This just assigns whatever text you supply to the configuration setting. 54 | 55 | **boolean** 56 | This assigns a boolean value to the configuration setting. True values 57 | are "1", "yes", "true", and "on". False values are "0", "no", "false", 58 | and "off". 59 | 60 | **text (multiple allowed)** 61 | These fields accept one or more values on new lines, for example a tag 62 | expression might look like: 63 | 64 | .. code-block:: ini 65 | 66 | tags=@foo,~@bar 67 | @zap 68 | 69 | which is the equivalent of the command-line usage:: 70 | 71 | --tags @foo,~@bar --tags @zap. 72 | 73 | 74 | Recognised Settings 75 | ------------------- 76 | 77 | {config} 78 | 79 | 80 | -------------------------------------------------------------------------------- /behave-parallel/docs/behave_ecosystem.rst: -------------------------------------------------------------------------------- 1 | .. _id.appendix.behave_ecosystem: 2 | 3 | Behave Ecosystem 4 | ============================================================================== 5 | 6 | The following tools and extensions try to simplify the work with `behave`_. 7 | 8 | .. _behave: https://github.com/behave/behave 9 | 10 | 11 | Tools 12 | ------------------------------------------------------------------------------ 13 | 14 | =========================== =========================================================================== 15 | Tool Description 16 | =========================== =========================================================================== 17 | `cucutags`_ Generate `ctags`_-like information (cross-reference index) 18 | for Gherkin feature files and behave step definitions. 19 | =========================== =========================================================================== 20 | 21 | .. _cucutags: https://gitorious.org/cucutags/cucutags/ 22 | .. _ctags: http://ctags.sourceforge.net/ 23 | 24 | 25 | Editor Plugins 26 | ------------------------------------------------------------------------------ 27 | 28 | =================== ============================================================================= 29 | Editor Plugin Description 30 | =================== ============================================================================= 31 | `gedit-behave`_ `gedit`_ plugin for jumping between feature and step files. 32 | `vim-behave`_ `vim`_ plugin: Port of `vim-cucumber`_ to Python `behave`_. 33 | =================== ============================================================================= 34 | 35 | .. _gedit: https://projects.gnome.org/gedit/ 36 | .. _vim: http://www.vim.org/ 37 | 38 | .. _gedit-behave: https://gitorious.org/cucutags/gedit-behave 39 | .. _vim-behave: https://gitorious.org/cucutags/vim-behave 40 | .. _vim-cucumber: https://github.com/tpope/vim-cucumber.git 41 | 42 | 43 | -------------------------------------------------------------------------------- /behave-parallel/docs/formatters.rst: -------------------------------------------------------------------------------- 1 | .. _id.appendix.formatters: 2 | 3 | ============================================================================== 4 | Formatters and Reporters 5 | ============================================================================== 6 | 7 | `behave`_ provides 2 different concepts for reporting results of a test run: 8 | 9 | * formatters 10 | * reporters 11 | 12 | A slightly different interface is provided for each "formatter" concept. 13 | The ``Formatter`` is informed about each step that is taken. 14 | The ``Reporter`` has a more coarse-grained API. 15 | 16 | 17 | Formatters 18 | ------------------------------------------------------------------------------ 19 | 20 | The following formatters are currently supported: 21 | 22 | ============== ======== ================================================================ 23 | Name Mode Description 24 | ============== ======== ================================================================ 25 | help normal Shows all registered formatters. 26 | json normal JSON dump of test run 27 | json.pretty normal JSON dump of test run (human readable) 28 | plain normal Very basic formatter with maximum compatibility 29 | pretty normal Standard colourised pretty formatter 30 | progress normal Shows dotted progress for each executed scenario. 31 | progress2 normal Shows dotted progress for each executed step. 32 | progress3 normal Shows detailed progress for each step of a scenario. 33 | rerun normal Emits scenario file locations of failing scenarios 34 | sphinx.steps dry-run Generate sphinx-based documentation for step definitions. 35 | steps dry-run Shows step definitions (step implementations). 36 | steps.doc dry-run Shows documentation for step definitions. 37 | steps.usage dry-run Shows how step definitions are used by steps (in feature files). 38 | tags dry-run Shows tags (and how often they are used). 39 | tags.location dry-run Shows tags and the location where they are used. 40 | ============== ======== ================================================================ 41 | 42 | .. note:: 43 | 44 | You can use more that one formatter during a test run. 45 | But in general you have only one formatter that writes to ``stdout``. 46 | 47 | The "Mode" column indicates if a formatter is intended to be used in 48 | dry-run (``--dry-run`` command-line option) or normal mode. 49 | 50 | 51 | Reporters 52 | ------------------------------------------------------------------------------ 53 | 54 | The following reporters are currently supported: 55 | 56 | ============== ================================================================ 57 | Name Description 58 | ============== ================================================================ 59 | junit Provides JUnit XML-like output. 60 | summary Provides a summary of the test run. 61 | ============== ================================================================ 62 | 63 | .. _behave: http://pypi.python.org/pypi/behave 64 | -------------------------------------------------------------------------------- /behave-parallel/docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to behave! 2 | ================== 3 | 4 | .. pypi-release:: behave 5 | :prefix: Download 6 | :class: note 7 | 8 | behave is behaviour-driven development, Python style. 9 | 10 | Behavior-driven development (or BDD) is an agile software development 11 | technique that encourages collaboration between developers, QA and 12 | non-technical or business participants in a software project. We have 13 | a page further describing this `philosophy`_. 14 | 15 | *behave* uses tests written in a natural language style, backed up by Python 16 | code. 17 | 18 | Once you've `installed`_ *behave* we recommend the `tutorial`_ and then the 19 | `test setup`_ and `api`_ references, the page of `related`_ software 20 | (things that you can combine with *behave*) 21 | and finally the information on `how to use 22 | and configure`_ the *behave* tool. 23 | 24 | There is also a `comparison`_ with the other tools available. 25 | 26 | .. _`philosophy`: philosophy.html 27 | .. _`installed`: install.html 28 | .. _`tutorial`: tutorial.html 29 | .. _`test setup`: gherkin.html 30 | .. _`api`: api.html 31 | .. _`how to use and configure`: behave.html 32 | .. _`related`: related.html 33 | .. _`comparison`: comparison.html 34 | 35 | 36 | .. toctree:: 37 | :maxdepth: 2 38 | 39 | install 40 | tutorial 41 | philosophy 42 | gherkin 43 | behave 44 | api 45 | django 46 | comparison 47 | appendix 48 | 49 | 50 | Indices and tables 51 | ================== 52 | 53 | * :ref:`genindex` 54 | * :ref:`modindex` 55 | * :ref:`search` 56 | 57 | -------------------------------------------------------------------------------- /behave-parallel/docs/install.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | 4 | .. pypi-release:: behave 5 | :prefix: Download 6 | :class: note 7 | 8 | Installing *behave* is a relatively simple process if you have `pip`_ 9 | installed: 10 | 11 | pip install behave 12 | 13 | If you do not have `pip`_ installed then you might have easy_install 14 | instead. In that case just substitute "easy_install" for "pip" in the above 15 | command. 16 | 17 | If you have neither then we highly recommend you get `pip`_. 18 | 19 | If you are unwilling or unable to get `pip`_ then you may install *behave* 20 | manually by following the download link above and grabbing the source 21 | bundle. Once you have that you need to unpack it. Then, in the directory 22 | created by the unpacking, run: 23 | 24 | python setup.py install 25 | 26 | .. _`pip`: http://www.pip-installer.org/en/latest/installing.html 27 | -------------------------------------------------------------------------------- /behave-parallel/docs/parse_builtin_types.rst: -------------------------------------------------------------------------------- 1 | .. _id.appendix.parse_builtin_types: 2 | 3 | Predefined Data Types in ``parse`` 4 | ============================================================================== 5 | 6 | `behave`_ uses the `parse`_ module (inverse of Python `string.format`_) 7 | under the hoods to parse parameters in step definitions. 8 | This leads to rather simple and readable parse expressions for step parameters. 9 | 10 | .. code:: python 11 | 12 | # -- FILE: features/steps/type_transform_example_steps.py 13 | from behave import given 14 | 15 | @given('I have {number:d} friends') #< Convert 'number' into int type. 16 | def step_given_i_have_number_friends(context, number): 17 | assert number > 0 18 | ... 19 | 20 | Therefore, the following ``parse types`` are already supported 21 | in step definitions without registration of any *user-defined type*: 22 | 23 | 24 | ===== =========================================== ============ 25 | Type Characters Matched Output Type 26 | ===== =========================================== ============ 27 | w Letters and underscore str 28 | W Non-letter and underscore str 29 | s Whitespace str 30 | S Non-whitespace str 31 | d Digits (effectively integer numbers) int 32 | D Non-digit str 33 | n Numbers with thousands separators (, or .) int 34 | % Percentage (converted to value/100.0) float 35 | f Fixed-point numbers float 36 | e Floating-point numbers with exponent float 37 | e.g. 1.1e-10, NAN (all case insensitive) 38 | g General number format (either d, f or e) float 39 | b Binary numbers int 40 | o Octal numbers int 41 | x Hexadecimal numbers (lower and upper case) int 42 | ti ISO 8601 format date/time datetime 43 | e.g. 1972-01-20T10:21:36Z 44 | te RFC2822 e-mail format date/time datetime 45 | e.g. Mon, 20 Jan 1972 10:21:36 +1000 46 | tg Global (day/month) format date/time datetime 47 | e.g. 20/1/1972 10:21:36 AM +1:00 48 | ta US (month/day) format date/time datetime 49 | e.g. 1/20/1972 10:21:36 PM +10:30 50 | tc ctime() format date/time datetime 51 | e.g. Sun Sep 16 01:03:52 1973 52 | th HTTP log format date/time datetime 53 | e.g. 21/Nov/2011:00:07:11 +0000 54 | tt Time time 55 | e.g. 10:21:36 PM -5:30 56 | ===== =========================================== ============ 57 | 58 | 59 | .. _behave: http://pypi.python.org/pypi/behave 60 | .. _parse: http://pypi.python.org/pypi/parse 61 | .. _string.format: http://docs.python.org/library/string.html#format-string-syntax -------------------------------------------------------------------------------- /behave-parallel/docs/related.rst: -------------------------------------------------------------------------------- 1 | .. _id.appendix.related: 2 | 3 | =============================== 4 | Software that Enhances *behave* 5 | =============================== 6 | 7 | * Mock 8 | * nose.tools and nose.twistedtools 9 | * mechanize for pretending to be a browser 10 | * selenium webdriver for actually driving a browser 11 | * wsgi_intercept for providing more easily testable WSGI servers 12 | * BeautifulSoup, lxml and html5lib for parsing HTML 13 | * ... 14 | 15 | -------------------------------------------------------------------------------- /behave-parallel/docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinxcontrib-cheeseshop 2 | -------------------------------------------------------------------------------- /behave-parallel/docs/test_domains.rst: -------------------------------------------------------------------------------- 1 | .. _id.appendix.test_domain: 2 | 3 | Testing Domains 4 | ============================================================================== 5 | 6 | Behave and other BDD frameworks allow you to provide **step libraries** 7 | to reuse step definitions in similar projects that address the same 8 | problem domain. 9 | 10 | Support of the following testing domains is currently known: 11 | 12 | =============== ================= ========================================================= 13 | Testing Domain Name Description 14 | =============== ================= ========================================================= 15 | Command-line `behave4cmd`_ Test command-line tools, like behave, etc. (coming soon). 16 | Web Apps `django-behave`_ Test Django Web apps with behave. 17 | Web, SMS, ... `behaving`_ Test Web Apps, Email, SMS, Personas (step library). 18 | =============== ================= ========================================================= 19 | 20 | .. _behave4cmd: https://github.com/jenisys/behave4cmd 21 | .. _django-behave: https://github.com/rwillmer/django-behave 22 | .. _behaving: https://github.com/ggozad/behaving 23 | -------------------------------------------------------------------------------- /behave-parallel/docs/update_behave_rst.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import re 4 | import sys 5 | import conf 6 | import textwrap 7 | 8 | sys.argv[0] = 'behave' 9 | 10 | from behave import configuration 11 | from behave import __main__ 12 | 13 | with open('behave.rst-template') as f: 14 | template = f.read() 15 | 16 | #cmdline = configuration.parser.format_help() 17 | 18 | config = [] 19 | cmdline = [] 20 | for fixed, keywords in configuration.options: 21 | skip = False 22 | if 'dest' in keywords: 23 | dest = keywords['dest'] 24 | else: 25 | for opt in fixed: 26 | if opt.startswith('--no'): 27 | skip = True 28 | if opt.startswith('--'): 29 | dest = opt[2:].replace('-', '_') 30 | else: 31 | assert len(opt) == 2 32 | dest = opt[1:] 33 | 34 | text = re.sub(r'\s+', ' ', keywords['help']).strip() 35 | text = text.replace('%%', '%') 36 | text = textwrap.fill(text, 70, initial_indent=' ', subsequent_indent=' ') 37 | if fixed: 38 | # -- COMMAND-LINE OPTIONS (CONFIGFILE only have empty fixed): 39 | cmdline.append('**%s**\n%s' % (', '.join(fixed), text)) 40 | 41 | if skip or dest in 'tags_help lang_list lang_help version'.split(): 42 | continue 43 | 44 | action = keywords.get('action', 'store') 45 | if action == 'store': 46 | type = 'text' 47 | elif action in ('store_true','store_false'): 48 | type = 'boolean' 49 | elif action == 'append': 50 | type = 'text (multiple allowed)' 51 | else: 52 | raise ValueError('unknown action %s' % action) 53 | 54 | text = re.sub(r'\s+', ' ', keywords.get('config_help', keywords['help'])).strip() 55 | text = text.replace('%%', '%') 56 | text = textwrap.fill(text, 70, initial_indent=' ', subsequent_indent=' ') 57 | config.append('**%s** -- %s\n%s' % (dest, type, text)) 58 | 59 | 60 | values = dict( 61 | cmdline='\n'.join(cmdline), 62 | tag_expression=__main__.TAG_HELP, 63 | config='\n'.join(config), 64 | ) 65 | 66 | with open('behave.rst', 'w') as f: 67 | f.write(template.format(**values)) 68 | -------------------------------------------------------------------------------- /behave-parallel/features/README.txt: -------------------------------------------------------------------------------- 1 | behave features: Self-Tests 2 | =============================================================================== 3 | 4 | This directory contains feature tests that are executed with behave. 5 | These self-tests are used to: 6 | 7 | * ensure that ``behave`` reacts as expected 8 | * define the common expected behaviour for behave 9 | * support "Acceptance Test Driven-Design" (ATDD) 10 | 11 | RELATED: 12 | * Cucumber Technology Compatibility Kit: https://github.com/cucumber/cucumber-tck -------------------------------------------------------------------------------- /behave-parallel/features/context.global_params.feature: -------------------------------------------------------------------------------- 1 | Feature: Global Context Parameters defined in "environment.py" 2 | 3 | | Specification: 4 | | * When a Context parameter is defined in "environment.py", 5 | | its value is provided to all scenarios (steps). 6 | | * Each scenario has the same global parameters (and values). 7 | | * A scenario (step) may modify global parameters (values). 8 | | * After a scenario is executed all changes to Context parameters are reverted. 9 | 10 | Scenario: Test Setup Description (Example) 11 | Given a file named "features/environment.py" with: 12 | """ 13 | def before_all(context): 14 | context.global_name = "env:Alice" 15 | context.global_age = 12 16 | """ 17 | 18 | Scenario: Modify global Context parameter in Scenario Step 19 | Given the behave context contains: 20 | | Parameter | Value | 21 | | global_name | "env:Alice" | 22 | | global_age | 12 | 23 | When I set the context parameter "global_name" to "step:Bob" 24 | Then the behave context should contain: 25 | | Parameter | Value | 26 | | global_name | "step:Bob" | 27 | | global_age | 12 | 28 | 29 | Scenario: Ensure that Global Context parameter is reset for next Scenario 30 | Then the behave context should have a parameter "global_name" 31 | And the behave context should contain: 32 | | Parameter | Value | 33 | | global_name | "env:Alice" | 34 | | global_age | 12 | 35 | 36 | -------------------------------------------------------------------------------- /behave-parallel/features/context.local_params.feature: -------------------------------------------------------------------------------- 1 | Feature: Local Context Parameters defined in Scenarios (Steps) 2 | 3 | | Specification: 4 | | * When a step adds/modifies an attribute in the Context object, 5 | | then its value is only available to other steps in this scenario. 6 | | * After a scenario is executed all Context object changes are undone. 7 | 8 | Scenario: Add Local Context parameter in Scenario/Step 9 | Given the behave context does not have a parameter "local_name" 10 | When I set the context parameter "local_name" to "Alice" 11 | Then the behave context should have a parameter "local_name" 12 | And the behave context should contain: 13 | | Parameter | Value | 14 | | local_name | "Alice" | 15 | 16 | Scenario: Ensure that Local Context parameter is not available to next Scenario 17 | Then the behave context should not have a parameter "local_name" 18 | -------------------------------------------------------------------------------- /behave-parallel/features/directory_layout.basic.feature: -------------------------------------------------------------------------------- 1 | Feature: Basic directory layout (Variant 1) 2 | 3 | As a story/test writer 4 | I want a simple, non-deep directory structure 5 | So that I can easily get an overview which stories/tests exist 6 | 7 | | BASIC DIRECTORY LAYOUT STRUCTURE: 8 | | features/ 9 | | +-- steps/*.py # Step definitions or step-library imports. 10 | | +-- *.feature # Feature files. 11 | | +-- environment.py # OPTIONAL: environment setup/hooks. 12 | | 13 | | SEE ALSO: 14 | | * http://pythonhosted.org/behave/gherkin.html#layout-variations 15 | 16 | 17 | @setup 18 | Scenario: Setup directory structure 19 | Given a new working directory 20 | And a file named "features/steps/steps.py" with: 21 | """ 22 | from behave import step 23 | 24 | @step('{word:w} step passes') 25 | def step_passes(context, word): 26 | pass 27 | 28 | @step('{word:w} step fails') 29 | def step_fails(context, word): 30 | assert False, "XFAIL-STEP" 31 | """ 32 | And a file named "features/alice.feature" with: 33 | """ 34 | Feature: Alice 35 | Scenario: A1 36 | Given a step passes 37 | When another step passes 38 | Then a step passes 39 | """ 40 | And a file named "features/bob.feature" with: 41 | """ 42 | Feature: Bob 43 | Scenario: B1 44 | When a step passes 45 | Then another step passes 46 | """ 47 | 48 | 49 | Scenario: Run behave with feature directory 50 | When I run "behave -f progress features/" 51 | Then it should pass with: 52 | """ 53 | 2 features passed, 0 failed, 0 skipped 54 | 2 scenarios passed, 0 failed, 0 skipped 55 | 5 steps passed, 0 failed, 0 skipped, 0 undefined 56 | """ 57 | 58 | Scenario: Run behave with one feature file 59 | When I run "behave -f progress features/alice.feature" 60 | Then it should pass with: 61 | """ 62 | 1 feature passed, 0 failed, 0 skipped 63 | 1 scenario passed, 0 failed, 0 skipped 64 | 3 steps passed, 0 failed, 0 skipped, 0 undefined 65 | """ 66 | 67 | 68 | Scenario: Run behave with two feature files 69 | When I run "behave -f progress features/alice.feature features/bob.feature" 70 | Then it should pass with: 71 | """ 72 | 2 features passed, 0 failed, 0 skipped 73 | 2 scenarios passed, 0 failed, 0 skipped 74 | 5 steps passed, 0 failed, 0 skipped, 0 undefined 75 | """ 76 | -------------------------------------------------------------------------------- /behave-parallel/features/directory_layout.basic2.feature: -------------------------------------------------------------------------------- 1 | Feature: Basic directory layout (Variant 1B) 2 | 3 | As a story/test writer 4 | I want a simple, non-deep directory structure 5 | So that I can easily get an overview which stories/tests exist 6 | 7 | | BASIC DIRECTORY LAYOUT STRUCTURE: 8 | | testing/features/ 9 | | +-- steps/*.py # Step definitions or step-library imports. 10 | | +-- *.feature # Feature files. 11 | | +-- environment.py # OPTIONAL: environment setup/hooks. 12 | | 13 | | SEE ALSO: 14 | | * http://pythonhosted.org/behave/gherkin.html#layout-variations 15 | 16 | 17 | @setup 18 | Scenario: Setup directory structure 19 | Given a new working directory 20 | And a file named "testing/features/steps/steps.py" with: 21 | """ 22 | from behave import step 23 | 24 | @step('{word:w} step passes') 25 | def step_passes(context, word): 26 | pass 27 | 28 | @step('{word:w} step fails') 29 | def step_fails(context, word): 30 | assert False, "XFAIL-STEP" 31 | """ 32 | And a file named "testing/features/alice.feature" with: 33 | """ 34 | Feature: Alice 35 | Scenario: A1 36 | Given a step passes 37 | When another step passes 38 | Then a step passes 39 | """ 40 | And a file named "testing/features/bob.feature" with: 41 | """ 42 | Feature: Bob 43 | Scenario: B1 44 | When a step passes 45 | Then another step passes 46 | """ 47 | 48 | 49 | Scenario: Run behave with testing directory 50 | When I run "behave -f progress testing/" 51 | Then it should fail with: 52 | """ 53 | ConfigError: No steps directory in "{__WORKDIR__}/testing" 54 | """ 55 | 56 | Scenario: Run behave with feature subdirectory 57 | When I run "behave -f progress testing/features/" 58 | Then it should pass with: 59 | """ 60 | 2 features passed, 0 failed, 0 skipped 61 | 2 scenarios passed, 0 failed, 0 skipped 62 | 5 steps passed, 0 failed, 0 skipped, 0 undefined 63 | """ 64 | 65 | Scenario: Run behave with one feature file 66 | When I run "behave -f progress testing/features/alice.feature" 67 | Then it should pass with: 68 | """ 69 | 1 feature passed, 0 failed, 0 skipped 70 | 1 scenario passed, 0 failed, 0 skipped 71 | 3 steps passed, 0 failed, 0 skipped, 0 undefined 72 | """ 73 | 74 | 75 | Scenario: Run behave with two feature files 76 | Given a file named "one.featureset" with: 77 | """ 78 | testing/features/alice.feature 79 | testing/features/bob.feature 80 | """ 81 | When I run "behave -f progress @one.featureset" 82 | Then it should pass with: 83 | """ 84 | 2 features passed, 0 failed, 0 skipped 85 | 2 scenarios passed, 0 failed, 0 skipped 86 | 5 steps passed, 0 failed, 0 skipped, 0 undefined 87 | """ 88 | -------------------------------------------------------------------------------- /behave-parallel/features/environment.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # ----------------------------------------------------------------------------- 4 | # HOOKS: 5 | # ----------------------------------------------------------------------------- 6 | def before_all(context): 7 | setup_context_with_global_params_test(context) 8 | 9 | # ----------------------------------------------------------------------------- 10 | # SPECIFIC FUNCTIONALITY: 11 | # ----------------------------------------------------------------------------- 12 | def setup_context_with_global_params_test(context): 13 | context.global_name = "env:Alice" 14 | context.global_age = 12 15 | -------------------------------------------------------------------------------- /behave-parallel/features/feature.description.feature: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sauce-archives/Python-Behave-Appium-Android/8477d99c14dc8331d2f8b1824f0b02fcc9c82b42/behave-parallel/features/feature.description.feature -------------------------------------------------------------------------------- /behave-parallel/features/formatter.help.feature: -------------------------------------------------------------------------------- 1 | Feature: Help Formatter 2 | 3 | As a tester 4 | I want to know which formatter are supported 5 | To be able to select one. 6 | 7 | Scenario: 8 | Given a new working directory 9 | When I run "behave --format=help" 10 | Then it should pass 11 | And the command output should contain: 12 | """ 13 | Available formatters: 14 | json JSON dump of test run 15 | json.pretty JSON dump of test run (human readable) 16 | null Provides formatter that does not output anything. 17 | plain Very basic formatter with maximum compatibility 18 | pretty Standard colourised pretty formatter 19 | progress Shows dotted progress for each executed scenario. 20 | progress2 Shows dotted progress for each executed step. 21 | progress3 Shows detailed progress for each step of a scenario. 22 | rerun Emits scenario file locations of failing scenarios 23 | sphinx.steps Generate sphinx-based documentation for step definitions. 24 | steps Shows step definitions (step implementations). 25 | steps.doc Shows documentation for step definitions. 26 | steps.usage Shows how step definitions are used by steps. 27 | tags Shows tags (and how often they are used). 28 | tags.location Shows tags and the location where they are used. 29 | """ 30 | -------------------------------------------------------------------------------- /behave-parallel/features/runner.select_files_by_regexp.example.feature: -------------------------------------------------------------------------------- 1 | Feature: Select feature files by using regular expressions (self-test) 2 | 3 | Use behave self-tests to ensure that --incude/--exclude options work. 4 | RELATED: runner.select_files_by_regexp.feature 5 | 6 | @setup 7 | Scenario: Feature Setup 8 | Given a new working directory 9 | And an empty file named "features/steps/steps.py" 10 | And a file named "features/alice.feature" with: 11 | """ 12 | Feature: Alice 13 | Scenario: A1 14 | """ 15 | And a file named "features/barbi.feature" with: 16 | """ 17 | Feature: Barbi 18 | Scenario: B1 19 | """ 20 | And a file named "features/bob.feature" with: 21 | """ 22 | Feature: Bob 23 | Scenario: B2 24 | """ 25 | 26 | 27 | Scenario: Include only feature files 28 | 29 | Select the following feature files: barbi.feature, bob.feature 30 | 31 | When I run "behave --include='features/b.*' -f plain features/" 32 | Then it should pass with: 33 | """ 34 | 2 features passed, 0 failed, 0 skipped 35 | """ 36 | And the command output should contain: 37 | """ 38 | Feature: Barbi 39 | Scenario: B1 40 | 41 | Feature: Bob 42 | Scenario: B2 43 | """ 44 | 45 | Scenario: Exclude only feature files 46 | 47 | Select the following feature files: alice.feature 48 | 49 | When I run "behave --exclude='features/b.*' -f plain features/" 50 | Then it should pass with: 51 | """ 52 | 1 feature passed, 0 failed, 0 skipped 53 | """ 54 | And the command output should contain: 55 | """ 56 | Feature: Alice 57 | """ 58 | 59 | Scenario: Include and exclude feature files 60 | 61 | Select the following feature files: alice.feature 62 | 63 | When I run "behave --include='features/.*a.*\.feature' --exclude='.*/barbi.*' -f plain features/" 64 | Then it should pass with: 65 | """ 66 | 1 feature passed, 0 failed, 0 skipped 67 | """ 68 | And the command output should contain: 69 | """ 70 | Feature: Alice 71 | """ 72 | -------------------------------------------------------------------------------- /behave-parallel/features/runner.select_files_by_regexp.feature: -------------------------------------------------------------------------------- 1 | @sequential 2 | Feature: Select feature files by using regular expressions 3 | 4 | As a tester 5 | I want to include/exclude feature files into/from a test run by using wildcards 6 | To be more flexible and avoid to specify all feature files 7 | 8 | | SPECIFICATION: 9 | | * behave provides --include and --exclude command line options 10 | | * --include option selects a subset of all files that should be included 11 | | * --exclude option is applied after include option is applied 12 | | 13 | | EXAMPLE: 14 | | behave --include="features/ali.*\.feature" ... 15 | | behave --exclude="features/ali.*" ... 16 | 17 | 18 | Background: 19 | Given behave has the following feature fileset: 20 | """ 21 | features/alice.feature 22 | features/bob.feature 23 | features/barbi.feature 24 | """ 25 | 26 | Scenario: Include only feature files 27 | When behave includes feature files with "features/a.*" 28 | And behave excludes no feature files 29 | Then the following feature files are selected: 30 | """ 31 | features/alice.feature 32 | """ 33 | 34 | Scenario: Include more than one feature file 35 | When behave includes feature files with "features/b.*" 36 | Then the following feature files are selected: 37 | """ 38 | features/bob.feature 39 | features/barbi.feature 40 | """ 41 | 42 | 43 | Scenario: Exclude only feature files 44 | When behave excludes feature files with "features/a.*" 45 | And behave includes all feature files 46 | Then the following feature files are selected: 47 | """ 48 | features/bob.feature 49 | features/barbi.feature 50 | """ 51 | 52 | Scenario: Exclude more than one feature file 53 | When behave excludes feature files with "features/b.*" 54 | Then the following feature files are selected: 55 | """ 56 | features/alice.feature 57 | """ 58 | 59 | Scenario: Include and exclude feature files 60 | 61 | Ensure that exclude file pattern is applied after include file pattern. 62 | 63 | When behave includes feature files with "features/.*a.*\.feature" 64 | And behave excludes feature files with ".*/barbi.*" 65 | Then the following feature files are selected: 66 | """ 67 | features/alice.feature 68 | """ 69 | 70 | Scenario: Include and exclude feature files (in 2 steps) 71 | 72 | Show how file inclusion/exclusion works by emulating the two steps. 73 | 74 | When behave includes feature files with "features/.*a.*\.feature" 75 | Then the following feature files are selected: 76 | """ 77 | features/alice.feature 78 | features/barbi.feature 79 | """ 80 | When behave excludes feature files with ".*/barbi.*" 81 | Then the following feature files are selected: 82 | """ 83 | features/alice.feature 84 | """ 85 | -------------------------------------------------------------------------------- /behave-parallel/features/runner.unknown_formatter.feature: -------------------------------------------------------------------------------- 1 | Feature: When an unknown formatter is used 2 | 3 | 4 | Scenario: Unknown formatter is used 5 | When I run "behave -f unknown1" 6 | Then it should fail with: 7 | """ 8 | behave: error: format=unknown1 is unknown 9 | """ 10 | 11 | Scenario: Unknown formatter is used together with another formatter 12 | When I run "behave -f plain -f unknown1" 13 | Then it should fail with: 14 | """ 15 | behave: error: format=unknown1 is unknown 16 | """ 17 | 18 | Scenario: Two unknown formatters are used 19 | When I run "behave -f plain -f unknown1 -f tags -f unknown2" 20 | Then it should fail with: 21 | """ 22 | behave: error: format=unknown1, unknown2 is unknown 23 | """ 24 | -------------------------------------------------------------------------------- /behave-parallel/features/scenario_outline.basics.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #187 ScenarioOutline uses wrong return value when if fails 3 | 4 | Ensure that ScenarioOutline run-logic behaves as expected. 5 | 6 | @setup 7 | Scenario: Feature Setup 8 | Given a new working directory 9 | And a file named "features/steps/steps.py" with: 10 | """ 11 | from behave import step 12 | 13 | @step('a step passes') 14 | def step_passes(context): 15 | pass 16 | 17 | @step('a step fails') 18 | def step_fails(context): 19 | assert False, "XFAIL-STEP" 20 | """ 21 | 22 | Scenario: All examples pass 23 | Given a file named "features/example.scenario_outline_pass.feature" with: 24 | """ 25 | Feature: All Examples pass 26 | Scenario Outline: 27 | Given a step 28 | 29 | Examples: 30 | | outcome | Comment | 31 | | passes | First example passes | 32 | | passes | Last example passes | 33 | """ 34 | When I run "behave -f plain features/example.scenario_outline_pass.feature" 35 | Then it should pass with: 36 | """ 37 | 1 feature passed, 0 failed, 0 skipped 38 | 2 scenarios passed, 0 failed, 0 skipped 39 | """ 40 | 41 | @scenario_outline.fails 42 | Scenario: First example fails 43 | Given a file named "features/example.scenario_outline_fail_first.feature" with: 44 | """ 45 | Feature: First Example in Scenario Outline fails 46 | Scenario Outline: 47 | Given a step 48 | 49 | Examples: 50 | | outcome | Comment | 51 | | fails | First example fails | 52 | | passes | Last example passes | 53 | """ 54 | When I run "behave -f plain features/example.scenario_outline_fail_first.feature" 55 | Then it should fail with: 56 | """ 57 | 0 features passed, 1 failed, 0 skipped 58 | 1 scenario passed, 1 failed, 0 skipped 59 | """ 60 | 61 | @scenario_outline.fails 62 | Scenario: Last example fails 63 | Given a file named "features/example.scenario_outline_fail_last.feature" with: 64 | """ 65 | Feature: Last Example in Scenario Outline fails 66 | Scenario Outline: 67 | Given a step 68 | 69 | Examples: 70 | | outcome | Comment | 71 | | passes | First example passes | 72 | | fails | Last example fails | 73 | """ 74 | When I run "behave -f plain features/example.scenario_outline_fail_last.feature" 75 | Then it should fail with: 76 | """ 77 | 0 features passed, 1 failed, 0 skipped 78 | 1 scenario passed, 1 failed, 0 skipped 79 | """ 80 | 81 | @scenario_outline.fails 82 | Scenario: Middle example fails 83 | Given a file named "features/example.scenario_outline_fail_middle.feature" with: 84 | """ 85 | Feature: Middle Example in Scenario Outline fails 86 | Scenario Outline: 87 | Given a step 88 | 89 | Examples: 90 | | outcome | Comment | 91 | | passes | First example passes | 92 | | fails | Middle example fails | 93 | | passes | Last example passes | 94 | """ 95 | When I run "behave -f plain features/example.scenario_outline_fail_middle.feature" 96 | Then it should fail with: 97 | """ 98 | 0 features passed, 1 failed, 0 skipped 99 | 2 scenarios passed, 1 failed, 0 skipped 100 | """ 101 | -------------------------------------------------------------------------------- /behave-parallel/features/step.execute_steps.feature: -------------------------------------------------------------------------------- 1 | Feature: Execute Steps within a Step Function (Nested Steps) 2 | 3 | As a tester 4 | I want to reuse existing steps and call several ones within another step 5 | So that I can comply with the the DRY principle. 6 | 7 | Scenario: Execute a number of simple steps (GOOD CASE) 8 | Given a new working directory 9 | And a file named "features/steps/steps.py" with: 10 | """ 11 | from behave import given, when, then 12 | 13 | @given(u'I go to the supermarket') 14 | def step_given_I_go_to_the_supermarket(context): 15 | context.shopping_cart = {} 16 | 17 | @when(u'I buy {amount:n} {item:w}') 18 | def step_when_I_buy(context, amount, item): 19 | assert amount >= 0 20 | if not context.shopping_cart.has_key(item): 21 | context.shopping_cart[item] = 0 22 | context.shopping_cart[item] += amount 23 | 24 | # -- HERE: Is the interesting functionality. 25 | @when(u'I buy the usual things') 26 | def step_when_I_buy_the_usual_things(context): 27 | context.execute_steps(u''' 28 | When I buy 2 apples 29 | And I buy 3 bananas 30 | ''') 31 | 32 | @then(u'I have {amount:n} {item:w}') 33 | def step_then_I_have(context, amount, item): 34 | actual = context.shopping_cart.get(item, 0) 35 | assert amount == actual 36 | """ 37 | And a file named "features/use_nested_steps.feature" with: 38 | """ 39 | Feature: 40 | Scenario: 41 | Given I go to the supermarket 42 | When I buy the usual things 43 | Then I have 2 apples 44 | And I have 3 bananas 45 | """ 46 | When I run "behave -f plain features/use_nested_steps.feature" 47 | Then it should pass with: 48 | """ 49 | 1 feature passed, 0 failed, 0 skipped 50 | 1 scenario passed, 0 failed, 0 skipped 51 | 4 steps passed, 0 failed, 0 skipped, 0 undefined 52 | """ 53 | 54 | @not_implemented 55 | Scenario: A Nested Step Fails with Assert 56 | 57 | @not_implemented 58 | Scenario: A Nested Step Fails with Exception 59 | 60 | -------------------------------------------------------------------------------- /behave-parallel/features/step.execute_steps.with_table.feature: -------------------------------------------------------------------------------- 1 | Feature: Execute nested steps that use a table 2 | 3 | Scenario: 4 | Given a new working directory 5 | And a file named "features/steps/steps.py" with: 6 | """ 7 | from behave import given, when, then, step 8 | 9 | @given('the following nested steps') 10 | def step_given_following_nested_steps(context): 11 | assert context.text, "ENSURE: multi-line text is provided." 12 | context.nested_steps = unicode(context.text) 13 | 14 | @step('I execute the nested steps {comment}') 15 | def step_execute_nested_steps_with_table(context, comment): 16 | assert context.nested_steps, "ENSURE: nested steps are provided." 17 | context.execute_steps(context.nested_steps) 18 | 19 | @then('the step "{expected_step}" was called') 20 | def then_step_was_called(context, expected_step): 21 | assert context.steps_called, "ENSURE: steps_called is provided." 22 | assert expected_step in context.steps_called 23 | 24 | @then('the table should be equal to') 25 | def then_table_should_be_equal_to(context): 26 | assert context.table, "ENSURE: table is provided." 27 | expected_table = context.table 28 | actual_table = context.the_table 29 | assert actual_table == expected_table 30 | 31 | # -- SPECIAL-STEP: 32 | @step('I setup an address book with') 33 | def step_setup_address_book_with_friends(context): 34 | assert context.table, "ENSURE: table is provided." 35 | if not hasattr(context, "steps_called"): 36 | context.steps_called = [] 37 | context.steps_called.append("I setup an address book with") 38 | context.the_table = context.table 39 | """ 40 | And a file named "features/execute_nested_steps_with_table.feature" with: 41 | ''' 42 | Feature: 43 | Scenario: 44 | Given the following nested steps: 45 | """ 46 | When I setup an address book with: 47 | | Name | Telephone Number | 48 | | Alice | 555 1111 | 49 | | Bob | 555 2222 | 50 | """ 51 | When I execute the nested steps with a table 52 | Then the step "I setup an address book with" was called 53 | And the table should be equal to: 54 | | Name | Telephone Number | 55 | | Alice | 555 1111 | 56 | | Bob | 555 2222 | 57 | ''' 58 | When I run "behave -f plain features/execute_nested_steps_with_table.feature" 59 | Then it should pass with: 60 | """ 61 | 1 feature passed, 0 failed, 0 skipped 62 | 1 scenario passed, 0 failed, 0 skipped 63 | 4 steps passed, 0 failed, 0 skipped, 0 undefined 64 | """ 65 | 66 | -------------------------------------------------------------------------------- /behave-parallel/features/step.use_step_library.feature: -------------------------------------------------------------------------------- 1 | Feature: Use a step library 2 | 3 | As a tester 4 | I want to use steps from one or more step libraries 5 | To simplify the reuse of problem domain specific steps in multiple projects. 6 | 7 | 8 | Scenario: Use a simple step library 9 | Given a new working directory 10 | And an empty file named "step_library1/__init__.py" 11 | And a file named "step_library1/alice_steps.py" with: 12 | """ 13 | from behave import step 14 | 15 | @step('I meet Alice') 16 | def step_meet_alice(context): 17 | pass 18 | """ 19 | And a file named "step_library1/bob_steps.py" with: 20 | """ 21 | from behave import step 22 | 23 | @step('I meet Bob') 24 | def step_meet_bob(context): 25 | pass 26 | """ 27 | And a file named "features/steps/use_step_library.py" with: 28 | """ 29 | from step_library1 import alice_steps, bob_steps 30 | """ 31 | And a file named "features/example_use_step_library.feature" with: 32 | """ 33 | Feature: 34 | Scenario: 35 | Given I meet Alice 36 | And I meet Bob 37 | """ 38 | When I run "behave -f plain features/example_use_step_library.feature" 39 | Then it should pass with: 40 | """ 41 | 1 feature passed, 0 failed, 0 skipped 42 | 1 scenario passed, 0 failed, 0 skipped 43 | 2 steps passed, 0 failed, 0 skipped, 0 undefined 44 | """ 45 | -------------------------------------------------------------------------------- /behave-parallel/features/step_dialect.given_when_then.feature: -------------------------------------------------------------------------------- 1 | Feature: Step Dialect for BDD Steps with Given/When/Then Keywords 2 | 3 | In order to execute a sequence of steps with BDD keywords (Given/When/Then) 4 | As a test/story writer 5 | I want to have the possibility to express myself. 6 | 7 | | NOTE: 8 | | * More details are provided in other features. 9 | 10 | 11 | Scenario: Simple example 12 | 13 | Normally preferred style with BDD keywords. 14 | Note that BDD keywords are dependent on language settings. 15 | 16 | Given a step passes 17 | When a step passes 18 | And a step passes 19 | Then a step passes 20 | And a step passes 21 | But a step passes 22 | 23 | 24 | Scenario: Simple example (with lower-case keywords) 25 | 26 | Alternative style with lower-case BDD keywords. 27 | 28 | given a step passes 29 | when a step passes 30 | and a step passes 31 | then a step passes 32 | and a step passes 33 | but a step passes 34 | 35 | 36 | Scenario: Step usage example with details by running behave 37 | Given a new working directory 38 | And a file named "features/steps/steps.py" with: 39 | """ 40 | from behave import given, when, then, step 41 | 42 | @given('a step passes') 43 | def given_step_passes(context): 44 | pass 45 | 46 | @when('a step passes') 47 | def when_step_passes(context): 48 | pass 49 | 50 | @then('a step passes') 51 | def then_step_passes(context): 52 | pass 53 | 54 | @step('a step passes with "{param}"') 55 | def step_passes_with_param(context, param): 56 | pass 57 | 58 | @step('another step passes') 59 | def step_passes(context): 60 | pass 61 | 62 | @step('another step passes with "{param}"') 63 | def step_passes(context, param): 64 | pass 65 | """ 66 | And a file named "features/basic_steps.feature" with: 67 | """ 68 | Feature: 69 | Scenario: 70 | Given a step passes 71 | And another step passes 72 | When a step passes with "Alice" 73 | Then another step passes with "Bob" 74 | """ 75 | When I run "behave -f plain -T features/basic_steps.feature" 76 | Then it should pass with: 77 | """ 78 | 1 scenario passed, 0 failed, 0 skipped 79 | 4 steps passed, 0 failed, 0 skipped 80 | """ 81 | And the command output should contain: 82 | """ 83 | Feature: 84 | Scenario: 85 | Given a step passes ... passed 86 | And another step passes ... passed 87 | When a step passes with "Alice" ... passed 88 | Then another step passes with "Bob" ... passed 89 | """ -------------------------------------------------------------------------------- /behave-parallel/features/steps/behave_select_files_steps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Provides step definitions that test how the behave runner selects feature files. 4 | 5 | EXAMPLE: 6 | Given behave has the following feature fileset: 7 | ''' 8 | features/alice.feature 9 | features/bob.feature 10 | features/barbi.feature 11 | ''' 12 | When behave includes feature files with "features/a.*\.feature" 13 | And behave excludes feature files with "features/b.*\.feature" 14 | Then the following feature files are selected: 15 | ''' 16 | features/alice.feature 17 | ''' 18 | """ 19 | 20 | from behave import given, when, then 21 | from behave.runner_util import FeatureListParser 22 | from hamcrest import assert_that, equal_to 23 | from copy import copy 24 | import re 25 | 26 | # ----------------------------------------------------------------------------- 27 | # STEP UTILS: 28 | # ----------------------------------------------------------------------------- 29 | class BasicBehaveRunner(object): 30 | def __init__(self, config=None): 31 | self.config = config 32 | self.feature_files = [] 33 | 34 | def select_files(self): 35 | """ 36 | Emulate behave runners file selection by using include/exclude patterns. 37 | :return: List of selected feature filenames. 38 | """ 39 | selected = [] 40 | for filename in self.feature_files: 41 | if not self.config.exclude(filename): 42 | selected.append(str(filename)) 43 | return selected 44 | 45 | # ----------------------------------------------------------------------------- 46 | # STEP DEFINITIONS: 47 | # ----------------------------------------------------------------------------- 48 | @given('behave has the following feature fileset') 49 | def step_given_behave_has_feature_fileset(context): 50 | assert context.text is not None, "REQUIRE: text" 51 | behave_runner = BasicBehaveRunner(config=copy(context.config)) 52 | behave_runner.feature_files = FeatureListParser.parse(context.text) 53 | context.behave_runner = behave_runner 54 | 55 | @when('behave includes all feature files') 56 | def step_when_behave_includes_all_feature_files(context): 57 | assert context.behave_runner, "REQUIRE: context.behave_runner" 58 | context.behave_runner.config.include_re = None 59 | 60 | @when('behave includes feature files with "{pattern}"') 61 | def step_when_behave_includes_feature_files_with_pattern(context, pattern): 62 | assert context.behave_runner, "REQUIRE: context.behave_runner" 63 | context.behave_runner.config.include_re = re.compile(pattern) 64 | 65 | @when('behave excludes no feature files') 66 | def step_when_behave_excludes_no_feature_files(context): 67 | assert context.behave_runner, "REQUIRE: context.behave_runner" 68 | context.behave_runner.config.exclude_re = None 69 | 70 | @when('behave excludes feature files with "{pattern}"') 71 | def step_when_behave_excludes_feature_files_with_pattern(context, pattern): 72 | assert context.behave_runner, "REQUIRE: context.behave_runner" 73 | context.behave_runner.config.exclude_re = re.compile(pattern) 74 | 75 | @then('the following feature files are selected') 76 | def step_then_feature_files_are_selected_with_text(context): 77 | assert context.text is not None, "REQUIRE: text" 78 | assert context.behave_runner, "REQUIRE: context.behave_runner" 79 | selected_files = context.text.strip().splitlines() 80 | actual_files = context.behave_runner.select_files() 81 | assert_that(actual_files, equal_to(selected_files)) 82 | -------------------------------------------------------------------------------- /behave-parallel/features/steps/context_steps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Step definition for Context object tests. 4 | 5 | EXAMPLE 6 | Scenario: Show that Context parameter 7 | Given I set the parameter "person" to "Alice" in the behave context 8 | Then the behave context should have a parameter named "person" 9 | And the behave context object should contain: 10 | | Parameter | Value | 11 | | person | "Alice" | 12 | 13 | Scenario: Show that Context parameter are not present in next scenario 14 | Then the behave context should not have a parameter named "person" 15 | """ 16 | 17 | from behave import given, when, then, step 18 | from hamcrest import assert_that, equal_to 19 | 20 | # ----------------------------------------------------------------------------- 21 | # STEPS: 22 | # ----------------------------------------------------------------------------- 23 | @step(u'I set the context parameter "{param_name}" to "{value}"') 24 | def step_set_behave_context_parameter_to(context, param_name, value): 25 | setattr(context, param_name, value) 26 | 27 | @step(u'the parameter "{param_name}" exists in the behave context') 28 | def step_behave_context_parameter_exists(context, param_name): 29 | assert hasattr(context, param_name) 30 | 31 | @step(u'the parameter "{param_name}" does not exist in the behave context') 32 | def step_behave_context_parameter_not_exists(context, param_name): 33 | assert not hasattr(context, param_name) 34 | 35 | @given(u'the behave context has a parameter "{param_name}"') 36 | def given_behave_context_has_parameter_named(context, param_name): 37 | step_behave_context_parameter_exists(context, param_name) 38 | 39 | @given(u'the behave context does not have a parameter "{param_name}"') 40 | def given_behave_context_does_not_have_parameter_named(context, param_name): 41 | step_behave_context_parameter_not_exists(context, param_name) 42 | 43 | @step(u'the behave context should have a parameter "{param_name}"') 44 | def step_behave_context_should_have_parameter_named(context, param_name): 45 | step_behave_context_parameter_exists(context, param_name) 46 | 47 | @step(u'the behave context should not have a parameter "{param_name}"') 48 | def step_behave_context_should_not_have_parameter_named(context, param_name): 49 | step_behave_context_parameter_not_exists(context, param_name) 50 | 51 | @then(u'the behave context should contain') 52 | def then_behave_context_should_contain_with_table(context): 53 | assert context.table, "ENSURE: table is provided." 54 | for row in context.table.rows: 55 | param_name = row["Parameter"] 56 | param_value = row["Value"] 57 | if param_value.startswith('"') and param_value.endswith('"'): 58 | param_value = param_value[1:-1] 59 | actual = str(getattr(context, param_name, None)) 60 | assert hasattr(context, param_name) 61 | assert_that(actual, equal_to(param_value)) 62 | 63 | @given(u'the behave context contains') 64 | def given_behave_context_contains_with_table(context): 65 | then_behave_context_should_contain_with_table(context) -------------------------------------------------------------------------------- /behave-parallel/features/steps/use_steplib_behave4cmd.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Use behave4cmd0 step library (predecessor of behave4cmd). 4 | """ 5 | 6 | # -- REGISTER-STEPS: 7 | import behave4cmd0.__all_steps__ 8 | import behave4cmd0.passing_steps 9 | import behave4cmd0.failing_steps 10 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/README.txt: -------------------------------------------------------------------------------- 1 | issue.features: 2 | =============================================================================== 3 | 4 | :Status: PREPARED (fixes are being applied). 5 | :Requires: Python >= 2.6 (due to step implementations) 6 | 7 | This directory contains behave self-tests to ensure that behave related 8 | issues are fixed. 9 | 10 | PROCEDURE: 11 | 12 | * ONCE: Install python requirements ("requirements.txt") 13 | * Run the tests with behave 14 | 15 | :: 16 | 17 | bin/behave -f progress issue.features/ 18 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0030.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #30 "behave --version" runs features and shows no version 3 | 4 | Scenario: Ensure environment assumptions are correct (Sanity Check) 5 | Given a new working directory 6 | When I run "behave" 7 | Then it should fail 8 | And the command output should contain: 9 | """ 10 | No steps directory in "{__WORKDIR__}/features" 11 | """ 12 | 13 | Scenario: Ensure --version option is processed correctly 14 | Given a new working directory 15 | When I run "behave --version" 16 | Then it should pass 17 | And the command output should not contain: 18 | """ 19 | No steps directory in "{__WORKDIR__}/features" 20 | """ 21 | 22 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0031.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #31 "behave --format help" raises an error 3 | 4 | Scenario: 5 | Given a new working directory 6 | When I run "behave --format=help" 7 | Then it should pass 8 | And the command output should contain: 9 | """ 10 | Available formatters: 11 | json JSON dump of test run 12 | json.pretty JSON dump of test run (human readable) 13 | null Provides formatter that does not output anything. 14 | plain Very basic formatter with maximum compatibility 15 | pretty Standard colourised pretty formatter 16 | """ 17 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0032.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #32 "behave --junit-directory=xxx" fails if more than 1 level must be created 3 | 4 | Scenario: 5 | Given a new working directory 6 | And a file named "features/steps/steps.py" with: 7 | """ 8 | from behave import given, when, then 9 | 10 | @given(u'passing') 11 | def step(context): 12 | pass 13 | """ 14 | And a file named "features/issue32_1.feature" with: 15 | """ 16 | Feature: One 17 | Scenario: One 18 | Given passing 19 | """ 20 | 21 | When I run "behave --junit --junit-directory=report/test_results" 22 | Then it should pass with: 23 | """ 24 | 1 feature passed, 0 failed, 0 skipped 25 | 1 scenario passed, 0 failed, 0 skipped 26 | 1 step passed, 0 failed, 0 skipped, 0 undefined 27 | """ 28 | And the directory "report/test_results" should exist 29 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0035.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #35 Plain Formatter shows wrong steps when tag-selection is used 3 | 4 | Background: Test Setup 5 | Given a new working directory 6 | And a file named "features/steps/steps.py" with: 7 | """ 8 | from behave import given, when, then 9 | 10 | @given(u'the ninja has a third level black-belt') 11 | def step(context): 12 | pass 13 | 14 | @when(u'attacked by {opponent}') 15 | def step(context, opponent): 16 | pass 17 | 18 | @then(u'the ninja should {reaction}') 19 | def step(context, reaction): 20 | pass 21 | """ 22 | And a file named "features/issue35_1.feature" with: 23 | """ 24 | Feature: Using Tags with Features and Scenarios 25 | 26 | @one 27 | Scenario: Weaker opponent 28 | Given the ninja has a third level black-belt 29 | When attacked by a samurai 30 | Then the ninja should engage the opponent 31 | 32 | @two 33 | Scenario: Stronger opponent 34 | Given the ninja has a third level black-belt 35 | When attacked by Chuck Norris 36 | Then the ninja should run for his life 37 | """ 38 | 39 | Scenario: Select First Scenario with Tag 40 | When I run "behave --no-timings -f plain --tags=@one features/issue35_1.feature" 41 | Then it should pass with: 42 | """ 43 | 1 feature passed, 0 failed, 0 skipped 44 | 1 scenario passed, 0 failed, 1 skipped 45 | 3 steps passed, 0 failed, 3 skipped, 0 undefined 46 | """ 47 | And the command output should contain: 48 | """ 49 | Feature: Using Tags with Features and Scenarios 50 | Scenario: Weaker opponent 51 | Given the ninja has a third level black-belt ... passed 52 | When attacked by a samurai ... passed 53 | Then the ninja should engage the opponent ... passed 54 | Scenario: Stronger opponent 55 | """ 56 | 57 | Scenario: Select Second Scenario with Tag 58 | When I run "behave --no-timings -f plain --tags=@two features/issue35_1.feature" 59 | Then it should pass with: 60 | """ 61 | 1 feature passed, 0 failed, 0 skipped 62 | 1 scenario passed, 0 failed, 1 skipped 63 | 3 steps passed, 0 failed, 3 skipped, 0 undefined 64 | """ 65 | And the command output should contain: 66 | """ 67 | Feature: Using Tags with Features and Scenarios 68 | Scenario: Weaker opponent 69 | Scenario: Stronger opponent 70 | Given the ninja has a third level black-belt ... passed 71 | When attacked by Chuck Norris ... passed 72 | Then the ninja should run for his life ... passed 73 | """ 74 | 75 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0044.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #44 Shell-like comments are removed in Multiline Args 3 | 4 | As I user 5 | I want that multiline arguments (docstrings) contents are preserved. 6 | 7 | Background: Test Setup 8 | Given a new working directory 9 | And a file named "features/steps/steps.py" with: 10 | """ 11 | from behave import given, when, then 12 | from hamcrest import assert_that, equal_to 13 | 14 | @given(u'a multiline text argument with') 15 | def step(context): 16 | context.expected_text = context.text 17 | 18 | @then(u'the multiline text argument should be') 19 | def step(context): 20 | assert_that(context.text, equal_to(context.expected_text)) 21 | """ 22 | 23 | Scenario: Ensure shell comment lines are not filtered out in multiline text 24 | Given a file named "features/issue44_test.feature" with: 25 | ''' 26 | Feature: Multiline text with shell comment lines 27 | Scenario: 28 | Given a multiline text argument with: 29 | """ 30 | Lorem ipsum. 31 | # THIS IS A SHELL COMMENT. 32 | Ipsum lorem. 33 | """ 34 | Then the multiline text argument should be: 35 | """ 36 | Lorem ipsum. 37 | # THIS IS A SHELL COMMENT. 38 | Ipsum lorem. 39 | """ 40 | ''' 41 | When I run "behave -c -f pretty features/issue44_test.feature" 42 | Then it should pass 43 | And the command output should contain: 44 | """ 45 | # THIS IS A SHELL COMMENT. 46 | """ 47 | But the command output should not contain: 48 | """ 49 | Lorem ipsum. 50 | Ipsum lorem. 51 | """ 52 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0046.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #46 Behave returns 0 (SUCCESS) even in case of test failures 3 | 4 | As I behave user 5 | I want to detect test success or test failures 6 | By using the process return value, 0 (SUCCESS) and non-zero for failure. 7 | 8 | Background: Test Setup 9 | Given a new working directory 10 | Given a file named "features/steps/steps.py" with: 11 | """ 12 | from behave import given 13 | 14 | @given(u'passing') 15 | def step(context): 16 | pass 17 | 18 | @given(u'failing') 19 | def step(context): 20 | assert False, "failing" 21 | """ 22 | 23 | Scenario: Successful Execution 24 | Given a file named "features/passing.feature" with: 25 | """ 26 | Feature: Passing 27 | Scenario: Passing Scenario Example 28 | Given passing 29 | """ 30 | When I run "behave -c -q features/passing.feature" 31 | Then it should pass with: 32 | """ 33 | 1 feature passed, 0 failed, 0 skipped 34 | 1 scenario passed, 0 failed, 0 skipped 35 | 1 step passed, 0 failed, 0 skipped, 0 undefined 36 | """ 37 | 38 | Scenario: Failing Execution 39 | Given a file named "features/failing.feature" with: 40 | """ 41 | Feature: Failing 42 | Scenario: Failing Scenario Example 43 | Given failing 44 | """ 45 | When I run "behave -c -q features/failing.feature" 46 | Then it should fail with: 47 | """ 48 | 0 features passed, 1 failed, 0 skipped 49 | 0 scenarios passed, 1 failed, 0 skipped 50 | 0 steps passed, 1 failed, 0 skipped, 0 undefined 51 | """ 52 | 53 | Scenario: Passing and Failing Execution 54 | Given a file named "features/passing_and_failing.feature" with: 55 | """ 56 | Feature: Passing and Failing 57 | Scenario: Passing Scenario Example 58 | Given passing 59 | Scenario: Failing Scenario Example 60 | Given failing 61 | """ 62 | When I run "behave -c -q features/passing_and_failing.feature" 63 | Then it should fail with: 64 | """ 65 | 0 features passed, 1 failed, 0 skipped 66 | 1 scenario passed, 1 failed, 0 skipped 67 | 1 step passed, 1 failed, 0 skipped, 0 undefined 68 | """ 69 | And the command output should contain: 70 | """ 71 | Feature: Passing and Failing 72 | Scenario: Passing Scenario Example 73 | Given passing 74 | Scenario: Failing Scenario Example 75 | Given failing 76 | Assertion Failed: failing 77 | """ 78 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0052.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #52 Summary counts are wrong with option --tags 3 | 4 | Wrong summary counts are shown for skipped and failed scenarios 5 | when option --tags=done is used (and some scenarios are skipped). 6 | 7 | 8 | Background: Test Setup 9 | Given a new working directory 10 | Given a file named "features/steps/steps.py" with: 11 | """ 12 | from behave import given 13 | 14 | @given(u'passing') 15 | def step(context): 16 | pass 17 | 18 | @given(u'failing') 19 | def step(context): 20 | assert False, "failing" 21 | """ 22 | 23 | Scenario: Successful Execution of Tagged Scenario 24 | Given a file named "features/tagged_scenario1.feature" with: 25 | """ 26 | Feature: Passing tagged Scenario 27 | @done 28 | Scenario: P1 29 | Given passing 30 | 31 | @unimplemented 32 | Scenario: N1 33 | Given passing 34 | @unimplemented 35 | Scenario: N2 36 | Given passing 37 | """ 38 | When I run "behave --junit -c --tags @done features/tagged_scenario1.feature" 39 | Then it should pass with: 40 | """ 41 | 1 feature passed, 0 failed, 0 skipped 42 | 1 scenario passed, 0 failed, 2 skipped 43 | """ 44 | 45 | Scenario: Failing Execution of Tagged Scenario 46 | Given a file named "features/tagged_scenario2.feature" with: 47 | """ 48 | Feature: Failing tagged Scenario 49 | @done 50 | Scenario: F1 51 | Given failing 52 | 53 | @unimplemented 54 | Scenario: N1 55 | Given passing 56 | @unimplemented 57 | Scenario: N2 58 | Given passing 59 | """ 60 | When I run "behave --junit -c --tags @done features/tagged_scenario2.feature" 61 | Then it should fail 62 | And the command output should contain: 63 | """ 64 | 0 features passed, 1 failed, 0 skipped 65 | 0 scenarios passed, 1 failed, 2 skipped 66 | """ 67 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0059.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #59 Fatal error when using --format=json 3 | 4 | Using the JSON formatter caused a fatal error. 5 | 6 | Background: Test Setup 7 | Given a new working directory 8 | And a file named "features/steps/steps.py" with: 9 | """ 10 | from behave import given 11 | 12 | @given(u'passing') 13 | def step(context): 14 | pass 15 | """ 16 | And a file named "features/issue59_test.feature" with: 17 | """ 18 | Feature: Passing tagged Scenario 19 | Scenario: P1 20 | Given passing 21 | """ 22 | 23 | Scenario: Use the JSONFormatter 24 | When I run "behave --format=json features/issue59_test.feature" 25 | Then it should pass with: 26 | """ 27 | 1 feature passed, 0 failed, 0 skipped 28 | 1 scenario passed, 0 failed, 0 skipped 29 | """ 30 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0064.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #64 Exit status not set to 1 even there are failures in certain cases 3 | 4 | The behave exit status not always returns 1 when failure(s) occur. 5 | The problem was associated with the Feature.run() logic implementation. 6 | 7 | This problem was first discovered while verifying issue #52 (see comments). 8 | See also similar test when tags select a subset of scenarios. 9 | 10 | RELATED ISSUES: 11 | * issue #52 12 | 13 | Background: Test Setup 14 | Given a new working directory 15 | Given a file named "features/steps/steps.py" with: 16 | """ 17 | from behave import given 18 | 19 | @given(u'passing') 20 | def step(context): 21 | pass 22 | 23 | @given(u'failing') 24 | def step(context): 25 | assert False, "failing" 26 | """ 27 | 28 | Scenario: Failing in First Scenario 29 | Given a file named "features/issue64_case1.feature" with: 30 | """ 31 | Feature: Failing in First Scenario 32 | Scenario: 33 | Given failing 34 | 35 | Scenario: 36 | Given passing 37 | """ 38 | When I run "behave --format=plain features/issue64_case1.feature" 39 | Then it should fail with: 40 | """ 41 | 0 features passed, 1 failed, 0 skipped 42 | 1 scenario passed, 1 failed, 0 skipped 43 | """ 44 | 45 | Scenario: Failing in Middle Scenario 46 | Given a file named "features/issue64_case2.feature" with: 47 | """ 48 | Feature: Failing in Middle Scenario 49 | Scenario: 50 | Given passing 51 | Scenario: 52 | Given failing 53 | Scenario: 54 | Given passing 55 | """ 56 | When I run "behave --format=plain features/issue64_case2.feature" 57 | Then it should fail with: 58 | """ 59 | 0 features passed, 1 failed, 0 skipped 60 | 2 scenarios passed, 1 failed, 0 skipped 61 | """ 62 | 63 | Scenario: Failing in Last Scenario 64 | Given a file named "features/issue64_case3.feature" with: 65 | """ 66 | Feature: Failing in Last Scenario 67 | Scenario: 68 | Given passing 69 | Scenario: 70 | Given passing 71 | Scenario: 72 | Given failing 73 | """ 74 | When I run "behave --format=plain features/issue64_case3.feature" 75 | Then it should fail with: 76 | """ 77 | 0 features passed, 1 failed, 0 skipped 78 | 2 scenarios passed, 1 failed, 0 skipped 79 | """ 80 | 81 | Scenario: Failing in First and Last Scenario 82 | Given a file named "features/issue64_case4.feature" with: 83 | """ 84 | Feature: Failing in First and Last Scenario 85 | Scenario: 86 | Given failing 87 | Scenario: 88 | Given passing 89 | Scenario: 90 | Given failing 91 | """ 92 | When I run "behave --format=plain features/issue64_case4.feature" 93 | Then it should fail with: 94 | """ 95 | 0 features passed, 1 failed, 0 skipped 96 | 1 scenario passed, 2 failed, 0 skipped 97 | """ 98 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0065.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #65 Unrecognized --tag-help argument 3 | 4 | The "behave --help" output refers to the option "--tag-help" 5 | in the description of the "--tags" option. 6 | The correct option for more help on tags is "--tags-help". 7 | 8 | Scenario: Ensure environment assumptions are correct (Sanity Check) 9 | Given a new working directory 10 | When I run "behave --help" 11 | Then the command output should contain: 12 | """ 13 | --tags-help 14 | """ 15 | But the command output should not contain: 16 | """ 17 | --tag-help 18 | """ 19 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0066.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #66: context.text and context.table are not cleared 3 | 4 | I noticed that context.table and context.text survive after the step is finished. 5 | 6 | 7 | Background: Test Setup 8 | Given a new working directory 9 | And a file named "features/steps/steps.py" with: 10 | """ 11 | from behave import given, when, then 12 | from hamcrest import assert_that, equal_to, is_not, is_, none 13 | 14 | @given(u'a step with multiline text') 15 | def step(context): 16 | assert context.text is not None 17 | assert context.text, "Ensure non-empty" 18 | assert isinstance(context.text, basestring) 19 | 20 | @given(u'a step with a table') 21 | def step(context): 22 | assert context.table is not None 23 | 24 | @when(u'I check the "context.{name}" attribute') 25 | def step(context, name): 26 | context.name = name 27 | context.value = getattr(context, name, None) 28 | 29 | @then(u'its value is None') 30 | def step(context): 31 | assert_that(context.value, is_(none())) 32 | 33 | @then(u'its value is "{value}"') 34 | def step(context, value): 35 | assert_that(context.value, equal_to(value)) 36 | 37 | @then(u'its value is not "{value}"') 38 | def step(context, value): 39 | assert_that(value, is_not(equal_to(context.value))) 40 | """ 41 | 42 | Scenario: Ensure multiline text data is cleared for next step 43 | Given a file named "features/issue66_case1.feature" with: 44 | """ 45 | Feature: 46 | Scenario: 47 | Given a step with multiline text: 48 | ''' 49 | Alice, Bob and Charly 50 | ''' 51 | When I check the "context.text" attribute 52 | Then its value is not "Alice, Bob and Charly" 53 | But its value is None 54 | """ 55 | When I run "behave -f plain features/issue66_case1.feature" 56 | Then it should pass with: 57 | """ 58 | 1 scenario passed, 0 failed, 0 skipped 59 | 4 steps passed, 0 failed, 0 skipped, 0 undefined 60 | """ 61 | 62 | Scenario: Ensure table data is cleared for next step 63 | Given a file named "features/issue66_case2.feature" with: 64 | """ 65 | Feature: 66 | Scenario: 67 | Given a step with a table: 68 | | name | gender | 69 | | Alice | female | 70 | | Bob | male | 71 | When I check the "context.table" attribute 72 | Then its value is None 73 | """ 74 | When I run "behave -f plain features/issue66_case2.feature" 75 | Then it should pass with: 76 | """ 77 | 1 scenario passed, 0 failed, 0 skipped 78 | 3 steps passed, 0 failed, 0 skipped, 0 undefined 79 | """ 80 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0067.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #67: JSON formatter cannot serialize tables. 3 | 4 | The JSON formatter cannot handle tables (currently): 5 | 6 | * Table as setup/intermediate/result table in steps of scenario 7 | * Examples tables in a ScenarioOutline 8 | 9 | A JSON exception occurs when such a feature file should be processed. 10 | 11 | 12 | Scenario: Scenario with Tables 13 | Given a new working directory 14 | And a file named "features/steps/steps1.py" with: 15 | """ 16 | from behave import given, when, then 17 | 18 | @given(u'I add the following employees') 19 | def step(context): 20 | pass # -- SKIP: Table processing here. 21 | 22 | @when(u'I select department "{department}"') 23 | def step(context, department): 24 | context.department = department 25 | 26 | @then(u'I get the following employees') 27 | def step(context): 28 | pass # -- SKIP: Table processing here. 29 | """ 30 | And a file named "features/issue67_case1.feature" with: 31 | """ 32 | Feature: Scenario with Tables 33 | Scenario: 34 | Given I add the following employees: 35 | | name | department | 36 | | Alice | Wonderland | 37 | | Bob | Moonwalk | 38 | When I select department "Wonderland" 39 | Then I get the following employees: 40 | | name | department | 41 | | Alice | Wonderland | 42 | """ 43 | When I run "behave -f json features/issue67_case1.feature" 44 | Then it should pass with: 45 | """ 46 | 1 scenario passed, 0 failed, 0 skipped 47 | 3 steps passed, 0 failed, 0 skipped, 0 undefined 48 | """ 49 | But the command output should not contain: 50 | """ 51 | TypeError: is not JSON serializable 52 | """ 53 | 54 | Scenario: ScenarioOutline with Examples Table 55 | Given a file named "features/steps/steps2.py" with: 56 | """ 57 | from behave import given, when, then 58 | 59 | @given(u'a step with "{name}"') 60 | def step(context, name): 61 | context.name = name 62 | 63 | @when(u'a step with "{name}" occurs') 64 | def step(context, name): 65 | assert context.name == name 66 | 67 | @then(u'a step with "{name}" is reached') 68 | def step(context, name): 69 | assert context.name == name 70 | """ 71 | And a file named "features/issue67_case2.feature" with: 72 | """ 73 | Feature: ScenarioOutline with Examples Table 74 | Scenario Outline: 75 | Given a step with "" 76 | When a step with "" occurs 77 | Then a step with "" is reached 78 | 79 | Examples: 80 | |name | 81 | |Alice| 82 | |Bob | 83 | """ 84 | When I run "behave -f json features/issue67_case2.feature" 85 | Then it should pass with: 86 | """ 87 | 2 scenarios passed, 0 failed, 0 skipped 88 | 6 steps passed, 0 failed, 0 skipped, 0 undefined 89 | """ 90 | 91 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0069.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #69: JUnitReporter: Fault when processing ScenarioOutlines with failing steps 3 | 4 | The problem occurs when "behave --junit ..." is used 5 | And a feature contains one or more ScenarioOutline(s) with failing steps. 6 | 7 | The JUnitReport does not process ScenarioOutline correctly (logic-error). 8 | Therefore, Scenarios of a ScenarioOutline are processes as Scenario steps. 9 | This causes problems when the step.status is "failed". 10 | 11 | RELATED: 12 | * issue #63 13 | 14 | Background: Test Setup 15 | Given a new working directory 16 | And a file named "features/steps/steps.py" with: 17 | """ 18 | from behave import given 19 | 20 | @given(u'a {outcome} step with "{name}"') 21 | def step(context, outcome, name): 22 | context.name = name 23 | assert outcome == "passing" 24 | 25 | @when(u'a {outcome} step with "{name}" occurs') 26 | def step(context, outcome, name): 27 | assert outcome == "passing" 28 | assert context.name == name 29 | 30 | @then(u'a {outcome} step with "{name}" is reached') 31 | def step(context, outcome, name): 32 | assert outcome == "passing" 33 | assert context.name == name 34 | """ 35 | 36 | Scenario: ScenarioOutline with Failing Steps 37 | Given a file named "features/issue63_case2.feature" with: 38 | """ 39 | Feature: ScenarioOutline with Passing and Failing Steps 40 | Scenario Outline: 41 | Given a passing step with "" 42 | When a failing step with "" occurs 43 | Then a passing step with "" is reached 44 | 45 | Examples: 46 | |name | 47 | |Alice| 48 | |Bob | 49 | """ 50 | When I run "behave -c --junit features/issue63_case2.feature" 51 | Then it should fail with: 52 | """ 53 | 0 scenarios passed, 2 failed, 0 skipped 54 | 2 steps passed, 2 failed, 2 skipped, 0 undefined 55 | """ 56 | But the command output should not contain: 57 | """ 58 | AttributeError: 'Scenario' object has no attribute 'exception' 59 | """ 60 | And the command output should not contain: 61 | """ 62 | behave/reporter/junit.py 63 | """ 64 | 65 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0072.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #72: Using 'GHERKIN_COLORS' fails with Exception 3 | 4 | > Trying: GHERKIN_COLORS=executing=white behave 5 | > It fails: 6 | > 7 | > Traceback (most recent call last): 8 | > ... 9 | > File "/.../behave/formatter/ansi_escapes.py", line 38, in 10 | > escapes[alias] = ''.join([colors[c] for c in aliases[alias].split(',')]) 11 | > TypeError: list indices must be integers, not str 12 | > 13 | > The reason is that the global variable colors is defined twice in this module. 14 | > The second variable overrides/modifies the first (without intention). 15 | 16 | 17 | Scenario: Using GHERKIN_COLORS in new working dir 18 | Given a new working directory 19 | And I set the environment variable "GHERKIN_COLORS" to "executing=white" 20 | When I run "behave" 21 | Then it should fail with: 22 | """ 23 | No steps directory in "{__WORKDIR__}/features" 24 | """ 25 | But the command output should not contain: 26 | """ 27 | Traceback (most recent call last): 28 | """ 29 | And the command output should not contain: 30 | """ 31 | TypeError: list indices must be integers, not str 32 | """ 33 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0075.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #75: behave @features_from_text_file does not work 3 | 4 | | Feature of Cucumber. Reading the source code, I see it partly implemented. 5 | | 6 | | $ behave @list_of_features.txt 7 | | https://github.com/jeamland/behave/blob/master/behave/runner.py#L416:L430 8 | | 9 | | However it fails because: 10 | | * it does not remove the @ from the path 11 | | * it does not search the steps/ directory in the parents of the feature files themselves 12 | 13 | 14 | @reuse.colocated_test 15 | Scenario: Use feature listfile 16 | Given I use the current directory as working directory 17 | When I run "behave -f plain features/runner.feature_listfile.feature" 18 | Then it should pass 19 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0077.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #77: Does not capture stdout from sub-processes 3 | 4 | | My step functions are using wrapper objects to interact with SUT. 5 | | Those wrappers use this kind of thing to invoke executables: 6 | | 7 | | subprocess.check_call('myprog', ..., stderr=subprocess.STDOUT) 8 | | 9 | | However, the output from those calls does not appear in the stdout 10 | | captured by behave when a step fails. 11 | 12 | 13 | Background: Test Setup 14 | Given a new working directory 15 | Given a file named "hello.py" with: 16 | """ 17 | import sys 18 | 19 | def hello(): 20 | result = 0 21 | args = sys.argv[1:] 22 | if args and args[0].startswith("--fail"): 23 | result = 1 24 | args = args[1:] 25 | message = " ".join(args) 26 | sys.stdout.write("Hello {0}\n".format(message)) 27 | sys.exit(result) 28 | 29 | if __name__ == "__main__": 30 | hello() 31 | """ 32 | And a file named "features/steps/subprocess_call_steps.py" with: 33 | """ 34 | from behave import given, when, then 35 | import subprocess 36 | import os.path 37 | import sys 38 | 39 | PYTHON = sys.executable 40 | HERE = os.path.dirname(__file__) 41 | 42 | @when(u'I make a subprocess call "hello {commandline}"') 43 | def step(context, commandline): 44 | result = subprocess_call_hello(commandline.split()) 45 | assert result == 0 46 | 47 | def subprocess_call_hello(args): 48 | command_args = [ PYTHON, "hello.py" ] + args 49 | result = subprocess.check_call(command_args, stderr=subprocess.STDOUT) 50 | return result 51 | # result = subprocess.check_output(command_args, stderr=subprocess.STDOUT) 52 | # return result 53 | """ 54 | 55 | Scenario: Subprocess call shows generated output 56 | Given a file named "features/issue77_hello_OK.feature" with: 57 | """ 58 | Feature: 59 | Scenario: 60 | When I make a subprocess call "hello world." 61 | """ 62 | When I run "behave -f plain features/issue77_hello_OK.feature" 63 | Then it should pass with: 64 | """ 65 | 1 scenario passed, 0 failed, 0 skipped 66 | 1 step passed, 0 failed, 0 skipped, 0 undefined 67 | """ 68 | And the command output should contain: 69 | """ 70 | Hello world. 71 | """ 72 | 73 | Scenario: Subprocess call fails with captured output 74 | Given a file named "features/issue77_hello_FAIL.feature" with: 75 | """ 76 | Feature: 77 | Scenario: 78 | When I make a subprocess call "hello --fail FAIL." 79 | """ 80 | When I run "behave -f plain features/issue77_hello_FAIL.feature" 81 | Then it should fail with: 82 | """ 83 | 0 scenarios passed, 1 failed, 0 skipped 84 | 0 steps passed, 1 failed, 0 skipped, 0 undefined 85 | """ 86 | And the command output should contain: 87 | """ 88 | Hello FAIL. 89 | """ 90 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0080.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #80: source file names not properly printed with python3 3 | 4 | | $ behave -f pretty example/example.feature 5 | | Scenario: run a simple test # example/example.feature:3 6 | | Given we have behave installed # :3 7 | | When we implement a test # :7 8 | | Then behave will test it for us! # :11 9 | 10 | 11 | Background: Test Setup 12 | Given a new working directory 13 | And a file named "features/steps/steps.py" with: 14 | """ 15 | from behave import given, when, then 16 | 17 | @given(u'a step passes') 18 | def step(context): 19 | pass 20 | 21 | @when(u'a step passes') 22 | def step(context): 23 | pass 24 | 25 | @then(u'a step passes') 26 | def step(context): 27 | pass 28 | """ 29 | And a file named "features/basic.feature" with: 30 | """ 31 | Feature: 32 | Scenario: 33 | Given a step passes 34 | When a step passes 35 | Then a step passes 36 | """ 37 | 38 | Scenario: Show step locations 39 | When I run "behave -c -f pretty --no-timings features/basic.feature" 40 | Then it should pass 41 | And the command output should contain: 42 | """ 43 | Feature: # features/basic.feature:1 44 | Scenario: # features/basic.feature:2 45 | Given a step passes # features/steps/steps.py:3 46 | When a step passes # features/steps/steps.py:7 47 | Then a step passes # features/steps/steps.py:11 48 | """ 49 | And the command output should not contain "# :" 50 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0083.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #83: behave.__main__:main() Various sys.exit issues 3 | 4 | | Currently, the main function has several issues related 5 | | to sys.exit() returncode usage: 6 | | 7 | | 1. sys.exit("string") is invalid, a number must be used: 8 | | => Used in exception cases after run (ParseError, ConfigError) 9 | | 10 | | 2. On success, the main() function returns implicitly None 11 | | instead of using sys.exit(0) 12 | | => No statement at end of function after failed case. 13 | 14 | @setup 15 | Scenario: Feature Setup 16 | Given a new working directory 17 | And a file named "features/steps/steps.py" with: 18 | """ 19 | from behave import step 20 | 21 | @step(u'a step passes') 22 | def step_passes(context): 23 | pass 24 | """ 25 | 26 | Scenario: Successful test run 27 | Given a file named "features/passing.feature" with: 28 | """ 29 | Feature: 30 | Scenario: 31 | Given a step passes 32 | When a step passes 33 | Then a step passes 34 | """ 35 | When I run "behave -c features/passing.feature" 36 | Then it should pass 37 | And the command returncode is "0" 38 | 39 | Scenario: ParseError occurs 40 | Given a file named "features/invalid_with_ParseError.feature" with: 41 | """ 42 | Feature: 43 | Scenario: Invalid scenario which raises ParseError 44 | Given a step passes 45 | When2 a step passes 46 | """ 47 | When I run "behave -c features/invalid_with_ParseError.feature" 48 | Then it should fail 49 | And the command returncode is non-zero 50 | And the command output should contain: 51 | """ 52 | Failed to parse "{__WORKDIR__}/features/invalid_with_ParseError.feature" 53 | """ 54 | 55 | Scenario: ConfigError occurs 56 | Given a new working directory 57 | And a file named "features/passing2.feature" with: 58 | """ 59 | Feature: 60 | Scenario: 61 | Given a step passes 62 | """ 63 | When I run "behave -c features/passing2.feature" 64 | Then it should fail 65 | And the command returncode is non-zero 66 | And the command output should contain: 67 | """ 68 | No steps directory in "{__WORKDIR__}/features" 69 | """ 70 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0084.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #84: behave.runner behave does not reliably detected failed test runs 3 | 4 | | Behave does currently not reliably detected failed test runs and 5 | | therefore returns not sys.exit(1) at end of main(). 6 | | 7 | | 1. behave.runner:Runner.run_with_paths() returns failed==True 8 | | if last feature was successful and test runner does not stop 9 | | after first failing feature. 10 | | 11 | | 2. Issue #64: Same problem in behave.model.Feature.run() with scenarios 12 | 13 | Scenario: Test Setup 14 | Given a new working directory 15 | And a file named "features/passing.feature" with: 16 | """ 17 | Feature: Passing 18 | Scenario: 19 | Given a step passes 20 | When a step passes 21 | Then a step passes 22 | """ 23 | And a file named "features/failing.feature" with: 24 | """ 25 | Feature: Failing 26 | Scenario: 27 | Given a step fails 28 | When a step fails 29 | Then a step fails 30 | """ 31 | And a file named "features/steps/steps.py" with: 32 | """ 33 | from behave import step 34 | 35 | @step(u'a step passes') 36 | def step_passes(context): 37 | pass 38 | 39 | @step(u'a step fails') 40 | def step_fails(context): 41 | assert False, "step: a step fails" 42 | """ 43 | 44 | Scenario: First feature fails, second feature passes 45 | When I run "behave -f plain features/failing.feature features/passing.feature" 46 | Then it should fail with: 47 | """ 48 | 1 feature passed, 1 failed, 0 skipped 49 | 1 scenario passed, 1 failed, 0 skipped 50 | 3 steps passed, 1 failed, 2 skipped, 0 undefined 51 | """ 52 | 53 | Scenario: First feature passes, second feature fails 54 | When I run "behave -f plain features/passing.feature features/failing.feature" 55 | Then it should fail with: 56 | """ 57 | 1 feature passed, 1 failed, 0 skipped 58 | 1 scenario passed, 1 failed, 0 skipped 59 | 3 steps passed, 1 failed, 2 skipped, 0 undefined 60 | """ 61 | 62 | Scenario: First feature passes, second fails, last passes 63 | When I run "behave -f plain features/passing.feature features/failing.feature features/passing.feature" 64 | Then it should fail with: 65 | """ 66 | 2 features passed, 1 failed, 0 skipped 67 | 2 scenarios passed, 1 failed, 0 skipped 68 | 6 steps passed, 1 failed, 2 skipped, 0 undefined 69 | """ 70 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0092.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #92: Output from --format=plain shows skipped steps in next scenario 3 | 4 | | DUPLICATED, FIXED-BY: issue #35 solution. 5 | | 6 | | Given a feature has more than one scenario 7 | | When the --format=plain option is used 8 | | and a middle step of a scenario fails 9 | | Then the skipped steps appear under the next scenario 10 | 11 | 12 | Scenario: 13 | Given a new working directory 14 | And a file named "features/issue92_syndrome.feature" with: 15 | """ 16 | Feature: Testing Plain Output 17 | Reproduces bug where output from previous scenario appears before current. 18 | 19 | Scenario: First example 20 | Given this step works 21 | When this step fails 22 | Then this step appears in the wrong place 23 | 24 | Scenario: Second example 25 | Given this step works 26 | When this step fails 27 | Then this step appears in the wrong place 28 | """ 29 | And a file named "features/steps/steps.py" with: 30 | """ 31 | from behave import step 32 | 33 | @step(u'this step works') 34 | def working(context): 35 | pass 36 | 37 | 38 | @step(u'this step fails') 39 | def failing(context): 40 | assert False, 'step failed' 41 | 42 | 43 | @step(u'this step appears in the wrong place') 44 | def missing(context): 45 | pass 46 | """ 47 | When I run "behave --no-timings --format=plain features/issue92_syndrome.feature" 48 | Then it should fail with: 49 | """ 50 | 0 features passed, 1 failed, 0 skipped 51 | 0 scenarios passed, 2 failed, 0 skipped 52 | 2 steps passed, 2 failed, 2 skipped, 0 undefined 53 | """ 54 | And the command output should contain: 55 | """ 56 | Feature: Testing Plain Output 57 | Scenario: First example 58 | Given this step works ... passed 59 | When this step fails ... failed 60 | Assertion Failed: step failed 61 | 62 | Scenario: Second example 63 | Given this step works ... passed 64 | When this step fails ... failed 65 | Assertion Failed: step failed 66 | """ 67 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0109.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #109: Insists that implemented tests are not implemented 3 | 4 | | STATUS: Resolved, not a behave problem. 5 | | 6 | | Following feature file marks implemented step "when I submit the following data" 7 | | as not implemented. 8 | 9 | 10 | Scenario: 11 | Given a new working directory 12 | And a file named "features/syndrome109.feature" with: 13 | """ 14 | @wip 15 | Feature: Manage accounts from the admin interface 16 | 17 | Scenario: Login successfully via login form 18 | Given I navigate to "/admin/" 19 | when I submit the following data 20 | | name | value | 21 | | username | admin@foo.bar | 22 | | password | pass | 23 | then I see the word "Welcome" 24 | 25 | Scenario: Create user via admin user creation form 26 | Given I navigate to "/admin/users/user/add/" 27 | when I submit the following data 28 | | name | value | 29 | | email | spaaaaaaaaaaaaaaaaaaam@ham.eggs | 30 | | password1 | pass | 31 | | password2 | pass | 32 | then I see the word "successfully" 33 | """ 34 | And a file named "features/steps/steps.py" with: 35 | """ 36 | from behave import given, when, then 37 | 38 | @given(u'I navigate to "{url}"') 39 | def step_navigate_to_url(context, url): 40 | pass 41 | 42 | @when(u'I submit the following data') 43 | def step_submit_data(context): 44 | pass 45 | 46 | @then(u'I see the word "{word}"') 47 | def step_see_word(context, word): 48 | pass 49 | """ 50 | When I run "behave -w features/syndrome109.feature" 51 | Then it should pass with: 52 | """ 53 | 1 feature passed, 0 failed, 0 skipped 54 | 2 scenarios passed, 0 failed, 0 skipped 55 | 6 steps passed, 0 failed, 0 skipped, 0 undefined 56 | """ 57 | And the command output should not contain: 58 | """ 59 | You can implement step definitions for undefined steps with these snippets: 60 | """ 61 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0111.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #111: Comment following @wip tag results in scenario being ignored 3 | 4 | | If a comment is placed after the @wip tag, the following scenario 5 | | is ignored by behave: 6 | | 7 | | @wip # comment: this is work in progress 8 | | Scenario: test scenario 9 | | 10 | | results in behave -w not running the "test scenario". 11 | | After removing the comment, it runs as expected. 12 | 13 | 14 | Scenario: Test Setup 15 | Given a new working directory 16 | And a file named "features/steps/passing_steps.py" with: 17 | """ 18 | from behave import step 19 | 20 | @step(u'a step passes') 21 | def step_passes(context): 22 | pass 23 | """ 24 | And a file named "features/syndrome111.feature" with: 25 | """ 26 | Feature: 27 | 28 | @wip # Comment: blabla 29 | Scenario: S1 30 | Given a step passes 31 | 32 | @wip @one # Comment: foobar 33 | Scenario: S2 34 | Given a step passes 35 | """ 36 | 37 | Scenario: Scenario w/ comment on tag-line should run as normal 38 | When I run "behave --wip features/syndrome111.feature" 39 | Then it should pass with: 40 | """ 41 | 1 feature passed, 0 failed, 0 skipped 42 | 2 scenarios passed, 0 failed, 0 skipped 43 | 2 steps passed, 0 failed, 0 skipped, 0 undefined 44 | """ 45 | 46 | Scenario: Ensure 2nd scenario can be selected with other tag 47 | When I run "behave -f plain --tags=one features/syndrome111.feature" 48 | Then it should pass with: 49 | """ 50 | 1 feature passed, 0 failed, 0 skipped 51 | 1 scenario passed, 0 failed, 1 skipped 52 | 1 step passed, 0 failed, 1 skipped, 0 undefined 53 | """ 54 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0112.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | @change_request 3 | Feature: Issue #112: Improvement to AmbiguousStep error 4 | 5 | | AmbiguousStep could be more useful if it also showed the existing string 6 | | with which the new one is clashing. This is particularly useful 7 | | if using step parameters. 8 | 9 | 10 | Background: 11 | Given a new working directory 12 | And a file named "features/syndrome112.feature" with: 13 | """ 14 | Feature: 15 | Scenario: 16 | Given I buy 10 oranges 17 | """ 18 | 19 | Scenario: Good step ordering -- From specific to generic regular expression 20 | Given a file named "features/steps/good_steps.py" with: 21 | """ 22 | from behave import given, when, then 23 | 24 | # -- ORDERING-IMPORTANT: From more specific steps to less specific. 25 | @given(u'I buy {number:n} {items:w}') 26 | def step_given_I_buy2(context, number, items): 27 | pass 28 | 29 | # -- OTHERWISE: Generic step matches all other patterns. 30 | @given(u'I buy {amount} {product}') 31 | def step_given_I_buy(context, amount, product): 32 | pass 33 | """ 34 | When I run "behave -c features/syndrome112.feature" 35 | Then it should pass with: 36 | """ 37 | 1 feature passed, 0 failed, 0 skipped 38 | 1 scenario passed, 0 failed, 0 skipped 39 | 1 step passed, 0 failed, 0 skipped, 0 undefined 40 | """ 41 | 42 | 43 | Scenario: Bad step ordering causes AmbiguousStep 44 | Given a file named "features/steps/bad_steps.py" with: 45 | """ 46 | from behave import given, when, then 47 | 48 | # -- ORDERING-VIOLATED: Generic step comes first. 49 | @given(u'I buy {amount} {product}') 50 | def step_given_I_buy(context, amount, product): 51 | pass 52 | 53 | # -- AMBIGUOUS-STEP: Will occur here. 54 | @given(u'I buy {number:n} {items:w}') 55 | def step_given_I_buy2(context, number, items): 56 | pass 57 | """ 58 | When I run "behave -c features/syndrome112.feature" 59 | Then it should fail 60 | And the command output should contain: 61 | """ 62 | AmbiguousStep: @given('I buy {number:n} {items:w}') has already been defined in 63 | existing step @given('I buy {amount} {product}') at features/steps/bad_steps.py:4 64 | """ 65 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0116.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | @change_request 3 | Feature: Issue #116: SummaryReporter shows failed scenarios list 4 | 5 | Scenario: Test Setup 6 | Given a new working directory 7 | And a file named "features/steps/passing_failing_steps.py" with: 8 | """ 9 | from behave import step 10 | 11 | @step(u'a step passes') 12 | def step_passes(context): 13 | pass 14 | 15 | @step(u'a step fails') 16 | def step_fails(context): 17 | assert False, "FAILS" 18 | """ 19 | And a file named "features/e1.feature" with: 20 | """ 21 | Feature: E1 22 | 23 | Scenario: E1.1 24 | Given a step passes 25 | 26 | @xfail 27 | Scenario: E1.2 (XFAIL) 28 | Given a step fails 29 | 30 | Scenario: E1.3 31 | Given a step passes 32 | """ 33 | And a file named "features/e2.feature" with: 34 | """ 35 | @example2 36 | Feature: E2 37 | 38 | @xfail 39 | Scenario: E2.1 (XFAIL) 40 | Given a step fails 41 | 42 | Scenario: E2.2 43 | Given a step passes 44 | """ 45 | 46 | Scenario: Summary shows list of failed scenarios when at least one fails 47 | When I run "behave -f plain features/" 48 | Then it should fail 49 | And the command output should contain: 50 | """ 51 | Failing scenarios: 52 | features/e1.feature:7 E1.2 (XFAIL) 53 | features/e2.feature:5 E2.1 (XFAIL) 54 | 55 | 0 features passed, 2 failed, 0 skipped 56 | 3 scenarios passed, 2 failed, 0 skipped 57 | 3 steps passed, 2 failed, 0 skipped, 0 undefined 58 | """ 59 | 60 | Scenario: Summary hides list of failed scenarios when all scenarios pass 61 | When I run "behave -f plain --tags=~@xfail features/" 62 | Then it should pass with: 63 | """ 64 | 2 features passed, 0 failed, 0 skipped 65 | 3 scenarios passed, 0 failed, 2 skipped 66 | 3 steps passed, 0 failed, 2 skipped, 0 undefined 67 | """ 68 | But the command output should not contain: 69 | """ 70 | Failing scenarios: 71 | """ 72 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0125.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #125: Duplicate "Captured stdout" if substep has failed 3 | 4 | 5 | Background: Test Setup 6 | Given a new working directory 7 | And a file named "features/steps/steps.py" with: 8 | """ 9 | from behave import step 10 | 11 | @step('a step fails with stdout "{message}"') 12 | def step_fails_with_stdout(context, message): 13 | print(message) 14 | assert False, 'EXPECT: Step fails with stdout.' 15 | 16 | @step('substep fails with stdout "{message}"') 17 | def substep_fails_with_stdout(context, message): 18 | context.execute_steps(u'When a step fails with stdout "%s"' % message) 19 | """ 20 | 21 | Scenario: Subprocess call shows generated output 22 | Given a file named "features/issue125_example.feature" with: 23 | """ 24 | Feature: 25 | Scenario: 26 | When substep fails with stdout "Hello" 27 | """ 28 | When I run "behave -f plain --no-timings features/issue125_example.feature" 29 | Then it should fail with: 30 | """ 31 | 0 scenarios passed, 1 failed, 0 skipped 32 | 0 steps passed, 1 failed, 0 skipped, 0 undefined 33 | """ 34 | And the command output should not contain: 35 | """ 36 | Captured stdout: 37 | Hello 38 | 39 | Captured stdout: 40 | Hello 41 | """ 42 | But the command output should contain: 43 | """ 44 | Feature: 45 | Scenario: 46 | When substep fails with stdout "Hello" ... failed 47 | 48 | Assertion Failed: FAILED SUB-STEP: When a step fails with stdout "Hello" 49 | Substep info: Assertion Failed: EXPECT: Step fails with stdout. 50 | Captured stdout: 51 | Hello 52 | """ 53 | 54 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0127.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #127: Strip trailing colons 3 | 4 | | Trailing colon in a step is stripped by the Gherkin parser. 5 | | Undefined step snippets should not suggest the step with a trailing colon. 6 | | 7 | | GENERAL RULE (by looking at the parser): 8 | | 1. Colon in step in feature file is OK 9 | | (parser strips this for step-with-table or step-with-multiline-text). 10 | | 2. Step definitions in Python files should not end with a colon 11 | | (used in @given/@when/@then decorators). 12 | 13 | 14 | Background: 15 | Given a new working directory 16 | And a file named "features/example127.feature" with: 17 | """ 18 | Feature: 19 | Scenario: 20 | Given the following superusers exist: 21 | | Name | User Id | 22 | | Alice | 101 | 23 | | Bob | 102 | 24 | """ 25 | 26 | Scenario: Step Definition has no trailing colon (GOOD CASE) 27 | Given a file named "features/steps/good_steps.py" with: 28 | """ 29 | from behave import given 30 | 31 | @given(u'the following superusers exist') 32 | def step_given_following_superusers_exist(context): 33 | pass 34 | """ 35 | When I run "behave -f plain features/example127.feature" 36 | Then it should pass 37 | And the command output should not contain: 38 | """ 39 | You can implement step definitions for undefined steps with these snippets: 40 | 41 | @given(u'the following superusers exist:') 42 | def step_impl(context): 43 | assert False 44 | """ 45 | 46 | Scenario: Step Definition has trailing colon (BAD CASE) 47 | Given a file named "features/steps/bad_steps.py" with: 48 | """ 49 | from behave import given 50 | 51 | @given(u'the following superusers exist:') 52 | def step_given_following_superusers_exist(context): 53 | pass 54 | """ 55 | When I run "behave -f plain features/example127.feature" 56 | Then it should fail 57 | And the command output should contain: 58 | """ 59 | You can implement step definitions for undefined steps with these snippets: 60 | 61 | @given(u'the following superusers exist') 62 | def step_impl(context): 63 | assert False 64 | """ 65 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0139.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | @not_reproducible 3 | Feature: Issue #139: Wrong steps seem to be executed when using --wip 4 | 5 | | RELATED-TO: issue #35 6 | | behave --format=plain --tags @one" seems to execute right scenario w/ wrong steps 7 | | 8 | | If you have a feature file with two scenarios where the second is tagged 9 | | with @wip, running behave -w will output step names from the first scenario. 10 | | It does seem to run the correct code for the steps. 11 | 12 | 13 | Scenario: 14 | Given a new working directory 15 | And a file named "features/steps/steps.py" with: 16 | """ 17 | from behave import given, when, then, step 18 | 19 | @step('a step passes') 20 | def step_passes(context): 21 | pass 22 | 23 | @step('a step fails') 24 | def step_fails(context): 25 | assert False, "XFAIL" 26 | 27 | @when('I run a test step') 28 | def step_impl(context): 29 | pass 30 | 31 | @when('I run some other test step') 32 | def step_impl(context): 33 | pass 34 | 35 | @then('I should not see a failure here') 36 | def step_impl(context): 37 | pass 38 | """ 39 | And a file named "features/issue0139_example.feature" with: 40 | """ 41 | Feature: Bug in wip/behave -w 42 | 43 | Scenario: This is strange 44 | Given a step passes 45 | When a step passes 46 | Then a step fails 47 | 48 | @wip 49 | Scenario: Demonstrate bug 50 | When I run a test step 51 | And I run some other test step 52 | Then I should not see a failure here 53 | """ 54 | When I run "behave -w -f plain -T features/issue0139_example.feature" 55 | Then it should pass 56 | And the command output should contain: 57 | """ 58 | Feature: Bug in wip/behave -w 59 | Scenario: This is strange 60 | Scenario: Demonstrate bug 61 | When I run a test step ... passed 62 | And I run some other test step ... passed 63 | Then I should not see a failure here ... passed 64 | """ 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0142.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | @not_reproducible 3 | Feature: Issue #142: --junit flag fails to output with step table data: TypeError: is not JSON serializable 4 | 5 | DUPLICATES: issue #67 (already fixed). 6 | 7 | Scenario: 8 | Given a new working directory 9 | And a file named "features/steps/steps.py" with: 10 | """ 11 | from behave import given, when, then, step 12 | 13 | @then('use table data with') 14 | def step_impl(context): 15 | pass 16 | """ 17 | And a file named "features/issue0142_example.feature" with: 18 | """ 19 | Feature: 20 | Scenario: Use a table 21 | Then use table data with: 22 | | data | value | 23 | | behave outputs junit with tables | false | 24 | """ 25 | When I run "behave --junit -f json features/issue0142_example.feature" 26 | Then it should pass 27 | But the command output should not contain: 28 | """ 29 | TypeError: is not JSON serializable 30 | """ 31 | And the command output should not contain: 32 | """ 33 | Traceback (most recent call last): 34 | """ 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0143.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #143: Logging starts with a StreamHandler way too early 3 | 4 | | This verifies that some imported library or other item has not made a 5 | | call to logging too soon, which would add a StreamHandler. 6 | 7 | 8 | @setup 9 | Scenario: Feature Setup 10 | Given a new working directory 11 | And a file named "features/steps/steps.py" with: 12 | """ 13 | import logging 14 | from behave import given, when, then, step 15 | 16 | @step('I create {count:n} log records') 17 | def step_create_log_records(context, count): 18 | for i in range(count): 19 | logging.debug('Some debug logging') 20 | """ 21 | And a file named "features/issue0143_example.feature" with: 22 | """ 23 | Feature: Logging should not be output unless there is a failure 24 | 25 | Scenario: A passing test 26 | Given I create 4 log records 27 | """ 28 | 29 | Scenario: Ensure that no log-ouput occurs with enabled log-capture 30 | Given an empty file named "features/environment.py" 31 | When I run "behave -f plain --logcapture features/issue0143_example.feature" 32 | Then it should pass 33 | And the command output should not contain: 34 | """ 35 | DEBUG:root:Some debug logging 36 | """ 37 | 38 | 39 | Scenario: Ensure that log-ouput occurs with disabled log-capture 40 | Given a file named "features/environment.py" with: 41 | """ 42 | import logging 43 | 44 | def before_all(context): 45 | # -- basicConfig() will not set level if setup is already done. 46 | logging.basicConfig() 47 | logging.getLogger().setLevel(logging.DEBUG) 48 | """ 49 | When I run "behave -f plain --no-logcapture features/issue0143_example.feature" 50 | Then it should pass 51 | And the command output should contain: 52 | """ 53 | DEBUG:root:Some debug logging 54 | """ 55 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0145.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #145: before_feature/after_feature should not be skipped 3 | 4 | | Hooks before_feature(), after_feature() (and before_step()) are skipped 5 | | if --tags options select feature tag and scenario tag. 6 | | 7 | | SEE ALSO: https://github.com/cucumber/cucumber/wiki/Tags 8 | 9 | @setup 10 | Scenario: Setup 11 | Given a new working directory 12 | And a file named "features/steps/steps.py" with: 13 | """ 14 | from behave import step 15 | 16 | @step('a step passes') 17 | def step_passes(context): 18 | pass 19 | """ 20 | And a file named "features/issue0145_example.feature" with: 21 | """ 22 | @feature 23 | Feature: Feature-145 24 | 25 | @scenario 26 | Scenario: Scenario-145 27 | Given a step passes 28 | When a step passes 29 | Then a step passes 30 | """ 31 | And a file named "features/environment.py" with: 32 | """ 33 | from __future__ import print_function 34 | 35 | def before_feature(context, feature): 36 | print("hooks.before_feature: %s called." % feature.name) 37 | 38 | def after_feature(context, feature): 39 | print("hooks.after_feature: %s called." % feature.name) 40 | """ 41 | 42 | Scenario: Select only @scenario tag 43 | When I run "behave -f plain -T --tags=@scenario features/issue0145_example.feature" 44 | Then it should pass with: 45 | """ 46 | 1 feature passed, 0 failed, 0 skipped 47 | 1 scenario passed, 0 failed, 0 skipped 48 | 3 steps passed, 0 failed, 0 skipped, 0 undefined 49 | """ 50 | And the behave hook "before_feature" was called 51 | And the behave hook "after_feature" was called 52 | 53 | Scenario: Select @feature tag and @scenario tag (logical-and, fails if not fixed) 54 | When I run "behave -f plain -T --tags=@feature --tags=@scenario features/issue0145_example.feature" 55 | Then it should pass with: 56 | """ 57 | 1 feature passed, 0 failed, 0 skipped 58 | 1 scenario passed, 0 failed, 0 skipped 59 | 3 steps passed, 0 failed, 0 skipped, 0 undefined 60 | """ 61 | And the behave hook "before_feature" was called 62 | And the behave hook "after_feature" was called 63 | 64 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0152.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #152: Fix encoding issues 3 | 4 | | I fixed two encoding issues in pretty formatter and in JUnit serialization. 5 | | Now it's possible to use accented letters in feature files and 6 | | create JUnit reports from the tests. 7 | 8 | 9 | Scenario: Ensure JUnit reports can be created from a foreign language 10 | Given a new working directory 11 | And an empty file named "features/steps/steps.py" 12 | And a file named "features/eins.feature" with: 13 | """ 14 | # language: de 15 | Funktionalität: Die Welt ist schön 16 | Szenario: Was wäre wenn die schöne, neue Welt untergeht 17 | """ 18 | When I run "behave -f plain --junit --no-timings features/eins.feature" 19 | Then it should pass with: 20 | """ 21 | 1 feature passed, 0 failed, 0 skipped 22 | 1 scenario passed, 0 failed, 0 skipped 23 | 0 steps passed, 0 failed, 0 skipped, 0 undefined 24 | """ 25 | And the command output should contain: 26 | """ 27 | Funktionalität: Die Welt ist schön 28 | Szenario: Was wäre wenn die schöne, neue Welt untergeht 29 | """ 30 | 31 | 32 | @reuse.colocated_test 33 | Scenario: Ensure JUnit reports can be created from a foreign language 34 | Given I use the current directory as working directory 35 | When I run "behave -f plain --junit --no-timings tools/test-features/french.feature" 36 | Then it should pass with: 37 | """ 38 | 1 feature passed, 0 failed, 0 skipped 39 | 2 scenarios passed, 0 failed, 0 skipped 40 | 5 steps passed, 0 failed, 0 skipped, 0 undefined 41 | """ 42 | And the command output should contain: 43 | """ 44 | Fonctionnalité: testing stuff 45 | Scénario: test stuff 46 | Etant donné I am testing stuff ... passed 47 | Quand I exercise it work ... passed 48 | Alors it will work ... passed 49 | Scénario: test more stuff 50 | Etant donné I am testing stuff ... passed 51 | Alors it will work ... passed 52 | """ 53 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0159.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #159: output stream is wrapped twice in the codecs.StreamWriter 3 | 4 | @setup 5 | Scenario: Feature Setup 6 | Given a new working directory 7 | And a file named "features/steps/steps.py" with: 8 | """ 9 | # -*- coding: utf-8 -*- 10 | from behave import step 11 | 12 | @step('firstname is "{name}"') 13 | def step_impl(context, name): 14 | pass 15 | 16 | @step(u'full name is Loïc "{name}"') 17 | def step_impl(context, name): 18 | pass 19 | """ 20 | 21 | Scenario: Single feature, pass (a) 22 | Given a file named "features/issue159_stream_writer.feature" with: 23 | """ 24 | Feature: 25 | Scenario: 26 | When firstname is "Loïc" 27 | """ 28 | When I run "behave -f plain features/" 29 | Then it should pass 30 | 31 | 32 | Scenario: Single feature, pass (b) 33 | Given a file named "features/issue159_stream_writer.feature" with: 34 | """ 35 | Feature: 36 | Scenario: 37 | When full name is Loïc "Dupont" 38 | """ 39 | When I run "behave -f plain features/" 40 | Then it should pass 41 | 42 | 43 | Scenario: Two features, FAIL (a) 44 | Given a file named "features/issue159_stream_writer.feature" with: 45 | """ 46 | Feature: 47 | Scenario: 48 | When full name is Loïc "Dupont" 49 | """ 50 | And a file named "features/issue159_stream_writer_again.feature" with: 51 | """ 52 | Feature: 53 | Scenario: 54 | When full name is Loïc "Dupond" 55 | """ 56 | When I run "behave -f plain features/" 57 | Then it should pass 58 | 59 | 60 | Scenario: Two features, FAIL (b) 61 | Given a file named "features/issue159_stream_writer.feature" with: 62 | """ 63 | Feature: 64 | Scenario: 65 | When firstname is "Loïc" 66 | """ 67 | And a file named "features/issue159_stream_writer_again.feature" with: 68 | """ 69 | Feature: 70 | Scenario: 71 | When firstname is "Loïc" 72 | """ 73 | When I run "behave -f plain features/" 74 | Then it should pass 75 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0162.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #162 Unnecessary ContextMaskWarnings when assert fails or exception is raised 3 | 4 | | Behave shows unnecessary ContextMaskWarnings related to: 5 | | 6 | | * tags 7 | | * capture_stdout 8 | | * capture_stderr 9 | | * log_capture 10 | | 11 | | if: 12 | | 13 | | * an assertion fails in a step-definition/step-function 14 | | * an exception is raised by a step-definition/step-function 15 | | 16 | | and an additional scenario follows. 17 | | REASON: Context "behave" mode is not restored when an exception is raised. 18 | 19 | 20 | @setup 21 | Scenario: Feature Setup 22 | Given a new working directory 23 | And a file named "features/steps/steps.py" with: 24 | """ 25 | from behave import step 26 | 27 | @step('a step passes') 28 | def step_passes(context): 29 | pass 30 | 31 | @step('a step assert fails') 32 | def step_assert_fails(context): 33 | assert False, "XFAIL-STEP" 34 | 35 | @step('an exception is raised') 36 | def step_raises_exception(context): 37 | raise RuntimeError("XFAIL-STEP") 38 | """ 39 | 40 | 41 | Scenario: Assertion fails in a step 42 | Given a file named "features/example0162_assert_fails.feature" with: 43 | """ 44 | Feature: 45 | Scenario: 46 | Given a step passes 47 | When a step assert fails 48 | Then a step passes 49 | 50 | Scenario: 51 | Given a step passes 52 | """ 53 | When I run "behave -f plain features/example0162_assert_fails.feature" 54 | Then it should fail with: 55 | """ 56 | 1 scenario passed, 1 failed, 0 skipped 57 | 2 steps passed, 1 failed, 1 skipped, 0 undefined 58 | """ 59 | But the command output should not contain: 60 | """ 61 | ContextMaskWarning: user code is masking context attribute 62 | """ 63 | 64 | 65 | Scenario: Exception is raised in a step 66 | Given a file named "features/example0162_exception_raised.feature" with: 67 | """ 68 | Feature: 69 | Scenario: 70 | Given a step passes 71 | When an exception is raised 72 | Then a step passes 73 | 74 | Scenario: 75 | Given a step passes 76 | """ 77 | When I run "behave -f plain features/example0162_exception_raised.feature" 78 | Then it should fail with: 79 | """ 80 | 1 scenario passed, 1 failed, 0 skipped 81 | 2 steps passed, 1 failed, 1 skipped, 0 undefined 82 | """ 83 | But the command output should not contain: 84 | """ 85 | ContextMaskWarning: user code is masking context attribute 86 | """ 87 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0171.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #171: Importing step from other step file fails with AmbiguousStep Error 3 | 4 | | When a step module imports another step module 5 | | this should not cause AmbiguousStep errors 6 | | due to duplicated registration of the same step functions. 7 | | 8 | | NOTES: 9 | | * In general you should avoid this case (provided as example here). 10 | 11 | 12 | @reuse.colocated_test 13 | Scenario: Step module imports other step module 14 | Given I use the current directory as working directory 15 | When I run "behave -f plain features/step.import_other_step_module.feature" 16 | Then it should pass 17 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0172.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #172 Junit report file name populated incorrectly when running against a feature file 3 | 4 | @setup 5 | Scenario: Feature Setup 6 | Given a new working directory 7 | And a file named "features/steps/steps.py" with: 8 | """ 9 | from behave import step 10 | 11 | @step('a step passes') 12 | def step_passes(context): 13 | pass 14 | """ 15 | And a file named "features/feature_in_root_folder.feature" with: 16 | """ 17 | Feature: 18 | Scenario: 19 | Given a step passes 20 | """ 21 | And a file named "features/subfolder/feature_in_subfolder.feature" with: 22 | """ 23 | Feature: 24 | Scenario: 25 | Given a step passes 26 | """ 27 | 28 | Scenario: Running behave for one feature in root folder 29 | When I run "behave --junit --junit-directory=test_results features/feature_in_root_folder.feature" 30 | Then it should pass with: 31 | """ 32 | 1 feature passed, 0 failed, 0 skipped 33 | """ 34 | And a file named "test_results/TESTS-feature_in_root_folder.xml" exists 35 | 36 | Scenario: Running behave for one feature in a subfolder 37 | When I run "behave --junit --junit-directory=test_results features/subfolder/feature_in_subfolder.feature" 38 | Then it should pass with: 39 | """ 40 | 1 feature passed, 0 failed, 0 skipped 41 | """ 42 | And a file named "test_results/TESTS-subfolder.feature_in_subfolder.xml" exists 43 | 44 | Scenario: Running behave for all features 45 | When I run "behave --junit --junit-directory=test_results" 46 | Then it should pass with: 47 | """ 48 | 2 features passed, 0 failed, 0 skipped 49 | """ 50 | And a file named "test_results/TESTS-feature_in_root_folder.xml" exists 51 | And a file named "test_results/TESTS-subfolder.feature_in_subfolder.xml" exists 52 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0175.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #175: Scenario isn't marked as 'failed' when Background step fails 3 | 4 | Scenario has currently status "skipped" when a background step fails. 5 | Expected is that scenario status should be "failed". 6 | Ensure that this is the case. 7 | 8 | RELATED: features/background.feature 9 | REUSE: Scenario from there (as copy). 10 | 11 | | NOTE: 12 | | Cucumber has a slightly different behaviour. 13 | | When a background step fails the first scenario is marked as failed. 14 | | But the remaining scenarios are marked as skipped. 15 | | 16 | | This can lead to problems when you have sporadic background step failures. 17 | | For this reason, behave retries the background steps for each scenario. 18 | | 19 | | SEE ALSO: 20 | | * https://github.com/cucumber/cucumber/blob/master/features/docs/gherkin/background.feature 21 | 22 | 23 | @setup 24 | Scenario: Feature Setup 25 | Given a new working directory 26 | And a file named "features/steps/background_steps.py" with: 27 | """ 28 | from behave import step 29 | 30 | @step('{word} background step {outcome}') 31 | def step_background_step_passes_or_fails(context, word, outcome): 32 | if outcome == "fails": 33 | assert False, "XFAIL: background step" 34 | elif outcome == "passes": 35 | pass 36 | else: 37 | message = "Unexpected outcome=%s. Use: passes, fails" 38 | raise RuntimeError(message % outcome) 39 | """ 40 | And a file named "features/steps/passing_steps.py" with: 41 | """ 42 | from behave import step 43 | 44 | @step('{word} step passes') 45 | def step_passes(context, word): 46 | pass 47 | 48 | @step('{word} step fails') 49 | def step_passes(context, word): 50 | assert False, "XFAIL" 51 | """ 52 | 53 | 54 | Scenario: Failing Background Step causes all Scenarios to fail 55 | Given a file named "features/example.background_step_fails.feature" with: 56 | """ 57 | Feature: 58 | 59 | Background: B1 60 | Given a background step passes 61 | And a background step fails 62 | And another background step passes 63 | 64 | Scenario: S1 65 | When a step passes 66 | 67 | Scenario: S2 68 | Then a step passes 69 | And another step passes 70 | """ 71 | When I run "behave -f plain -T features/example.background_step_fails.feature" 72 | Then it should fail with: 73 | """ 74 | 0 scenarios passed, 2 failed, 0 skipped 75 | 2 steps passed, 2 failed, 5 skipped, 0 undefined 76 | """ 77 | And the command output should contain: 78 | """ 79 | Feature: 80 | Background: B1 81 | 82 | Scenario: S1 83 | Given a background step passes ... passed 84 | And a background step fails ... failed 85 | Assertion Failed: XFAIL: background step 86 | 87 | Scenario: S2 88 | Given a background step passes ... passed 89 | And a background step fails ... failed 90 | Assertion Failed: XFAIL: background step 91 | """ 92 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0177.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #177: Cannot setup logging_format 3 | 4 | | DESCPRIPTION: 5 | | When the logging_format is set in the behave configuration file 6 | | or on command-line, an exception is thrown, because 7 | | the ConfigParser tries to replace the placeholders in the format string 8 | | with option values in the configuration file (which do not exist). 9 | | 10 | | SOLUTION: 11 | | The format string must be processed as raw value (by the ConfigParser). 12 | | 13 | | RELATED: 14 | | * features/logging.setup_format.feature 15 | | * features/logging.setup_level.feature 16 | 17 | 18 | @reuse.colocated_test 19 | Scenario: Setup logging_format 20 | Given I use the current directory as working directory 21 | When I run "behave -f plain features/logging.setup_format.feature" 22 | Then it should pass 23 | And the command output should not contain: 24 | """ 25 | Traceback (most recent call last): 26 | """ 27 | And the command output should not contain: 28 | """ 29 | ConfigParser.InterpolationMissingOptionError: Bad value 30 | """ 31 | 32 | @reuse.colocated_test 33 | Scenario: Setup logging_level 34 | 35 | Ensure that the problem that was also mentioned, works as expected. 36 | Note that this "problem" never existed (hint: missing user knowledge). 37 | 38 | Given I use the current directory as working directory 39 | When I run "behave -f plain features/logging.setup_level.feature" 40 | Then it should pass 41 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0186.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #186: ScenarioOutline uses wrong return value when if fails 3 | 4 | ScenarioOutline returns encountered a failure only if the last scenario failed. 5 | Failures in earlier examples return the wrong result. 6 | Ensure that ScenarioOutline run-logic behaves as expected. 7 | 8 | @reuse.colocated_test 9 | Scenario: Reuse existing test 10 | Given I use the current directory as working directory 11 | When I run "behave -f plain features/scenario_outline.basics.feature" 12 | Then it should pass 13 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/issue0188.feature: -------------------------------------------------------------------------------- 1 | @issue 2 | Feature: Issue #188: Better diagnostics if nested step is undefined 3 | 4 | | Currently if nested step has no match, it's shown like this: 5 | | 6 | | Assertion Failed: Sub-step failed: When I do strange thign 7 | | Substep info: None 8 | | 9 | | Took some time to find that typo. 10 | | The suggestion is to fill substep error_message with at least "No match for step" 11 | | so it would become: 12 | | 13 | | Assertion Failed: Sub-step failed: When I do strange thign 14 | | Substep info: No match for step 15 | | 16 | | IMPLEMENTATION NOTE: 17 | | A slightly different output is provided: 18 | | 19 | | Assertion Failed: UNDEFINED SUB-STEP: When I do strange thign 20 | 21 | 22 | Scenario: Nested steps contain an undefined step 23 | Given a new working directory 24 | And a file named "features/steps/steps.py" with: 25 | """ 26 | from behave import step 27 | 28 | @step('{word:w} step passes') 29 | def step_passes(context, word): 30 | pass 31 | 32 | @then('a good diagnostic message is shown') 33 | def step_good_diagnostic_message_is_shown(context): 34 | pass 35 | 36 | @step('I execute nested steps with an undefined step') 37 | def step_passes(context): 38 | context.execute_steps(u''' 39 | Given another step passes 40 | When an undefined, nested step is executed 41 | Then third step passes 42 | ''') 43 | """ 44 | And a file named "features/example.execute_nested_undefined_step.feature" with: 45 | """ 46 | Feature: 47 | Scenario: 48 | Given a step passes 49 | When I execute nested steps with an undefined step 50 | Then a good diagnostic message is shown 51 | """ 52 | When I run "behave -f plain -T features/example.execute_nested_undefined_step.feature" 53 | Then it should fail with: 54 | """ 55 | Scenario: 56 | Given a step passes ... passed 57 | When I execute nested steps with an undefined step ... failed 58 | Assertion Failed: UNDEFINED SUB-STEP: When an undefined, nested step is executed 59 | """ 60 | 61 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/requirements.txt: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # PYTHON PACKAGE REQUIREMENTS: For running issue.features/ 3 | # ============================================================================ 4 | # REQUIRES: Python >= 2.5 5 | # REQUIRES: Python >= 3.2 6 | # DESCRIPTION: 7 | # pip install -r 8 | # 9 | # ============================================================================ 10 | 11 | PyHamcrest >= 1.6 12 | 13 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/steps/behave_hooks_steps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from behave import then 3 | 4 | @then('the behave hook "{hook}" was called') 5 | def step_behave_hook_was_called(context, hook): 6 | substeps = u'Then the command output should contain "hooks.{0}: "'.format(hook) 7 | context.execute_steps(substeps) 8 | 9 | -------------------------------------------------------------------------------- /behave-parallel/issue.features/steps/use_steplib_behave4cmd.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Use behave4cmd0 step library (predecessor of behave4cmd). 4 | """ 5 | 6 | # -- REGISTER-STEPS: 7 | import behave4cmd0.command_steps 8 | -------------------------------------------------------------------------------- /behave-parallel/more.features/formatter.json.validate_output.feature: -------------------------------------------------------------------------------- 1 | @slow 2 | Feature: Validate JSON Formatter Output 3 | 4 | To ensure that the JSON formatter generates valid JSON output 5 | As a tester 6 | I want that the JSON output is validated against its JSON schema. 7 | 8 | 9 | Scenario: Validate JSON output from features/ test run 10 | Given I use the current directory as working directory 11 | When I run "behave -f json -o testrun1.json features/" 12 | And I run "bin/jsonschema_validate.py testrun1.json" 13 | Then it should pass with: 14 | """ 15 | validate: testrun1.json ... OK 16 | """ 17 | 18 | Scenario: Validate JSON output from issue.features/ test run 19 | Given I use the current directory as working directory 20 | When I run "behave -f json -o testrun2.json issue.features/" 21 | And I run "bin/jsonschema_validate.py testrun2.json" 22 | Then it should pass with: 23 | """ 24 | validate: testrun2.json ... OK 25 | """ 26 | 27 | Scenario: Validate JSON output from tools/test-features/ test run 28 | Given I use the current directory as working directory 29 | When I run "behave -f json -o testrun3.json tools/test-features/" 30 | And I run "bin/jsonschema_validate.py testrun3.json" 31 | Then it should pass with: 32 | """ 33 | validate: testrun3.json ... OK 34 | """ -------------------------------------------------------------------------------- /behave-parallel/more.features/steps/use_steplib_behave4cmd.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Use behave4cmd0 step library (predecessor of behave4cmd). 4 | """ 5 | 6 | # -- REGISTER-STEPS: 7 | import behave4cmd0.__all_steps__ 8 | -------------------------------------------------------------------------------- /behave-parallel/requirements/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains python package requirements for behave. 2 | These requirement files are used by: 3 | 4 | * pip 5 | * tox 6 | -------------------------------------------------------------------------------- /behave-parallel/requirements/all.txt: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # BEHAVE: PYTHON PACKAGE REQUIREMENTS: All requirements 3 | # ============================================================================ 4 | # DESCRIPTION: 5 | # pip install -r 6 | # 7 | # SEE ALSO: 8 | # * http://www.pip-installer.org/ 9 | # ============================================================================ 10 | 11 | -r basic.txt 12 | -r develop.txt 13 | -r docs.txt 14 | -r more_py25.txt 15 | -r json.txt 16 | -------------------------------------------------------------------------------- /behave-parallel/requirements/basic.txt: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # BEHAVE: PYTHON PACKAGE REQUIREMENTS: Normal usage/installation (minimal) 3 | # ============================================================================ 4 | # DESCRIPTION: 5 | # pip install -r 6 | # 7 | # SEE ALSO: 8 | # * http://www.pip-installer.org/ 9 | # ============================================================================ 10 | 11 | argparse >= 1.2 12 | parse >= 1.6.2 13 | 14 | # -- MORE: 15 | # Python2.5: simplejson # -- json module was introduced in python2.6 16 | -------------------------------------------------------------------------------- /behave-parallel/requirements/develop.txt: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # PYTHON PACKAGE REQUIREMENTS FOR: behave -- For development only 3 | # ============================================================================ 4 | 5 | # -- TESTING: Unit tests and behave self-tests. 6 | # PREPARED-FUTURE: behave4cmd0, behave4cmd 7 | nose >= 1.1 8 | mock >= 1.0 9 | PyHamcrest >= 1.6 10 | 11 | # -- DEVELOPMENT SUPPORT: 12 | # PREPARED: nose-cov >= 1.4 13 | # PREPARED: paver >= 1.2 14 | tox >= 1.6.0 15 | coverage >= 3.6 16 | -------------------------------------------------------------------------------- /behave-parallel/requirements/docs.txt: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # BEHAVE: PYTHON PACKAGE REQUIREMENTS: For documentation generation 3 | # ============================================================================ 4 | 5 | sphinx >= 1.1 6 | sphinxcontrib-cheeseshop >= 0.2 7 | -------------------------------------------------------------------------------- /behave-parallel/requirements/json.txt: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # PYTHON PACKAGE REQUIREMENTS FOR: behave -- For development only 3 | # ============================================================================ 4 | 5 | # -- OPTIONAL: For JSON validation 6 | # REQUIRES: python >= 2.6 7 | jsonschema >= 1.3.0 8 | -------------------------------------------------------------------------------- /behave-parallel/requirements/more_py25.txt: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # BEHAVE: PYTHON PACKAGE REQUIREMENTS: More packages for Python2.5 3 | # ============================================================================ 4 | # Python2.5: json module was introduced in python2.6 5 | 6 | simplejson 7 | -------------------------------------------------------------------------------- /behave-parallel/requirements/optional.txt: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # BEHAVE: PYTHON PACKAGE REQUIREMENTS: Optional packages 3 | # ============================================================================ 4 | # Python2.5: importlib module was introduced in python2.7, python3.2... 5 | # Python2.6: importlib module was introduced in python2.7, python3.2... 6 | 7 | importlib 8 | -------------------------------------------------------------------------------- /behave-parallel/setup.cfg: -------------------------------------------------------------------------------- 1 | [upload_docs] 2 | upload-dir = build/docs/html 3 | 4 | [nosetests] 5 | where = test 6 | 7 | [behave_test] 8 | format = progress 9 | tags = -@xfail 10 | args = features tools/test-features issue.features 11 | 12 | [aliases] 13 | test = nosetests 14 | 15 | -------------------------------------------------------------------------------- /behave-parallel/setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | """ 3 | Setup script for behave. 4 | 5 | USAGE: 6 | python setup.py install 7 | python setup.py behave_test # -- XFAIL on Windows (currently). 8 | python setup.py nosetests 9 | """ 10 | 11 | import sys 12 | import os.path 13 | sys.path.insert(0, os.curdir) 14 | 15 | from setuptools import find_packages, setup 16 | from setuptools_behave import behave_test 17 | 18 | requirements = ['parse>=1.6.2'] 19 | zip_safe = True 20 | major, minor = sys.version_info[:2] 21 | if major == 2 and minor < 7: 22 | requirements.append('argparse') 23 | requirements.append('importlib') 24 | if major == 2 and minor < 6: 25 | requirements.append('simplejson') 26 | 27 | description = ''.join(open('README.rst').readlines()[5:]) 28 | 29 | setup( 30 | name='behave', 31 | version='1.2.4a1', 32 | description='behave is behaviour-driven development, Python style', 33 | long_description=description, 34 | author='Benno Rice, Richard Jones and Jens Engel', 35 | author_email='behave-users@googlegroups.com', 36 | url='http://github.com/behave/behave', 37 | packages=find_packages(exclude=[ 38 | "test", "test.*", 39 | "behave4cmd0", "behave4cmd0.*"]), 40 | entry_points={ 41 | 'console_scripts': [ 42 | 'behave = behave.__main__:main' 43 | ], 44 | 'distutils.commands': [ 45 | 'behave_test = setuptools_behave:behave_test' 46 | ] 47 | }, 48 | install_requires=requirements, 49 | test_suite='nose.collector', 50 | tests_require=['nose>=1.3', 'mock>=1.0', 'PyHamcrest>=1.7.2'], 51 | cmdclass = { 52 | 'behave_test': behave_test, 53 | }, 54 | use_2to3=True, 55 | license="BSD", 56 | classifiers=[ 57 | "Development Status :: 4 - Beta", 58 | "Environment :: Console", 59 | "Intended Audience :: Developers", 60 | "Operating System :: OS Independent", 61 | "Programming Language :: Python :: 2.5", 62 | "Programming Language :: Python :: 2.6", 63 | "Programming Language :: Python :: 2.7", 64 | "Programming Language :: Python :: 3.2", 65 | "Programming Language :: Python :: 3.3", 66 | "Programming Language :: Python :: Implementation :: CPython", 67 | "Programming Language :: Python :: Implementation :: Jython", 68 | "Programming Language :: Python :: Implementation :: PyPy", 69 | "Topic :: Software Development :: Testing", 70 | "License :: OSI Approved :: BSD License", 71 | ], 72 | ) 73 | 74 | 75 | -------------------------------------------------------------------------------- /behave-parallel/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sauce-archives/Python-Behave-Appium-Android/8477d99c14dc8331d2f8b1824f0b02fcc9c82b42/behave-parallel/test/__init__.py -------------------------------------------------------------------------------- /behave-parallel/test/reporters/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sauce-archives/Python-Behave-Appium-Android/8477d99c14dc8331d2f8b1824f0b02fcc9c82b42/behave-parallel/test/reporters/__init__.py -------------------------------------------------------------------------------- /behave-parallel/test/test_ansi_escapes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # pylint: disable=C0103,R0201,W0401,W0614,W0621 3 | # C0103 Invalid name (setUp(), ...) 4 | # R0201 Method could be a function 5 | # W0401 Wildcard import 6 | # W0614 Unused import ... from wildcard import 7 | # W0621 Redefining name ... from outer scope 8 | 9 | from nose import tools 10 | from behave.formatter import ansi_escapes 11 | import unittest 12 | 13 | class StripEscapesTest(unittest.TestCase): 14 | ALL_COLORS = ansi_escapes.colors.keys() 15 | CURSOR_UPS = [ ansi_escapes.up(count) for count in range(10) ] 16 | TEXTS = [ 17 | u"lorem ipsum", 18 | u"Alice\nBob\nCharly\nDennis", 19 | ] 20 | 21 | @classmethod 22 | def colorize(cls, text, color): 23 | color_escape = "" 24 | if color: 25 | color_escape = ansi_escapes.colors[color] 26 | return color_escape + text + ansi_escapes.escapes["reset"] 27 | 28 | @classmethod 29 | def colorize_text(cls, text, colors=None): 30 | if not colors: 31 | colors = [] 32 | colors_size = len(colors) 33 | color_index = 0 34 | colored_chars = [] 35 | for char in text: 36 | color = colors[color_index] 37 | colored_chars.append(cls.colorize(char, color)) 38 | color_index += 1 39 | if color_index >= colors_size: 40 | color_index = 0 41 | return "".join(colored_chars) 42 | 43 | def test_should_return_same_text_without_escapes(self): 44 | for text in self.TEXTS: 45 | tools.eq_(text, ansi_escapes.strip_escapes(text)) 46 | 47 | def test_should_return_empty_string_for_any_ansi_escape(self): 48 | for text in ansi_escapes.colors.values(): 49 | tools.eq_("", ansi_escapes.strip_escapes(text)) 50 | for text in ansi_escapes.escapes.values(): 51 | tools.eq_("", ansi_escapes.strip_escapes(text)) 52 | 53 | 54 | def test_should_strip_color_escapes_from_text(self): 55 | for text in self.TEXTS: 56 | colored_text = self.colorize_text(text, self.ALL_COLORS) 57 | tools.eq_(text, ansi_escapes.strip_escapes(colored_text)) 58 | self.assertNotEqual(text, colored_text) 59 | 60 | for color in self.ALL_COLORS: 61 | colored_text = self.colorize(text, color) 62 | tools.eq_(text, ansi_escapes.strip_escapes(colored_text)) 63 | self.assertNotEqual(text, colored_text) 64 | 65 | def test_should_strip_cursor_up_escapes_from_text(self): 66 | for text in self.TEXTS: 67 | for cursor_up in self.CURSOR_UPS: 68 | colored_text = cursor_up + text + ansi_escapes.escapes["reset"] 69 | tools.eq_(text, ansi_escapes.strip_escapes(colored_text)) 70 | self.assertNotEqual(text, colored_text) 71 | -------------------------------------------------------------------------------- /behave-parallel/test/test_configuration.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | import os.path 3 | import tempfile 4 | 5 | from nose.tools import * 6 | from behave import configuration 7 | 8 | # one entry of each kind handled 9 | TEST_CONFIG='''[behave] 10 | outfiles= /absolute/path1 11 | relative/path2 12 | paths = /absolute/path3 13 | relative/path4 14 | tags = @foo,~@bar 15 | @zap 16 | format=pretty 17 | tag-counter 18 | stdout_capture=no 19 | bogus=spam 20 | ''' 21 | 22 | class TestConfiguration(object): 23 | 24 | def test_read_file(self): 25 | tn = tempfile.mktemp() 26 | tndir = os.path.dirname(tn) 27 | with open(tn, 'w') as f: 28 | f.write(TEST_CONFIG) 29 | 30 | d = configuration.read_configuration(tn) 31 | eq_(d['outfiles'], [ 32 | os.path.normpath('/absolute/path1'), 33 | os.path.normpath(os.path.join(tndir, 'relative/path2')), 34 | ]) 35 | eq_(d['paths'], [ 36 | os.path.normpath('/absolute/path3'), # -- WINDOWS-REQUIRES: normpath 37 | os.path.normpath(os.path.join(tndir, 'relative/path4')), 38 | ]) 39 | eq_(d['format'], ['pretty', 'tag-counter']) 40 | eq_(d['tags'], ['@foo,~@bar', '@zap']) 41 | eq_(d['stdout_capture'], False) 42 | ok_('bogus' not in d) 43 | 44 | -------------------------------------------------------------------------------- /behave-parallel/test/test_formatter_progress.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Test progress formatters: 4 | * behave.formatter.progress.ScenarioProgressFormatter 5 | * behave.formatter.progress.StepProgressFormatter 6 | """ 7 | 8 | from __future__ import absolute_import 9 | from .test_formatter import FormatterTests as FormatterTest 10 | from .test_formatter import MultipleFormattersTests as MultipleFormattersTest 11 | 12 | class TestScenarioProgressFormatter(FormatterTest): 13 | formatter_name = "progress" 14 | 15 | 16 | class TestStepProgressFormatter(FormatterTest): 17 | formatter_name = "progress2" 18 | 19 | 20 | class TestPrettyAndScenarioProgress(MultipleFormattersTest): 21 | formatters = ['pretty', 'progress'] 22 | 23 | class TestPlainAndScenarioProgress(MultipleFormattersTest): 24 | formatters = ['plain', 'progress'] 25 | 26 | class TestJSONAndScenarioProgress(MultipleFormattersTest): 27 | formatters = ['json', 'progress'] 28 | 29 | class TestPrettyAndStepProgress(MultipleFormattersTest): 30 | formatters = ['pretty', 'progress2'] 31 | 32 | class TestPlainAndStepProgress(MultipleFormattersTest): 33 | formatters = ['plain', 'progress2'] 34 | 35 | class TestJSONAndStepProgress(MultipleFormattersTest): 36 | formatters = ['json', 'progress2'] 37 | 38 | class TestScenarioProgressAndStepProgress(MultipleFormattersTest): 39 | formatters = ['progress', 'progress2'] 40 | -------------------------------------------------------------------------------- /behave-parallel/test/test_formatter_tags.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Test formatters: 4 | * behave.formatter.tags.TagsCountFormatter 5 | * behave.formatter.tags.TagsLocationFormatter 6 | """ 7 | 8 | from __future__ import absolute_import 9 | from .test_formatter import FormatterTests as FormatterTest 10 | from .test_formatter import MultipleFormattersTests as MultipleFormattersTest 11 | 12 | # ----------------------------------------------------------------------------- 13 | # FORMATTER TESTS: With TagCountFormatter 14 | # ----------------------------------------------------------------------------- 15 | class TestTagsCountFormatter(FormatterTest): 16 | formatter_name = "tags" 17 | 18 | # ----------------------------------------------------------------------------- 19 | # FORMATTER TESTS: With TagLocationFormatter 20 | # ----------------------------------------------------------------------------- 21 | class TestTagsLocationFormatter(FormatterTest): 22 | formatter_name = "tags.location" 23 | 24 | 25 | # ----------------------------------------------------------------------------- 26 | # MULTI-FORMATTER TESTS: With TagCountFormatter 27 | # ----------------------------------------------------------------------------- 28 | class TestPrettyAndTagsCount(MultipleFormattersTest): 29 | formatters = ["pretty", "tags"] 30 | 31 | class TestPlainAndTagsCount(MultipleFormattersTest): 32 | formatters = ["plain", "tags"] 33 | 34 | class TestJSONAndTagsCount(MultipleFormattersTest): 35 | formatters = ["json", "tags"] 36 | 37 | class TestRerunAndTagsCount(MultipleFormattersTest): 38 | formatters = ["rerun", "tags"] 39 | 40 | 41 | # ----------------------------------------------------------------------------- 42 | # MULTI-FORMATTER TESTS: With TagLocationFormatter 43 | # ----------------------------------------------------------------------------- 44 | class TestPrettyAndTagsLocation(MultipleFormattersTest): 45 | formatters = ["pretty", "tags.location"] 46 | 47 | class TestPlainAndTagsLocation(MultipleFormattersTest): 48 | formatters = ["plain", "tags.location"] 49 | 50 | class TestJSONAndTagsLocation(MultipleFormattersTest): 51 | formatters = ["json", "tags.location"] 52 | 53 | class TestRerunAndTagsLocation(MultipleFormattersTest): 54 | formatters = ["rerun", "tags.location"] 55 | 56 | class TestTagsCountAndTagsLocation(MultipleFormattersTest): 57 | formatters = ["tags", "tags.location"] 58 | -------------------------------------------------------------------------------- /behave-parallel/test/test_log_capture.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | 3 | from nose.tools import * 4 | from mock import patch 5 | 6 | from behave.log_capture import LoggingCapture 7 | 8 | class TestLogCapture(object): 9 | def test_get_value_returns_all_log_records(self): 10 | class FakeConfig(object): 11 | logging_filter = None 12 | logging_format = None 13 | logging_datefmt = None 14 | logging_level = None 15 | 16 | fake_records = [object() for x in range(0, 10)] 17 | 18 | handler = LoggingCapture(FakeConfig()) 19 | handler.buffer = fake_records 20 | 21 | with patch.object(handler.formatter, 'format') as format: 22 | format.return_value = 'foo' 23 | expected = '\n'.join(['foo'] * len(fake_records)) 24 | 25 | eq_(handler.getvalue(), expected) 26 | 27 | calls = [args[0][0] for args in format.call_args_list] 28 | eq_(calls, fake_records) 29 | -------------------------------------------------------------------------------- /behave-parallel/test/test_step_registry.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | 3 | from mock import Mock, patch 4 | from nose.tools import * 5 | from behave import step_registry 6 | 7 | class TestStepRegistry(object): 8 | def test_add_step_definition_adds_to_lowercased_keyword(self): 9 | registry = step_registry.StepRegistry() 10 | with patch('behave.matchers.get_matcher') as get_matcher: 11 | func = lambda x: -x 12 | string = 'just a test string' 13 | magic_object = object() 14 | get_matcher.return_value = magic_object 15 | 16 | for step_type in registry.steps.keys(): 17 | l = [] 18 | registry.steps[step_type] = l 19 | 20 | registry.add_step_definition(step_type.upper(), string, func) 21 | 22 | get_matcher.assert_called_with(func, string) 23 | eq_(l, [magic_object]) 24 | 25 | def test_find_match_with_specific_step_type_also_searches_generic(self): 26 | registry = step_registry.StepRegistry() 27 | 28 | given_mock = Mock() 29 | given_mock.match.return_value = None 30 | step_mock = Mock() 31 | step_mock.match.return_value = None 32 | 33 | registry.steps['given'].append(given_mock) 34 | registry.steps['step'].append(step_mock) 35 | 36 | step = Mock() 37 | step.step_type = 'given' 38 | step.name = 'just a test step' 39 | 40 | assert registry.find_match(step) is None 41 | 42 | given_mock.match.assert_called_with(step.name) 43 | step_mock.match.assert_called_with(step.name) 44 | 45 | def test_find_match_with_no_match_returns_none(self): 46 | registry = step_registry.StepRegistry() 47 | 48 | step_defs = [Mock() for x in range(0, 10)] 49 | for mock in step_defs: 50 | mock.match.return_value = None 51 | 52 | registry.steps['when'] = step_defs 53 | 54 | step = Mock() 55 | step.step_type = 'when' 56 | step.name = 'just a test step' 57 | 58 | assert registry.find_match(step) is None 59 | 60 | def test_find_match_with_a_match_returns_match(self): 61 | registry = step_registry.StepRegistry() 62 | 63 | step_defs = [Mock() for x in range(0, 10)] 64 | for mock in step_defs: 65 | mock.match.return_value = None 66 | magic_object = object() 67 | step_defs[5].match.return_value = magic_object 68 | 69 | registry.steps['then'] = step_defs 70 | 71 | step = Mock() 72 | step.step_type = 'then' 73 | step.name = 'just a test step' 74 | 75 | assert registry.find_match(step) is magic_object 76 | for mock in step_defs[6:]: 77 | eq_(mock.match.call_count, 0) 78 | 79 | @patch.object(step_registry.registry, 'add_step_definition') 80 | def test_make_step_decorator_ends_up_adding_a_step_definition(self, add_step_definition): 81 | step_type = object() 82 | string = object() 83 | func = object() 84 | 85 | decorator = step_registry.registry.make_decorator(step_type) 86 | wrapper = decorator(string) 87 | assert wrapper(func) is func 88 | add_step_definition.assert_called_with(step_type, string, func) 89 | 90 | -------------------------------------------------------------------------------- /behave-parallel/test/test_tag_expression.py: -------------------------------------------------------------------------------- 1 | from nose import tools 2 | 3 | from behave.tag_expression import TagExpression 4 | 5 | class TestTagExpressionNoTags(object): 6 | def setUp(self): 7 | self.e = TagExpression([]) 8 | 9 | def test_should_match_foo(self): 10 | assert self.e.check(['foo']) 11 | 12 | def test_should_match_empty_tags(self): 13 | assert self.e.check([]) 14 | 15 | class TestTagExpressionFoo(object): 16 | def setUp(self): 17 | self.e = TagExpression(['foo']) 18 | 19 | def test_should_match_foo(self): 20 | assert self.e.check(['foo']) 21 | 22 | def test_should_not_match_bar(self): 23 | assert not self.e.check(['bar']) 24 | 25 | def test_should_not_match_no_tags(self): 26 | assert not self.e.check([]) 27 | 28 | class TestTagExpressionNotFoo(object): 29 | def setUp(self): 30 | self.e = TagExpression(['-foo']) 31 | 32 | def test_should_match_bar(self): 33 | assert self.e.check(['bar']) 34 | 35 | def test_should_not_match_foo(self): 36 | assert not self.e.check(['foo']) 37 | 38 | class TestTagExpressionFooOrBar(object): 39 | def setUp(self): 40 | self.e = TagExpression(['foo,bar']) 41 | 42 | def test_should_match_foo(self): 43 | assert self.e.check(['foo']) 44 | 45 | def test_should_match_bar(self): 46 | assert self.e.check(['bar']) 47 | 48 | def test_should_not_match_zap(self): 49 | assert not self.e.check(['zap']) 50 | 51 | class TestTagExpressionFooOrBarAndNotZap(object): 52 | def setUp(self): 53 | self.e = TagExpression(['foo,bar', '-zap']) 54 | 55 | def test_should_match_foo(self): 56 | assert self.e.check(['foo']) 57 | 58 | def test_should_not_match_foo_zap(self): 59 | assert not self.e.check(['foo', 'zap']) 60 | 61 | class TestTagExpressionFoo3OrNotBar4AndZap5(object): 62 | def setUp(self): 63 | self.e = TagExpression(['foo:3,-bar', 'zap:5']) 64 | 65 | def test_should_count_tags_for_positive_tags(self): 66 | tools.eq_(self.e.limits, {'foo': 3, 'zap': 5}) 67 | 68 | def test_should_match_foo_zap(self): 69 | assert self.e.check(['foo', 'zap']) 70 | 71 | class TestTagExpressionParsing(object): 72 | def setUp(self): 73 | self.e = TagExpression([' foo:3 , -bar ', ' zap:5 ']) 74 | 75 | def test_should_have_limits(self): 76 | tools.eq_(self.e.limits, {'zap': 5, 'foo': 3}) 77 | 78 | class TestTagExpressionTagLimits(object): 79 | def test_should_be_counted_for_negative_tags(self): 80 | e = TagExpression(['-todo:3']) 81 | tools.eq_(e.limits, {'todo': 3}) 82 | 83 | def test_should_be_counted_for_positive_tags(self): 84 | e = TagExpression(['todo:3']) 85 | tools.eq_(e.limits, {'todo': 3}) 86 | 87 | def test_should_raise_an_error_for_inconsistent_limits(self): 88 | tools.assert_raises(Exception, TagExpression, ['todo:3', '-todo:4']) 89 | 90 | def test_should_allow_duplicate_consistent_limits(self): 91 | e = TagExpression(['todo:3', '-todo:3']) 92 | tools.eq_(e.limits, {'todo': 3}) 93 | 94 | -------------------------------------------------------------------------------- /behave-parallel/tools/convert_i18n_yaml.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pprint 4 | import sys 5 | 6 | import yaml 7 | 8 | # 9 | # usage: convert_i18n_yaml.py i18n.yml ../behave/i18n.py 10 | # 11 | languages = yaml.load(open(sys.argv[1])) 12 | 13 | for language in languages: 14 | keywords = languages[language] 15 | for k in keywords: 16 | v = keywords[k] 17 | # bloody YAML parser returns a mixture of unicode and str 18 | if not isinstance(v, unicode): 19 | v = v.decode('utf8') 20 | keywords[k] = v.split('|') 21 | 22 | content = '''#-*- encoding: UTF-8 -*- 23 | 24 | # file generated by convert_i18n_yaml.py from i18n.yaml 25 | 26 | languages = \\ 27 | ''' 28 | 29 | i18n_py = open(sys.argv[2], 'w') 30 | i18n_py.write(content.encode('UTF-8')) 31 | i18n_py.write(pprint.pformat(languages).encode('UTF-8')) 32 | i18n_py.write(u'\n') 33 | i18n_py.close() 34 | -------------------------------------------------------------------------------- /behave-parallel/tools/test-features/background.feature: -------------------------------------------------------------------------------- 1 | Feature: features may have backgrounds 2 | 3 | Background: some background stuff to run 4 | Given I am testing stuff 5 | and some stuff is set up 6 | 7 | Scenario: the stuff should be set up 8 | Given stuff has been set up 9 | Then it will work 10 | -------------------------------------------------------------------------------- /behave-parallel/tools/test-features/environment.py: -------------------------------------------------------------------------------- 1 | 2 | def before_all(context): 3 | context.testing_stuff = False 4 | context.stuff_set_up = False 5 | 6 | def before_feature(context, feature): 7 | context.is_spammy = 'spam' in feature.tags 8 | 9 | -------------------------------------------------------------------------------- /behave-parallel/tools/test-features/french.feature: -------------------------------------------------------------------------------- 1 | # language: fr 2 | Fonctionnalité: testing stuff 3 | 4 | Scénario: test stuff 5 | Etant donné I am testing stuff 6 | Quand I exercise it work 7 | Alors it will work 8 | 9 | Scénario: test more stuff 10 | Etant donné I am testing stuff 11 | Alors it will work 12 | -------------------------------------------------------------------------------- /behave-parallel/tools/test-features/outline.feature: -------------------------------------------------------------------------------- 1 | Feature: support scenario outlines 2 | 3 | Scenario Outline: run scenarios with one example table 4 | Given Some text 5 | When we add some text 6 | Then we should get the 7 | 8 | Examples: some simple examples 9 | | prefix | suffix | combination | 10 | | go | ogle | google | 11 | | onomat | opoeia | onomatopoeia | 12 | | comb | ination | combination | 13 | 14 | Scenario Outline: run scenarios with examples 15 | Given Some text 16 | When we add some text 17 | Then we should get the 18 | 19 | Examples: some simple examples 20 | | prefix | suffix | combination | 21 | | go | ogle | google | 22 | | onomat | opoeia | onomatopoeia | 23 | | comb | ination | combination | 24 | 25 | Examples: some other examples 26 | | prefix | suffix | combination | 27 | | 1 | 2 | 12 | 28 | | one | two | onetwo | 29 | 30 | @xfail 31 | Scenario Outline: scenarios that reference invalid subs 32 | Given Some text 33 | When we add try to use a reference 34 | Then it won't work 35 | 36 | Examples: some simple examples 37 | | prefix | 38 | | go | 39 | 40 | -------------------------------------------------------------------------------- /behave-parallel/tools/test-features/parse.feature: -------------------------------------------------------------------------------- 1 | Feature: parse stuff out of steps 2 | 3 | Scenario: basic parsing 4 | Given a string with an argument 5 | Then we get "with" parsed 6 | 7 | Scenario: custom type parsing 8 | Given a string with a custom type 9 | Then we get "WITH" parsed 10 | 11 | -------------------------------------------------------------------------------- /behave-parallel/tools/test-features/step-data.feature: -------------------------------------------------------------------------------- 1 | Feature: steps may have associated data 2 | 3 | Scenario: step with text 4 | Given some body of text 5 | """ 6 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed 7 | do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 8 | enim ad minim veniam, quis nostrud exercitation ullamco laboris 9 | nisi ut aliquip ex ea commodo consequat. 10 | """ 11 | Then the text is as expected 12 | 13 | Scenario: step with a table 14 | Given some initial data 15 | | name | department | 16 | | Barry | Beer Cans | 17 | | Pudey | Silly Walks | 18 | | Two-Lumps | Silly Walks | 19 | Then we will have the expected data 20 | 21 | @xfail 22 | Scenario: step with text that fails 23 | Given some body of text 24 | """ 25 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed 26 | do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 27 | enim ad minim VENIAM, quis nostrud exercitation ullamco laboris 28 | nisi ut aliquip ex ea commodo consequat. 29 | """ 30 | Then the text is as expected 31 | 32 | Scenario Outline: step with text and subtitution 33 | Given some body of text 34 | """ 35 | Lorem dolor sit amet, consectetur adipisicing elit, sed 36 | do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 37 | enim ad minim veniam, quis nostrud exercitation ullamco laboris 38 | nisi ut aliquip ex ea commodo consequat. 39 | """ 40 | Then the text is substituted as expected 41 | 42 | Examples: 43 | | ipsum | 44 | | spam | 45 | | ham | 46 | 47 | 48 | Scenario Outline: step with a table and substution 49 | Given some initial data 50 | | name | department | 51 | | Barry | Cans | 52 | | Pudey | Silly Walks | 53 | | Two-Lumps | Silly Walks | 54 | Then we will have the substituted data 55 | 56 | Examples: 57 | | spam | 58 | | spam | 59 | | ham | 60 | 61 | -------------------------------------------------------------------------------- /behave-parallel/tools/test-features/tags.feature: -------------------------------------------------------------------------------- 1 | @spam 2 | Feature: handle tags 3 | Tags may be set at various levels in various ways. 4 | 5 | Scenario: nothing changes 6 | Given the tag "spam" is set 7 | 8 | @ham @cram 9 | Scenario: adding the ham 10 | Given the tag "spam" is set 11 | and the tag "ham" is set 12 | and the tag "cram" is set 13 | 14 | @ham 15 | Scenario: adding the ham 16 | Given the tag "spam" is set 17 | and the tag "ham" is set 18 | and the tag "cram" is not set 19 | -------------------------------------------------------------------------------- /features/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sauce-archives/Python-Behave-Appium-Android/8477d99c14dc8331d2f8b1824f0b02fcc9c82b42/features/__init__.py -------------------------------------------------------------------------------- /features/environment.py: -------------------------------------------------------------------------------- 1 | import os 2 | from appium import webdriver 3 | from sauceclient import SauceClient 4 | 5 | username = os.environ.get('SAUCE_USERNAME') 6 | access_key = os.environ.get('SAUCE_ACCESS_KEY') 7 | url = 'http://%s:%s@ondemand.saucelabs.com:80/wd/hub' % (username, access_key) 8 | 9 | 10 | 11 | def before_scenario(context, scenario): 12 | context.name = scenario.name 13 | 14 | desired_caps = { 15 | "name": context.name, 16 | "app": "http://saucelabs.com/example_files/ContactManager.apk", 17 | "platformName": "Android", 18 | "deviceName": os.environ.get('deviceName'), 19 | "browserName": "", 20 | "platformVersion": "4.4", 21 | "appiumVersion": "1.5.3", 22 | "deviceOrientation": "portrait" 23 | } 24 | context.driver = webdriver.Remote(url, desired_caps) 25 | 26 | def after_scenario(context, scenario): 27 | if hasattr(context, 'driver'): 28 | context.driver.quit() 29 | sauce_client = SauceClient(username, access_key) 30 | test_status = scenario.status == 'passed' 31 | sauce_client.jobs.update_job(context.driver.session_id, passed = test_status) 32 | -------------------------------------------------------------------------------- /features/steps/steps.py: -------------------------------------------------------------------------------- 1 | import os 2 | from appium import webdriver 3 | 4 | username = os.environ.get('SAUCE_USERNAME') 5 | access_key = os.environ.get('SAUCE_ACCESS_KEY') 6 | 7 | @given('I click on the add contact button') 8 | def step_impl(context): 9 | button_one = context.driver.find_element_by_class_name("android.widget.Button") 10 | button_one.click() 11 | 12 | @when('I enter a name and email') 13 | def step_impl(context): 14 | text_fields = context.driver.find_elements_by_class_name("android.widget.EditText") 15 | text_fields[0].send_keys("Some Name") 16 | text_fields[2].send_keys("Some@example.com") 17 | 18 | @then('I click the Save button') 19 | def step_impl(context): 20 | context.driver.find_element_by_class_name("android.widget.Button").click() 21 | -------------------------------------------------------------------------------- /features/test.feature: -------------------------------------------------------------------------------- 1 | Feature: Adding a contact via an Android App 2 | 3 | Scenario: Add a Contact 4 | Given I click on the add contact button 5 | When I enter a name and email 6 | Then I click the Save button 7 | 8 | 9 | --------------------------------------------------------------------------------