Warning!
This course was created with an older version of pytest-bdd
.
Over the years, updates to the framework introduced backwards-incompatible changes.
The example project code and transcripts are updated, but the videos still show the old code.
Please review the pytest-bdd
docs to see
specific syntax changes in newer versions.
Now that we know about behavior-driven development, let's start using pytest-bdd
.
We'll start by looking at pytest
, the foundation upon which pytest-bdd
is built, and then we'll set up a project together that uses pytest-bdd
.
pytest is a fantastic, free and open-source test framework in Python.
According to the 2018 Python developer survey, it's also the most popular Python test framework by far. What makes pytest
so great is the fact that it's so simple and concise and Pythonic.
Here on pytest.org's homepage, we can see an example of a simple test. Here we have a simple function that does an increment operation. The test case is a one-line function, prefixed with βtest_β, that does the basic assert
. We can see, based on results, it's totally functional.
This is why people love pytest. It's so easy to get it up and running and start writing meaningful effective test cases.
One thing that makes pytest stand out from other test frameworks is its fixtures.
Fixtures are essentially functions that do setup and cleanup operations in a much more scalable and reusable way.
Let's take a look at the example fixture function here on pytest.org's documentation page.
# content of ./test_smtpsimple.py
import pytest
@pytest.fixture
def smtp_connection():
import smtplib
return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
def test_ehlo(smtp_connection):
response, msg = smtp_connection.ehlo()
assert response == 250
assert 0 # for demo purposes
This is what a fixture looks like right here.
It's prefixed by the decorator @pytest.fixture
and what it does is it sets something up, in this case an SMTP connection. All it does is it sets it up, and then it returns that object.
Any test case function can use a fixture by declaring it as a function argument.
What this does is it will run the fixture and do dependency injection with that returned reference, so that the test case has access to that object, as we can see here.
Fixtures can also be controlled by scope, whether they should be run once per test case, or maybe once per the entire tests we run.
I'm bringing up fixtures because this will become important later when we talk about how pytest-bdd
handles things with its step definitions.
Another awesome facet of the pytest framework is its ability to have extra plugins.
Plugins are a way to extend pytest, usually with some sort of extra bindings or extra features, or whatever you need to do to make integrations with other sorts of frameworks. This makes pytest essentially a limitless framework, because anyone can add plugins.
Pytest provides a bunch of standard ones, as listed here, such as integrations for Django and Flask, or maybe code coverage, or xdist which will run your tests in parallel.
We can even see on the list here the one that we're interested in, pytest-bdd
.
So how does pytest-bdd
fit in with pytest
?
As we saw on the previous page, pytest-bdd is a plugin for pytest
. What that means is that it adds all that extra goodness of BDD on top of the core pytest
framework.
If we look at the documentation page for pytest-bdd
on GitHub, we can see that that goodness is basically Gherkin feature files, together with some Python functions and decorators for writing step definitions that will execute those Gherkin steps.
Gherkin-style pytest-bdd
test cases are essentially run interchangeably as pytest tests.
That's why I favored using pytest-bdd
above other BDD frameworks in Python. The fact that pytest-bdd
is a plugin for pytest means that it gets to leverage all the goodness of pytest, including the fixtures and other plugins.
It's not standalone or isolated, so pytest-bdd
as a project can focus on what it's good at and rely on other plugins for other features to make testing even better.
The rest of this course will focus exclusively on the pytest-bdd
plugin.
If you want to learn more about pytest, I strongly recommend these 2 books: Python Testing With pytest by Brian Okken, as well as pytest Quick Start Guide by Bruno Oliveira. I've personally read both of these books and can attest that they are excellent resources for learning all the ins and outs of pytest.
You can also check out the documentation on pytest.org, which is excellent. You can also go to my blog for more information and some quick tutorials at AutomationPanda.
So now that we know about pytest
and pytest-bdd
, let's set up a project together.
Course Code
As a reminder, all of the code in this test automation university course is also available on my GitHub account, under the tau-pytest-bdd repository. I'll create a branch for each chapter so that you can follow along with the example code as we go.
Let's set up that project together.
I'm already at my terminal, and as you can see, I've already cloned my GitHub repository.
Every time I start working on a new project in Python, I like to create a virtual environment for that project to keep all of my dependencies well controlled. My preferred tool for that is pipenv
.
So, I'm going to set up my pipenv
for my project, using pipenv install
.
Boom. We're ready to go.
Now that I have pipenv
installed, I'm going to use pipenv
to install 2 dependency packages: pipenv install pytest
, as well as pipenv install pytest-bdd
, which is the plugin.
Nice.
Also, worth noting, I'm using Python 3.7, which is one of the more recent versions of Python. Once all this is set up, in my project I'll have a Pipfile
and a Pipfile.lock
which will have all of my dependencies.
Bam.
We should be good to go.
Now that we have our project set up, the next question naturally is, what IDE or editor should I use for developing my project?
Personally, I recommend PyCharm. According to that 2018 developer survey I mentioned before, PyCharm is one of the most popular Python IDEs. And for good reason. It's really nice to use, it has a lot of features.
Note about Pycharm
Warning: PyCharm Community Edition does NOT support BDD frameworks. If you get the Professional edition, it also supports many behavior-driven development frameworks, including ours, pytest-bdd
.
Other good options include Visual Studio Code, which you can get the Python extension for, as well as Cucumber extensions for Gherkin. And there's also PyDev from Eclipse.
I'll be using PyCharm throughout our course as my IDE, but feel free to use whichever one you like best.
In our next lesson, we'll be writing our first test case using pytest-bdd
.