Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix some spelling in the README and add some info. #103

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Features/Tutorial launch.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Feature: Tutorial examples could be executed successfully

Scenario: Catalog example with simplest steps
Given Copy path from "docs\tutorial" to "tutorial"
When run pytest
|cli_args| --rootdir=tutorial| tutorial/tests |

Then pytest outcome must contain tests with statuses:
|passed|
| 1|
26 changes: 20 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ BDD library for the pytest runner
.. _pytest: https://docs.pytest.org
.. _Gherkin: https://cucumber.io/docs/gherkin/reference
.. _pytest-bdd-ng: https://pytest-bdd-ng.readthedocs.io/en/default/
.. _pytest-bdd: https://github.com/pytest-dev/pytest-bdd

**pytest-bdd-ng** combine descriptive clarity of Gherkin_ language
with power and fullness of pytest_ infrastructure.
Expand All @@ -27,7 +28,14 @@ mentioned in feature steps with dependency injection. This allows a true BDD
just-enough specification of the requirements without obligatory maintaining any context object
containing the side effects of Gherkin imperative declarations.

.. NOTE:: Project documentation: pytest-bdd-ng_
.. NOTE:: Project documentation on readthedocs: pytest-bdd-ng_


Why ``NG`` ?
------------

The current pytest plugin for cucumber is pytest-bdd_ , a popular project with 1.2k stars and used in 3k public repos and maintained by the pytest community. The upstream open-cucumber project does not have an official python release, so the current cucumber specs include features not available in pytest-bdd_ . This project is an effort to bridge the gap and also make it easier for pytest users to access new cucumber features.


Install pytest-bdd-ng
---------------------
Expand All @@ -38,12 +46,12 @@ Install pytest-bdd-ng

Project layout
--------------
**pytest-bdd-ng** automatically collect `*.feature` files from pytest_ tests directory.
**pytest-bdd-ng** automatically collects ``*.feature`` files from pytest_ tests directory.
Important to remember, that feature files are used by other team members as live documentation,
so it's not a very good idea to mix documentation and test code.

The more features and scenarios you have, the more important becomes the question about
their organization. So recommended way is to organize your feature files in the folders by
their organization. So the recommended way is to organize your feature files in the folders by
semantic groups:

::
Expand All @@ -56,7 +64,7 @@ semantic groups:
└──auth
└──login.feature

And tests for this features could be organized in the next manner:
And tests for these features would be organized in the following manner:

::

Expand All @@ -83,7 +91,7 @@ And tests for this features could be organized in the next manner:
│ └──backend_auth.feature -> ../../features/backend/auth.feature
...

Step definitions could be organized in the next way
The step definitions would then be organized like this:

::

Expand Down Expand Up @@ -112,11 +120,17 @@ Step definitions could be organized in the next way
...

To make links between feature files at features directory and test directory there are few options
(for more information please investigate project tests):
(for more information please examine the project's tests):

#. Symlinks
#. `.desktop` files
#. `.webloc` files
#. `.url` files

.. NOTE:: Link files also could be used to load features by http://


How to Contribute
-----------------

The project is now open to contributions. Please open an issue for more details.
24 changes: 24 additions & 0 deletions ci/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import sys

import anyio
import dagger

"""
Copy files to the build container and list them.
"""


async def main():
async with dagger.Connection(dagger.Config(log_output=sys.stderr)) as client:
out = await (
client.container()
.from_("python:3.11-slim")
.with_directory("/host", client.host().directory("."))
.with_exec(["ls", "-al", "/host"])
.stdout()
)

print(out)


anyio.run(main)
Empty file added docs/__init__.py
Empty file.
69 changes: 69 additions & 0 deletions docs/developer.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#################
Developer Guide
#################

.. _quickstart: https://docs.dagger.io/quickstart/729236/cli

This section is introduced specifically for ``pytest-bdd-ng`` to help developers maintain and enhance the source code.


Reduce dependence on Github Actions
===================================

Currently the Github action can take as much as 29 minutes and it has pinned [dependencies in other repos](https://github.com/blaisep/pytest-bdd-ng/blob/default/.github/workflows/main.yml#L33).

I intend to implement local CI so that:
- We can easily rotate external dependencies
- We can iterate faster (by caching intermediate artifacts)
- Developers can follow the dependency tree more easily. (gitmodules don't get cloned locally)


Building the project locally
############################

Prepare your virtual environment
================================

To build the project locally, these instructions assume that you already have a working:
- installed a docker runtime (eg. Docker, Rancher, Orbstack, etc)
- dagger CLI (eg ``brew install dagger/tap/dagger``)
- dagger Python SDK in your virtualenv (eg. ``pip install -U dagger-io``)
You can refer to the dagger quickstart_ docs for help installing dagger.


Explore dagger
==============

Let's have a bit of fun exploring dagger. Create ``ci/main.py`` and paste the following code.

.. code-block::python

import sys
import anyio
import dagger

"""
Run directory listing of the files in the build container
"""

async def main():
async with dagger.Connection(dagger.Config(log_output=sys.stderr)) as client:
out = await (
client.container()
.from_("python:3.11-slim")
.with_directory("/host", client.host().directory("."))
.with_exec(["ls", "-al", "."])
.stdout()
)
print(out)
anyio.run(main)

Now run ``dagger run python ci/main.py``
Note the total time on the last line of the console input.

Run the command again and note the total time. It should be much faster.

Next, change the line ``.with_exec(["ls", "-al", "/host"])`` to ``.with_exec(["ls", "-al", "/host/tests"])``
and run ``dagger run python ci/main.py``

Is the directory listing different? How about the total time?
Binary file added docs/diagrams/cucumber.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions docs/diagrams/cucumber.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@startuml
!theme sketchy-outline
actor "Action" as test
collections "Source" as repo
control "Behave" as runner
database "Artifact" as out
participant "Console" as log

'autonumber
test -> runner: run pytest
runner <--> repo: read
runner -> runner: run tests
runner -> out: write
runner --> log: Log
@enduml
Binary file added docs/diagrams/pytest.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions docs/diagrams/pytest.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@startuml
!theme sketchy-outline
actor "Action" as test
collections "Source" as repo
control "Pytest" as runner
database "Artifact" as out
participant "Console" as log

'autonumber
test -> runner: run pytest
runner <--> repo: read
runner -> out: write
runner --> log: Log
@enduml
36 changes: 21 additions & 15 deletions docs/features.rst
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
.. NOTE:: Features below are part of end-to-end test suite; You always could find most specific
use cases of **pytest-bdd-ng** by investigation of its regression
test suite https://github.com/elchupanebrej/pytest-bdd-ng/tree/default/tests

Gherkin feature launch by pytest.feature
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. include:: ../Features/Gherkin feature launch by pytest.feature
:code: gherkin

Tags for Scenario Outlines examples.feature
###########################################

.. include:: ../Features/Scenario/Outline/Tags for Scenario Outlines examples.feature
:code: gherkin
.. NOTE:: Features below are part of end-to-end test suite; You always could find most specific
use cases of **pytest-bdd-ng** by investigation of its regression
test suite https://github.com/elchupanebrej/pytest-bdd-ng/tree/default/tests

Tutorial launch.feature
!!!!!!!!!!!!!!!!!!!!!!!

.. include:: ../Features/Tutorial launch.feature
:code: gherkin

Gherkin feature launch by pytest.feature
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. include:: ../Features/Gherkin feature launch by pytest.feature
:code: gherkin

Tags for Scenario Outlines examples.feature
###########################################

.. include:: ../Features/Scenario/Outline/Tags for Scenario Outlines examples.feature
:code: gherkin
Empty file added docs/tutorial/__init__.py
Empty file.
12 changes: 12 additions & 0 deletions docs/tutorial/features/books.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Feature files represent `Application under test` functional capabilities
# in form of acceptance test with representative examples
Feature: Library book searches and book delivery
Scenario: The catalog can be searched by author name.
Given these books in the catalog
| Author | Title |
| Stephen King | The Shining |
| James Baldwin | If Beale Street Could Talk |
When a name search is performed for Stephen
Then only these books will be returned
| Author | Title |
| Stephen King | The Shining |
24 changes: 24 additions & 0 deletions docs/tutorial/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Tutorial for Behave/Cucumber users
==================================

If you have experience with Behave or Cucumber, this tutorial is for you.

.. _tutorial: https://thebddcoach.com/post/a-quick-introduction-to-pytest-bdd-ng-for-people-who-are-already-familiar-with-cucumber-or-behave/
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A better idea is to rewrite the tutorial inside a project and make it updatable by the repository owner. If we have a tutorial as part of the e2e suite - it won't become outdated.


Leslie's tutorial_ ...

.. toctree::
:glob:

tests/features/*.feature
src/*.py
tests/*.py
tests/*.desktop
tests/steps/*.py


Set up the tutorial
-------------------

From the project root, activate a virtual environment and run:
``pip install -r docs/tutorial/requirements.txt``
3 changes: 3 additions & 0 deletions docs/tutorial/pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[pytest]
; Defines default rootpath and a lot of pytest configs
;
2 changes: 2 additions & 0 deletions docs/tutorial/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pytest
pytest_bdd_ng
27 changes: 27 additions & 0 deletions docs/tutorial/src/catalog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""This files represents simple `Application under test`"""
from dataclasses import dataclass, field
from typing import Iterable, List


@dataclass # Easy way to not write redundant __init__ https://docs.python.org/3/library/dataclasses.html
class Book:
author: str
title: str


@dataclass
class Catalog:
storage: List[Book] = field(default_factory=list)

def add_books_to_catalog(self, books: Iterable[Book]):
self.storage.extend(books)

def search_by_author(self, term: str):
for book in self.storage:
if term in book.author:
yield book

def search_by_title(self, term: str):
for book in self.storage:
if term in book.title:
yield book
Empty file added docs/tutorial/tests/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions docs/tutorial/tests/books.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[Desktop Entry]
Type=Link
URL=features/books.feature
; Feature files are gathered as usual test modules, but also could be linked into
; directory hierarchy by symlinks.
; Some operation systems do not provide symlinks, so such files could replace them.
21 changes: 21 additions & 0 deletions docs/tutorial/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""
conftest.py is local per-directory plugin of pytest.
Its mission is to define fixtures, steps, and hooks which will be used
by tests gathered by pytest from directory structure below

https://docs.pytest.org/en/latest/how-to/writing_plugins.html#conftest-py-local-per-directory-plugins
https://docs.pytest.org/en/latest/explanation/goodpractices.html#test-discovery
"""

from pytest import fixture

from .steps.library_steps import (
a_search_type_is_performed_for_search_term,
only_these_books_will_be_returned,
these_books_in_the_catalog,
)


@fixture
def search_results() -> list:
return []
Empty file.
Loading
Loading