Welcome to the first chapter of Behavior-Driven Python with pytest-bdd.
To start our course, I'd like to give a brief introduction to what behavior-driven development truly is.
BDD has become a popular software development methodology over the past couple of years, almost to the point of becoming a buzz word. Personally, I like to take a pragmatic approach to BDD. In this lesson, we'll look at some of the major practices of BDD and see how they fit in with Python test automation.
So, why do we even need a new software development process like BDD?
Well, these days, software development happens rapidly, and teams are pushed to continuously deliver new products and features. As a result, in the development process, 2 things suffer: collaboration and test automation. And it shakes out in many ways. For example, it's not uncommon for a product owner to describe a feature one way, have the developer implement it another way, and then have the tester try to test it third way — where all 3 amigos are not talking the same language.
Other common problems include poor planning meetings that end up more like “guessing” meetings than setting out a blueprint.
Or a lot of times, documentation and test cases are either abbreviated or skipped. Test automation in and of itself is a fairly steep challenge. And when teams are not always prepared for it or don't set a side time to do it, they’ll either miss their deadlines because they can't get their test automated in time, or though simply skip the testing and automation efforts all together.
How can we solve all of these problems?
The answer is pretty simple — return the focus to the behaviors of the features being developed. This may seem a little bit too simple, but it's the behaviors of the features being developed that deliver value to the end user.
The dictionary defines a behavior as the way in which one acts or conducts oneself. In software terms, a behavior is how a feature operates. It can be defined as a scenario of inputs, actions, and outcomes. We could also call it a “feature function”, so to speak. A product or feature exhibits countless behaviors.
Here are some examples of behaviors.
If we're looking at a web UI, basic interactions such as logging in, logging out, or navigating through pages, or submitting forms would all be considered behaviors of the web application.
We can also look at behaviors at the service API layer, where things like making successful calls, or verifying system state changes, or even receiving expected errors, could also be considered behaviors of the service API.
We could even look at behaviors in real life such as, if I'm at a store, adding items to a shopping cart or even paying for those items at checkout. If I were a panda, even eating bamboo would be considered a behavior.
Focusing on individual behaviors brings major efficiencies to both the development and the testing of software features.
Separating individual behaviors makes it easy to define a system without unnecessary repetition or complication.
For example, let's say that I'm building a shoe store website. There are multiple ways in which I could search for shoes.
Either way, those 2 separate behaviors will lead me to the same place, which is viewing a search results page. From there, I could do even more behaviors such as selecting the first link on the results page to view an individual product.
Separating these behaviors makes the developers and the testers do each individual behavior well because care and attention will be given directly to it. And furthermore, the application simply becomes a composition of multiple behaviors working together.
Behavior driven development then is simply a process that puts behaviors first in both development and in testing.
There are many practices that go along with behavior-driven development.
Three Amigos Meetings are time for the business, development and testing rolls on a team to come together to knock heads and to get on the same page.
Example Mapping is an activity that helps a team define a story and learn what it's about in terms of its rules examples and any questions people may have.
Specification by Example is a way for teams to describe behaviors and really define behaviors using a more formalized language, so that things are crystal clear.
Behavior Implementation is just a fancy way to say that the features get developed and the tests are automated.
We won't spend too much time in this course going over what these different practices are. But I want to just mention them to you so you can learn about them on your own.
Finally, I do want to shout out that BDD should be seen as a refinement and not an overhaul to existing processes.
They're meant to complement the things the team is already doing to help solve those aforementioned problems. For example, it's very common for Agile Scrum teams to start picking up some of these BDD practices to make their development process smoother and better.
Behavior specifications are the main artifacts of the BDD process.
They are, in effect, the requirements, acceptance criteria and test cases for the behaviors. And if a team is using a BDD test automation framework, they also become the test script.
Gherkin, by far, is the most popular specification language because most test frameworks use Gherkin.
For example, if I have a Cucumber Basket behavior, my Gherkin scenario could look like this.
Given an initial state where the basket has 2 cucumbers,
When an action is taken such as 4 cucumbers being added to the basket,
Then verify the outcome. What do we expect? That the basket contains 6 cucumbers.
These behaviors specifications, as we can see, are written in plain language so that anyone on the team could understand them.
They're self-documenting and they're descriptive. Gherkin is not meant to be a programming language, but rather a business specification language.
Since behavior specs are basically test cases, it only makes sense to automate them using some sort of test framework.
And that's exactly what BDD test frameworks do. They will glue each one of those Gherkin steps, based on its text, to some sort of method or function in a programming language, such as Python, so that the BDD test framework can run all those scenarios, like scripts.
Python has a number of BDD test frameworks.
One of the most popular ones is behave, which has been around for a while. It's very similar to the Cucumber project.
Another good choice is the radish framework which extends the Gherkin language with things like constants and scenario loops, making it a little bit more friendly for programmatic testing.
lettuce is another framework that's been around for quite some time and is also similar to Cucumber. Although, it doesn't seem to have as much activity anymore.
For this course though, we'll be using
The reason why we've chosen
pytest-bdd is because it is a plugin for
pytest, which is one of the best test frameworks in Python, and also one of the most popular. Pytest makes it very easy to write simple but powerful tests. It also comes with a bunch of other plugins such as for code coverage, or html reports, or parallel execution.
So, coming full circle now — why would we do behavior-driven development?
The main 2 benefits of BDD are better collaboration and better test automation.
Doing behavior-driven development enables everyone on the team to contribute to these behaviors, not just the programmers.
Gherkin, with its plain language specifications, can be read and understood by anyone. Also, doing BDD means quality shifts left. So, the team does everything properly from the start.
And finally, when it comes to testing an automation, all those Gherkin steps can easily be reused, which creates a snowball effect for getting your test automation work done.
If you want to learn more about BDD, here are some resources.
You can go to my blog at automation panda where I have a full page dedicated to BDD as well as several articles.
As I mentioned before, I strongly encourage you to learn more about BDD as a process.
For the rest of this course, we'll be looking at how do you use
pytest-bdd from a test automation standpoint.