Using Parameterized Steps
In situations where we want to test the same basic functionality but with different values, the current syntax that we're familiar with for test files can be extremely repetitive. That's where parameterized steps come in. In this first video, we take a look at the basics of parameterized steps and how they allow us to make our test files much more concise.
Knowledge Check
We must wrap the parameterized string that we're passing to @given, @when, or @then in the _________ function in order for the parameterization to work properly.
- Aparsers.parse
- Bparsers.params
- Cparsers.parameterize
- Dparsers.parsed
Verify your team's readiness — Request a Demo to verify practice assessments, completion reporting, and CSV / SCORM exports on the Team plan.
Using Scenario Outlines
Now that we've seen how to reduce the amount of repetition in our test file, let's see how we can do the same thing in our .feature files. To do this, we need to use something called scenario outlines. Here's what those look like.
Knowledge Check
Which of the following demonstrates the syntax for leaving a "space" in a .feature file scenario that can be filled in with different values?
- AWhen the user clicks to <button_name> button
- BWhen the user clicks to button_name button
- CWhen the user clicks to BUTTON_NAME button
- DWhen the user clicks to {button_name} button
Verify your team's readiness — Request a Demo to verify practice assessments, completion reporting, and CSV / SCORM exports on the Team plan.
Providing Background in BDD
Next, let's see how to reduce repetition even more by using something called "background" in our feature files. As you'll see, this allows us to consolidate repeated steps up at the top of our Features.
Knowledge Check
If we put a "given" step inside a feature's background, and then add a "given" step directly to a scenario in that feature, Pytest-bdd will use the scenario-specific "given" step and NOT the one in the background
- A
- B
- C
- D
Verify your team's readiness — Request a Demo to verify practice assessments, completion reporting, and CSV / SCORM exports on the Team plan.
Using "And" and "But" in Steps
Finally, let's take a look at a deceptively simple but important pair of keywords that can be used in .feature files to make our tests more reusable.
Knowledge Check
Which of the following could probably be broken up into multiple pieces using the "And" keyword?
- AThe user is an admin with multiple purchases
- BThe user clicks the "Buy" button
- CThe user enters a swear word into the text input
- DThe user is on the shopping cart page
Verify your team's readiness — Request a Demo to verify practice assessments, completion reporting, and CSV / SCORM exports on the Team plan.
Challenge & Solution: Writing Test Functions for "And" Steps
Now it's time for a challenge! In this challenge, you'll be asked to use what you've learned here to write test functions for an imaginary login page feature. Watch the video for more information.
And now that you've attempted the challenge, I'll show you how to solve it.
Knowledge Check
The @and decorator allows us to specify functions for steps that use the "and" keyword
- A
- B
- C
- D
Verify your team's readiness — Request a Demo to verify practice assessments, completion reporting, and CSV / SCORM exports on the Team plan.
View Transcript
Using Parameterized Steps
0:00Hi, Sean here and welcome to this skill where we're going to go a little bit
0:03more in depth
0:04with this behavior driven development stuff that we started on in the previous
0:09skill.
0:10So in the previous skill, we saw the basics of writing behavior driven tests,
0:15which as
0:15we saw tend to be more focused on the higher level functionality of an
0:20application versus
0:22the details of implementation, right?
0:24So while TDD tends to focus on like, you know, the little details, right, like
0:29the fact that
0:30a function that you define gives the right answer when you pass in certain
0:36arguments,
0:38behavior driven development, BDD tends to focus on things like what you see
0:41here, right?
0:42And these are from the previous skill.
0:44So if you didn't watch that, then I would recommend going back and taking a
0:48look at
0:48that before you watch this skill here.
0:52But anyway, the first thing that we're going to talk about here is something
0:56called parameterized
0:58tests and parameterized behavior driven tests or parameterized scenarios, I
1:04suppose you
1:05could call them as well, are essentially a way to run the same few tests with
1:12different
1:13values, right?
1:14So in our tests here, I purposely left out specific values from these, from the
1:19scenarios
1:20that we defined in our features, because that can tend to make your code very
1:25repetitive
1:26if you don't know how to, you know, use these parameterized tests that we're
1:30going to take
1:30a look at here.
1:31So again, just as a reminder, the way that this works, in case you, you know,
1:36need a
1:36little refresher from last time, the way that this feature file and the
1:41corresponding test
1:42file are sort of paired up in behavior driven development, at least when
1:47working with this,
1:49or is it here with this pi test BDD library that we learned about in the
1:54previous skill.
1:56The way that those are paired up is essentially in our test file, we just have
2:00to use these
2:01decorators in order to show pi test BDD.
2:07What functions are sort of the, the code manifestation, if you want to say it
2:13that way, the code manifestation
2:16of the lines that we have in our feature file.
2:19So if we take a look at this, some, well, here, let's, let's pick another one
2:22here.
2:22If we take a look at this, when they enter a valid integer number step in this
2:28scenario,
2:29where the user enters valid input, if we go over to our test file, we can see
2:34exactly
2:35what needs to be done or exactly what this actually looks like in code by
2:40taking a look
2:41at the function underneath the corresponding decorator for that, right?
2:46And pi test BDD actually does link those up behind the scenes as we saw in the
2:51challenge
2:52video, right?
2:53It actually looks for a matching step with this string in it, right?
2:57They enter a valid integer number.
2:59They enter a valid integer number.
3:01And that's how it actually orchestrates everything when we run our tests.
3:05So again, the idea of this is that the feature file serves as sort of a common
3:11ground between
3:12the developers and other non-technical folks so that they can speak the same
3:17language with
3:18regards to software behavior and linking them up with the actual tests that
3:23developers
3:24or testers, a lot of times those are the same people, linking those up with the
3:29tests that
3:29those people write makes it so that in theory, anyone should be able to run
3:35these tests and
3:36understand what's failing.
3:38Now, as we've seen previously, if we actually run these things, that output
3:42might not necessarily
3:43be the most, you know, manager readable thing or non-technical readable thing.
3:49But there are other ways that you can make it a little bit more readable as we
3:53'll see
3:53a little bit later on.
3:55So anyway, let's get into the parameterized steps thing.
4:01First of all, let's say that instead of just kind of doing general steps here,
4:07right, saying
4:08the user is on the how many times, I guess that one's pretty specific there,
4:12but we'll
4:12say when they enter a valid integer number, you might want to be more specific
4:17about this
4:17and say something like when they enter the number 10.
4:24Okay.
4:25And then you could say then the program prints out and you'd actually have the
4:31exact string,
4:32right, or the exact numbers that the program prints out right here.
4:37Oops, let me just paste that there.
4:39All right.
4:40Now, this is a much more specific scenario that we've written here.
4:44And the advantage of this is that because it's more specific, kind of obvious,
4:49linguistically,
4:51I guess it's also less ambiguous.
4:54So, you know, when you when we had before, when they enter a valid integer
4:59number, and
5:00here I'm actually going to copy this here so that I can duplicate that like so.
5:06All right.
5:07And then I'll put it back the way it was and paste the old one down below.
5:13Oops, there we go.
5:14Just so that we have this around for reference here, okay, and we'll say
5:18instead of user
5:19enters valid input, we'll say user enters 10.
5:22Okay.
5:23All right.
5:24So with the old thing here, the user enters a valid integer number.
5:27It might not be super clear what that means, right?
5:31So in fact, when the user enters that number, it's actually a string that we're
5:36specifying,
5:37which is a little detail that could nevertheless have some important
5:40consequences down the
5:41line.
5:42So anyway, the point of this being that if we have specific values like this,
5:47it gives
5:48us something much more concrete to talk about when something ends up not
5:53working the way
5:55that we the way that we hoped it would.
5:58Okay.
5:59So the problem with this though is if we want to run a similar scenario with
6:03multiple different
6:04values, right?
6:05So maybe the user enters 10, but maybe we also want to run that with the user
6:11enters
6:12maybe two.
6:13Okay.
6:14And in this case, we would have when they enter the number two, and we would
6:19have the
6:19first two primes there.
6:21And maybe we also have another one where it's the user enters maybe something
6:26like zero,
6:29we might expect the program to output.
6:31Well, here, first of all, we would say when they enter the number zero, then we
6:36would
6:36say the program prints out maybe the string nothing.
6:40Okay.
6:41Something like that.
6:42Well, notice that there's a lot of repetition in here.
6:45And, you know, while certain things like this given step in each scenario, we
6:51'll only have
6:52to write one corresponding function for that, right?
6:55We saw that just because of the way that pi test BDD matches things up, we're
7:00only going
7:00to need to define this thing once.
7:02But because we have different strings for each of these steps, even though they
7:06're the
7:06same, what we would actually have to do is say, and here I'm going to just copy
7:11this
7:11here and paste it a few times so that we can use that for our example, we would
7:17actually
7:17have to say they enter or yeah, here they enter the number zero.
7:23All right, so I'm just going to say, we'll say, remove that there and say they
7:29enter the
7:30number zero, and then we'll say they enter the number two, and then they enter
7:38the number
7:3910.
7:41So again, lots of repetition.
7:43The repetition is kind of spreading into the test file here.
7:49And we would of course have zero here, followed by two, followed by 10.
7:57And then what we would expect or what we would have to do rather is we would
8:01have to
8:02do that same thing for the then functions.
8:06So here's what that would look like.
8:08We would have to say here, I'll copy this one here, just like I did for the
8:12other one.
8:13Oops, let's try that again.
8:15There we go.
8:16All right, so there's that one, that one, and I'll paste it one more time there
8:19just
8:19to have the old one around.
8:21And now we would have to say the program prints.
8:25And then we would have in this case, 235, whatever.
8:29All right, we already have that there actually, but we need to replace that
8:34right here.
8:34All right, so we'd have to do that here.
8:37We'd have to do that for the two numbers.
8:40All right, so we'd say the program prints out two and three.
8:45And then we would have to say the program prints out nothing.
8:50And we would have to then go in here and modify the expectations.
8:55So we just leave that one the way it was.
8:58We'd have to change this one to two comma three.
9:01And we'd have to say that this one is going to be equal to the string nothing.
9:06So again, this is a big problem so far because we've just introduced a ton of
9:13repetition
9:14into our tests, not only in the feature file, but also in the test file.
9:18Now, as far as the feature file goes, there are ways that we can reduce this
9:23repetition
9:23further, but we're actually going to leave this for now because this would
9:27actually be
9:28something that would be nice to allow our non-technical coworkers to write out
9:36just so
9:36that they can be very specific about how the software should behave in
9:40different situations,
9:42right?
9:43So we can go back and show them how to reduce the repetition a little bit later
9:47.
9:47But the main thing that we're concerned with doing right now is we're concerned
9:51with reducing
9:52the massive amount of repetition in this test file now, right?
9:58So here's what we can do.
10:00Essentially, this works in a similar way to how functions work in Python, right
10:05?
10:06But similar anyway, as you'll see, what we can do is because there's only like
10:11one or
10:11two little differences in these when, you know, in these when functions that we
10:16've defined,
10:17as well as in these then functions that we've defined, what we can actually do
10:21is replace
10:22the parts that are the same with arguments.
10:26And actually this, this starts here in the decorator string.
10:30If there's a part of that string, right, a part of that step that we want to
10:33sort of
10:34leave open to different values, we can say they enter the number.
10:39And then in curly braces, we can say something like num, or we can call it n or
10:45whatever
10:45we want to call it.
10:47We'll just say something like user input.
10:49All right.
10:50And what that will do is that will tell a pi test BDD that we want this thing
10:56to match
10:56any string, right?
10:58Any step, well, any when step that is in our feature file that has that basic
11:05format with
11:06a value here, and we can basically just take that value now, and that will
11:10become an argument
11:11that we can use.
11:12So we'll just say user input like so.
11:15And then we're going to pass that in here by saying, here, we'll just use a
11:19template
11:20string there, user input.
11:23And that's going to be followed by that, that backslash n.
11:27Okay.
11:28So that's really all we need to do there.
11:31And we can remove these other ones.
11:34And what it'll actually do is that'll match all of the when steps there that
11:38start with
11:39they enter the number and then have some sort of value there.
11:42So if we run this thing, what we'll see, oh, and here before we do that,
11:46actually, there's
11:47something I almost forgot there, there is one more thing that we need to put in
11:51here
11:52when we're, you know, when we're using these parameterized steps, and that is
11:56we need
11:57to actually say parsers dot parse, and wrap that string like so.
12:03And this parsers thing is actually just something that we import from pi test B
12:07DD as well.
12:08So we'll say parsers there.
12:10And now if we run our code, what we'll see is that while the, not all the tests
12:14pass,
12:15right, because of this nothing thing, and we can just remove that one for now
12:18if we want
12:19to actually see them pass because they should.
12:22So I'll just remove that one there.
12:23All right.
12:24If we run this again, what we'll see is that sure enough, they all pass and it
12:28shows us
12:29that we're, you know, testing this for the values two and 10, right?
12:34Those have sort of magically appeared there.
12:37And we can do the same thing with the then steps, which we'll actually do in
12:43the next
12:43video.
12:44So I hope this has been informative for you, and I'd like to thank you for
12:47viewing.
Using Scenario Outlines
0:00All right, so now that we've seen the basics of parameterizing things in our
0:05test file,
0:06the next question that you might have is, is there a way that we can reduce the
0:11repetition
0:11inside the feature file?
0:13Right?
0:14In other words, if we know that we're just going to be kind of like reusing the
0:17same
0:17basic scenario, and by the way, let's put back that other scenario there.
0:21We'll come back to this in just a minute, right?
0:23If we know that we're going to be reusing essentially the same scenario with
0:27just a handful of,
0:29you know, sort of blank spaces here, swapped out, is there a way that we can
0:34allow the
0:34person writing the feature file to do this?
0:37Well, the answer to this is yes, and this is something called using scenario
0:44outlines.
0:45But before we take a look at that, let's actually go back to our primes program
0:50test file and
0:52do the same kind of parameterization that we did with the given steps, or sorry
0:59, the when
0:59steps that is with the then steps.
1:03So again, in each of these cases, we're just expressing some sort of
1:09expectation, right?
1:11You know, basically the output of the program.
1:14And that's really the only difference between each of these steps.
1:17So what we can actually do is we can parameterize these as well, just by saying
1:23something like
1:24expected output.
1:26All right, and we're going to have to use that parsers dot parse thing there as
1:32well
1:32in order to in order for that to work correctly.
1:35And now we can basically just replace this whole string with expected output.
1:43And that allows us to remove these other ones as well, right?
1:46This is going to essentially automatically pick up on the fact that there are
1:52multiple
1:53variations of this in our feature file, right, multiple variations of the
1:56program prints
1:57out blah, blah, blah, right?
1:59Yep, sure enough, we see that there's this one, there's this one, there's this
2:04one, there's
2:05other ones here too, which we might actually want to remove those just because
2:10now that
2:11this is parameterized, it's going to pick up on things like this, right, a
2:14message of
2:14disgust, you know, we might want to actually, we might want to actually specify
2:20the message
2:21that we want here.
2:22So we could say the program prints out how dare you, for example, all right,
2:29just like
2:29we did in the test here and oops, we only used one exclamation point there.
2:33So let's actually remove that like so.
2:36And this will actually be picked up on as well, right by this parameterized
2:41string that
2:41we have here, so we can actually just remove this thing.
2:45And that will be tested by our parameterized then step up here.
2:51All right, and we'll probably want to rename this thing here, because we're not
2:55checking
2:55for valid input anymore, we'll just say something like check output.
2:59And that's all we need to do there.
3:00So let's try running this again.
3:02And what we should see here, if we run it, oops, expected output is not defined
3:06.
3:06That's because I forgot to add it to the arguments here, right?
3:09So we're just going to say expected output like so alongside run program.
3:14And if we run this again, we'll see that one of these things fails.
3:18Right, that is this thing that we saw in the feature file, the first end prime
3:21separated
3:22by commas.
3:24So let's actually just remove this thing now.
3:26We don't need that anymore.
3:28And we can remove the other one here, just that corresponding then step,
3:33because we now
3:33have all of that parameterized.
3:35So let's try that again, and we'll have to come back to that nothing thing as
3:39well.
3:39In fact, let's actually just modify our primes program so that it takes care of
3:44that.
3:44We're just going to say something like if n equals zero, then what we're going
3:52to do
3:53is we're just going to print out nothing like so, and that should make that
3:57test pass.
3:57All right, cool.
3:58So we see all of our tests are passing now and we have those parameterized.
4:02But going back to our original question here at the beginning of the video, how
4:07can we
4:08do that same kind of thing where we reduce the repetition in the feature file?
4:12Well, here's what this is going to look like.
4:15All we really need to identify here is the things that are, well, the things
4:20that are
4:21different in between the repetition.
4:23So there's this number here, which would be the input.
4:27So we'll just say, we'll call that something like user input.
4:30All right.
4:32And then for the output, what we're going to do is we're going to say something
4:35like program
4:36output.
4:38And I'm just writing this all as like a one string and lowercase.
4:41You can add those.
4:42You can add the underscores there as well.
4:44That's perfectly acceptable.
4:45In fact, why don't we do that?
4:46Because that's a little bit better.
4:48And anyway, this for this scenario, we're no longer going to say user enters
4:53two.
4:54We're actually going to say something like user enters valid input again,
4:59because what
5:00we're going to also do is delete all of the scenarios that where that's
5:04repeated.
5:04OK, so user enters zero, user enters 10, user enters invalid input.
5:10These are-- this one's actually a repetition as well.
5:13We can specify this as the-- they enter instead of the number 10, we would say
5:19something like,
5:20well, I guess we've kind of made this more difficult by using the number in
5:25there.
5:25Because this isn't really a number.
5:27But we could say the number a, right?
5:30And what that'll do is that will actually pass that through the same when
5:38clause.
5:39There we go.
5:40They enter the number.
5:41And that a will be passed through.
5:44And we should expect to see this how dare you message there.
5:48So we can even delete that one as well.
5:51Although I guess we probably wouldn't want to do that because in this case,
5:56we'd have to put that under the scenario, the user enters valid input.
5:59This is the user enters invalid input.
6:01So we'll just leave that the way it is.
6:03So we'll just say something like the user enters invalid input a.
6:12But we can remove these other things here under the first scenario.
6:16And here's what this looks like in the same indentation space,
6:23the same indentation underneath this first scenario.
6:27We're going to say examples.
6:29And here's what this looks like.
6:31We actually create this little table thing.
6:34All right.
6:36And oops, there we go.
6:37We actually create this little table thing with the pipe symbols.
6:41And we're going to say user input.
6:45All right.
6:45So we're going to say user input and use a pipe symbol to divide that from the
6:51program
6:52output.
6:54And now that we have that, what we can do, we're basically just going to create
6:58a table with the expected values inside of it.
7:00So for the first one, if we want to test if the user input is 0, well,
7:04then our expected output there is going to be nothing, the string nothing.
7:12And then what we're going to do is we're going to do--
7:14if user input is 2, we'd expect for the program output to be 2 comma 3.
7:21And finally, if the user input is 10, this is going to be a rather lengthy
7:26thing.
7:26We might have to extend these a little bit.
7:29What we're going to do is we're going to go back to here--
7:32oh, it looks like I got rid of it there.
7:35I'm going to need those primes back.
7:37So hang on just one minute.
7:38We'll come back to here.
7:39While I-- there we go.
7:40I'm just going to go back to here, copy this, and then we'll put it back the
7:43way it was.
7:46There we go.
7:47All right.
7:48So let's paste that in there now.
7:50That's what I wanted there.
7:52And that should be all we need.
7:53All right.
7:54We don't have to move the whole thing over, although that might make it more
7:56readable
7:57if we were going to add more lines.
7:59OK, so what PyTest is going to do now is it's actually going to take all of
8:04these examples
8:05that we've created and substitute them into this scenario for user input and
8:12program output.
8:14So let's just try running this thing.
8:16What we're going to see here is--
8:18there we go.
8:19We see that it's created multiple test cases here for 0 and nothing.
8:25That one passes for 2 and 2, 3.
8:28That one passes for 10, and then the first 10 primes.
8:32That passes.
8:33And then we have this invalid input on the prompt blah, blah, blah.
8:37That one fails because the step definition isn't found for that.
8:44Oh, that's just because I changed this when clause there.
8:46Let's change that back to whatever it was before.
8:50They enter a valid--
8:52where is it?
8:53They enter a letter instead of a number.
8:54That's the one we want.
8:55So I'm going to copy that, paste that back there.
8:58And by the way, it is important to notice that this actually did warn us that
9:03we didn't
9:04have a matching test case for this one scenario that we defined or this one
9:10when step anyway
9:11that we defined.
9:12So that basically protects you from creating extra things in this feature file
9:17that don't
9:18have a corresponding test in the test file.
9:22Make sure that they're kept in sync with one another.
9:27So let's save this.
9:28And we're going to go back and run this again.
9:29And we should see that all of our tests pass.
9:31I'm going to remove that little dash s flag there.
9:34And there we go.
9:35We see that-- this is a little bit more readable now.
9:38And it shows that all of our tests pass as well as the values that we passed in
9:42for each
9:43of those.
9:44So anyway, that is the basics of using scenario outlines to reduce the amount
9:49of repetition
9:50in a feature file.
9:52So I hope this has been informative for you.
9:54And I'd like to thank you for viewing.
Providing Background in BDD
0:00All right, well, you've probably noticed by now that one of the main themes of
0:03this skill so far has been
0:05reducing repetition in behavior driven development code, right?
0:10So we saw how we could
0:12You know really reduce repetition by simply using the same steps over and over
0:19again
0:19We'll talk about that in more detail shortly as well because there's one more
0:22thing I wanted to mention about that
0:24but
0:25There's one thing that I want to mention here specifically first about feature
0:30files and
0:31That is you may have noticed that there's still a bit of repetition here in the
0:36basic setup right now
0:37It's a pretty common occurrence in behavior driven development that the
0:42the given step in a number of scenarios is gonna be the same right if you're
0:47you know testing out features of some sort of
0:50page or some sort of
0:52You know specific setup in an application and Python
0:56You're probably gonna need to have that same given step in a number of
1:01different scenarios
1:02And that's just really unnecessary repetition, right?
1:05Some people like to have that thing repeated over and over again just so that
1:08they know but
1:09Ultimately, that's just a bad practice to have that repeated, you know five six
1:14seven eight times right or more and
1:18That's why the gherkin syntax gives us something called
1:23Background that we can use to apply the same step to
1:28Multiple scenarios. All right, so here's what this looks like what we're gonna
1:33do is inside our feature
1:35Right our first end primes calculator thing here
1:38up at the top before the scenarios we're gonna add this background property and
1:46Essentially what this allows us to do this gives us a place to group everything
1:49together that
1:51You know that that we should have in common between all of the different
1:55scenarios now
1:56Usually the given step is gonna be the only thing in here that's repeated
2:00You know
2:02Really with most scenarios you're going to have a different when and then step
2:06that's usually the point of the whole thing
2:08So what we're gonna do here is we're just gonna take this repetitive given the
2:13user is on the how many primes prompt
2:15We're gonna put it in the background and we only have to do that once right so
2:19again this kind of
2:20Provides like shared code if you will or a shared step for all of the scenarios
2:26So if we add another scenario down here, it's automatically going to have this
2:31given step
2:32And so we won't have to we won't have to specify that again
2:36Cool, so that is pretty much all I wanted to say about that
2:42Let's just try running this thing so that we can actually see it in action
2:45Alright, so we're just gonna run pi test primes program test
2:47Pi and what we should see is that sure enough all of the tests run just like
2:52they did before
2:53Except there's a little bit less repetition here now that might seem you know
2:58that might not seem like a whole lot of savings there because actually
3:01We had to write this extra line this extra background line
3:03So we ended up with the same number of lines in here
3:06But the the nice part is if we were to go and add more scenarios now
3:11That would really reduce the amount of code that we would need to well the
3:15amount of extra lines that we would need to add
3:18Okay, now you might wonder what happens if we decide to add a different given
3:23step here, right?
3:25So if we go in here and add like another scenario, we'll just do something
3:28silly here. We'll just say something like user
3:31enters
3:33an empty string that's actually not too silly that's a valid thing that we
3:36would want to test and
3:38What we'll do here is we'll say we don't have to say given the users on the how
3:42many primes prompt anymore
3:44But just just for the sake of demonstration. Let's do that with something a
3:48little bit different. All right, so we're gonna say given
3:50the user is a
3:53Human alright, there's a silly part there right and this will just allow us to
3:58you know
3:58This will just allow us to demonstrate a different step in here
4:02So we're gonna say given the user is human and then what we'll do is we'll just
4:05copy these and
4:06Say something like when they enter
4:08an empty string
4:11Okay
4:14Then what we'll say is then the program prints out
4:17I
4:19Think here. We'll even put that in quotes. I think you forgot
4:24something okay, and
4:26What we'll see here is if we go into our test file, we're gonna have to
4:31actually add these steps
4:32Of course, so I'm just gonna copy these we'll go into here. We'll add we'll
4:36just add these down here
4:38We we don't have to sort them as you know given then when just because well, it
4:43's it's gonna be easier this way
4:44So we're gonna say I'm just gonna sort of change that into the given decorator
4:49there
4:49So we'll say given the user is human all right and then underneath this what we
4:55'll do is we'll say human user and
4:57Then what we'll do is we'll just say something like
5:00We'll just print out the user is human just so that we'll see that all right
5:07and
5:07Then we'll have our other
5:10Steps there so we'll say something like define or here. We're gonna need at
5:15when okay, and then we're gonna bring that up here and
5:17say they enter an empty string and
5:20Here, we'll just do the other decorator here for this too
5:25And then we'll say then and then we'll say the program prints out
5:29I think you forgot something and let's just define those here real quick
5:33We're not gonna make any assertions in there. That's not human user. We'll say
5:36empty string
5:37Input okay, we're just gonna say print
5:41Entering an empty string
5:46Okay, and I'm just putting these functions here so that we have something to
5:52look at here and then we'll say
5:53define
5:55forgot something and
5:57Then we'll just print out you forgot something
6:00Cool, so that's all we should need to do there
6:03Let's just try this really again
6:05This is just a demonstration to show you what happens when you define something
6:09new oh and oops that actually didn't work because
6:12Notice that this the program prints out thing that was picked up by this thing
6:18up here
6:19Okay, so we actually want to change that a little bit so we'll change this to
6:23say the program
6:25says alright just to make that a little bit different there and
6:29We're gonna we might want to change this a little bit too
6:34I don't remember what we said for the the enter the number thing, but we'll
6:38just say something like they
6:39You know what we'll say they don't
6:43Oops, let's try that again. They do not enter anything and hit enter
6:49All right, that should be a little bit better. So let's just bring these back
6:53over here. Okay, we're gonna
6:55Piece that into the new test things here
6:58So we're just gonna say there we go
6:59They do not enter anything and hit enter and then we'll say the program says I
7:03think you forgot something
7:05Alright
7:07There we go, and let's try this again. Hopefully that works a little bit better
7:11than what we had before and
7:12Sure enough what we see this is actually maybe not what you expected
7:16It adds this the user is human step, but notice that before this
7:22We have this on the prompt thing which is from the background
7:27So in other words when you add a given step when you already have this
7:31background thing here
7:32What that's essentially going to do is that's just going to run both of these
7:36right?
7:37It's gonna run the background and then it's going to run this
7:40Given thing here. So in other words if you
7:42Really want to use this background thing make sure that that step really does
7:47apply to all of the scenarios in your feature because otherwise
7:51You're just going to be you know, you're gonna be complicating things for
7:55yourself, right in this case
7:56If you really wanted a different, you know a different given step here
8:01You would just have to create another feature there and put that inside of
8:04there without the same background
8:06So anyway, that is the basics of using background in feature files
8:11So I hope this has been informative for you, and I'd like to thank you for
8:14viewing
Using "And" and "But" in Steps
0:00Okay, so now that we've taken a look at how to provide background and features,
0:05we're
0:05going to talk about one more thing that can be really helpful when writing
0:09feature files
0:10that are fairly complex.
0:13And these are two important keywords, if you want to think of them that way,
0:17called and
0:19and but.
0:20Now these are both used in very similar ways in feature files, but in order to
0:24demonstrate
0:24these, what I actually want to do is just kind of break this out into another,
0:30you know,
0:30another example so that we can reduce the clutter that we've kind of
0:35accumulated so far.
0:36So I'm just going to create a few new files, really just two new files, one
0:40feature file
0:41and one test file.
0:42So we're going to say new file.
0:45And we'll say something like and but dot feature.
0:50Okay, that's just what we're going to be doing here.
0:52In fact, actually, let's rename that more after like some sort of fictional
0:55feature here.
0:56Let's let's say that we're building an application and Python that allows users
1:00to log in, right?
1:01So we'll call this like the login page dot feature.
1:05And then what we'll do is we'll have the test for the login page, which is
1:08going to be login
1:10page dot or underscore rather test dot pie.
1:16Now as you can probably imagine, if we were going to do this in real life, you
1:18'd probably
1:19have a login page dot pie file, but let's just pretend that that exists and,
1:24you know,
1:25it'll just make this example go a lot faster if we don't have to actually build
1:28that thing
1:29for ourselves.
1:31So what we're going to do in here is let's imagine, you know, let's imagine
1:36some scenarios
1:37really just let's let's imagine the scenario where the user logs in
1:41successfully.
1:42Well, here's what that might look like.
1:43First of all, we're going to write a feature. All right, so we'll just say
1:49feature.
1:49And what we'll do here is we'll say user authentication, something like that.
1:56And now that we've done that, let's think of a scenario.
1:59All right, so let's some probably for a background here, we can say, given the
2:07user is on the
2:09login page, okay, that's just going to apply to all the scenarios in this
2:13feature, as you
2:14can probably imagine.
2:16What we're going to do now is we're going to define a few scenarios.
2:20And the interesting thing here is that these scenarios are really a little bit
2:26too complex
2:27to describe just using a single step.
2:29So let's just take a look at the successful login scenario, right?
2:33So we'll say scenario successful login. All right.
2:38And what this might look like is we already know that the user is on the login
2:44page, but
2:45you know, how is the user going to actually successfully log in?
2:49Well, they're going to enter in their email or username to the email or
2:54username text
2:55input there.
2:56They're going to enter in the correct password.
2:59And then they're going to click this, you know, login button or whatever,
3:03whatever we
3:04end up writing on that button.
3:06And those are really three different things that the user is doing.
3:09Now, the way that you end up dividing this up is really up to you.
3:14But the way that I would suggest you do it is you actually specify these two
3:18things here
3:18as given steps.
3:21All right.
3:22And then you make clicking the login button, the action, this will just make it
3:27a lot easier
3:28as you'll see in the tests to reuse these things later on, right?
3:33If we want to test, for example, what happens when the user clicks the login
3:36button without
3:37entering anything into these text inputs, we're going to it's going to be
3:41really a nice
3:42thing that we've split this up because we won't have to write a whole new, you
3:46know,
3:46a whole new piece of functionality for that login button.
3:50So here's what this is going to look like.
3:53And I'm just, well, first of all, I guess let me show you what this would look
3:56like if
3:57you were to do it, what I would call the wrong way, right?
4:00We've set up this given thing here.
4:03What we'll do is we'll say when the user, or we can say they, when they enter a
4:10valid
4:11username, a valid password and click the login button, right?
4:20That's a pretty lengthy when thing there.
4:23And the problem with this again is that because of the way that these feature
4:27files work with
4:28PyTest BDD, we wouldn't be able to reuse any of this over in the test file.
4:34All right.
4:35So we're not going to want to do that.
4:36But here, let me just finish this test here.
4:38I'll say, then, and this is just the expectation here, we'll say, then they
4:47should be redirected
4:49to the dashboard page and should see a welcome message or something like that,
4:57right?
4:58Or maybe a welcome pop up.
5:01Okay.
5:02So again, we see the same problem here with this then step.
5:07This is really two things that we're testing, right?
5:10They're going to be redirected to the dashboard page and they should see a
5:13welcome pop up.
5:14Now, interestingly enough, what the Gherkin syntax allows us to do in order to
5:21actually
5:22split these things up and make them more reusable is it allows us to simply put
5:26these
5:26things on different lines.
5:29So here's what we're going to do here.
5:30We're going to say, you know, when they enter a valid username and they enter a
5:38valid password
5:41and we already wrote and there, all right, but it's you should be with a
5:45capital letter
5:45there and they click the login button, then they should be redirected to the
5:51dashboard
5:52page and they should see a welcome pop up.
5:59All right.
6:00So again, this is just a sort of an add on step that Gherkin syntax allows us
6:05to use
6:06in order to make pieces of our application more reusable.
6:09So now if we go back into the login page test file, which we haven't written
6:14anything in
6:15yet and add separate steps or separate functions for each of those things,
6:20right?
6:21In other words, we're going to have separate functions for this thing here when
6:24they enter
6:25a valid username and this one here when they enter a valid password and this
6:30one here when
6:31they and they click the login button and that will allow us to rearrange those
6:36and reuse
6:36those as needed.
6:38Okay, so let's go back to login page test.
6:40Here's what this is going to look like.
6:42We're going to start off by importing from pi test BDD.
6:48We're going to import given when and then and here's the thing.
6:54There's not really a separate decorator for and, right?
6:59There's basically you just use the decorator for whatever step these are under.
7:04So we would put these under when since they're actions, you could also have
7:10them as sort
7:11of preconditions, right?
7:12Under given.
7:14And I think that's what I said at the beginning, but actually I think it makes
7:16a little bit
7:17more sense to have these as actions because again, we might want to test what
7:21happens
7:22when the user enters a valid username and there might be something specific
7:26that we want
7:27to check after that like that the box is outlined in green, something like that
7:32.
7:32Okay.
7:33So anyway, now that we've imported those things, we're going to define the
7:37basic steps for this
7:39and that is actually something I'm going to leave up to you as a challenge.
7:42Okay.
7:43So I will see you in the next video and I'll describe what exactly is expected
7:47from you
7:47and give you a few more details about the and keyword and how it relates to
7:52functions
7:53inside of here.
7:54So I hope this has been informative for you and I'd like to thank you for
7:56viewing.
Challenge & Solution: Writing Test Functions for "And" Steps
0:00All right, so as promised, here is the challenge video where basically you're
0:05going to take
0:06what we've written in this feature file and write test functions for it.
0:12Basically all you have to know, and I already mentioned this, but I'll say it
0:16again, all
0:17you have to know is that when you use and underneath one of these steps, such
0:22as when
0:22or then, you're just going to use the same decorator for it as you would have
0:28if, well,
0:28you're going to use the decorator for whatever step it's under.
0:31So you're going to use when decorators for when they enter a valid password,
0:34when they
0:34click the login button, things like that, right?
0:37Because these specify actions.
0:39And likewise, you're going to use given for any, we don't have any ands there,
0:43I suppose.
0:44You could say the user is on the login page, you know, and if you wanted to add
0:49some other
0:50precondition, maybe it's possible for the user to be on the login page when
0:54they're already
0:55authenticated.
0:57Well, sites don't do that, but you get the idea, we might say and the user is
1:03not authenticated.
1:04Okay, and you could do that there.
1:08Now, as far as writing these test functions goes, all you really have to do is
1:13print them
1:13out just to prove that everything's going on as it should in here.
1:19So one last thing that I wanted to mention too before you go into your
1:22challenge and
1:23actually write these things and run it is I mentioned that there was another
1:27keyword
1:28called but right inside the feature files that we could use.
1:33And really that does the exact same thing as and it's just more, it just makes
1:37more
1:37grammatical sense sometimes to do that or it really highlights, you know, when
1:43something
1:43is not normal, right?
1:46So you could say something like given the user is on the login page, but the
1:51user is
1:52authenticated, right?
1:54In that case, what we might expect, right, if the user is already authenticated
1:59is that
1:59the user will be redirected to another page or something like that, right?
2:05So again, this but does the same thing as and, right, programmatically, but
2:12grammatically,
2:13it really helps us to communicate our intentions a little bit more clearly.
2:17Okay, so I'm going to remove this one there.
2:19But anyway, that is your challenge is just to write the corresponding functions
2:23for these
2:24so that they run.
2:26And if you want to test out how much more reusable this is, try writing maybe
2:30another
2:31feature for or not another feature, but another scenario for an unsuccessful
2:37login, right,
2:38where the user enters a username and an invalid password and clicks the login
2:42button.
2:43And you'll see how much easier it makes, you know, how much easier these
2:47keywords make
2:48it to reconfigure things with a minimum of extra code.
2:53So anyway, that is your challenge.
2:54Feel free to give this about five to 10 minutes to complete.
2:57And once you've given it a try, you can move on to the next video where I'll
3:00walk you through
3:01the solution.
3:02So I hope this has been informative for you and I'd like to thank you for
3:05viewing.
Challenge & Solution: Writing Test Functions for "And" Steps
0:00All right, well, hopefully you've given this a try.
0:02Let's take a look at the solution.
0:04So I'm going to start off here just by copying some of these
0:07to make it easier to set up over in the test file.
0:11And I'm just going to put the corresponding decorators
0:14with each of these first.
0:16So again, this is going to be given.
0:19All right, so we'll say at given,
0:22and then we'll say the user is on the login page.
0:25And then for scenario, we don't really need anything
0:28for that. That's just something that's defined in the feature
0:30file.
0:30We're going to change this one now to when.
0:33So we'll say, oops, let's try that again.
0:35There we go, at when.
0:36And then we'll say they enter a valid username.
0:39And then we'll do and.
0:42But this one, of course, is going to turn into when,
0:45because it's under the when step.
0:47It's an action, right?
0:49And then we'll do the same thing for click the login button.
0:52So we'll say at--
0:54there we go, at when they click the login button.
0:58And finally, we're going to do then.
1:01So I'll put a space in between there,
1:02just to make it easier to keep track of those.
1:05So we'll say then they should be directed to the dashboard
1:09page.
1:10And for and, since this is under then,
1:12we're going to change that to then as well.
1:15All right, we're going to remove and there.
1:16And we'll just say then they should see a welcome pop up.
1:20And now we just need to write the corresponding functions
1:23for each of these.
1:24So we're just going to make this one something like user is--
1:30here, we'll just say on login page for that one.
1:34And we'll just say print.
1:35And we'll say user is on the login page.
1:40All right, let's not put exclamation points after all
1:42of those.
1:42That's going to get a little bit tiring to read.
1:44But we're going to do the same thing for this one now.
1:47OK, so we'll say something like user enters some username.
1:54All right, some valid username we'll say.
1:57And then we'll do the same thing.
1:59Oops, I forgot the function there.
2:00That should be enter username.
2:02And by the way, you may have noticed here
2:05that these two things here anyway
2:08might make for good parameterized tests.
2:12Because for now, what we've said is they enter a valid username.
2:16But what you could say is you could actually
2:18say something like they enter and you could have value into the--
2:26and then you could say something like input name, text input.
2:32And you could use that to test pretty much any text input
2:37in the app that you're testing.
2:38So that might really reduce the amount of test functions
2:42that you have to create.
2:43But we'll just leave it the way that we had it first.
2:48So we'll do the same thing with our password now.
2:50So we'll say enter password.
2:54And we'll say user enters some valid password.
2:58And then we'll do the same thing for the login button.
3:01We'll say user--
3:04there we go-- clicks the login button.
3:08And then for the then things here,
3:11we'll just say something like redirected.
3:16Oops, I already have user clicks the login button.
3:19Let's change this to something like is--
3:22or here we'll say check-- checking, rather--
3:25if the user was redirected.
3:30OK.
3:31And then last but not least, here we'll
3:34say something like check if redirected.
3:38And for the welcome pop-up, we'll say check if welcome.
3:42And we'll say checking if the user sees a welcome pop-up.
3:48That's all we really need to do there.
3:50So let's give this thing a try.
3:52And again, notice that there's nothing in this test file
3:56that's actually telling PyTest BDD
3:59when all of these functions should be run.
4:02The entire specification for that
4:04is in this feature file, which, as we've already
4:07established in this skill and previous skills,
4:10is editable not just by developers.
4:13So if someone wanted to sort of rearrange these things
4:18and test another scenario, it would be very easy for them
4:22to do that.
4:22They wouldn't have to know anything about writing Python
4:25code in order to make that happen.
4:26They could just come in here and say,
4:28when they enter a valid username, or better yet,
4:31if we were to parameterize this thing,
4:33you could have a string with symbols in it, for example,
4:36as into the username input, something like that.
4:39And ultimately, that would make it much easier
4:42for non-technical people to write those tests.
4:44So anyway, let's just try running this thing.
4:47We're going to run this file.
4:49Since we created a new file, we're going to say PyTest,
4:52loginpagetest.py.
4:54We're going to run it with the dash v and dash s flag
4:57so we can see what's going on there.
4:58And oops, it looks like that didn't work there.
5:00That's because we need to actually import the scenarios
5:04from the loginpage.feature file.
5:06So we're going to say, here we're going to import scenarios
5:10as well.
5:11And then we'll say scenarios.
5:13And that's going to be loginpage.feature, right?
5:16We're manually linking that up with this feature file
5:19because there's nothing in the naming convention that actually
5:22shows what belongs to what.
5:24So this says that these tests are for that feature file.
5:28Cool.
5:29So let's try running this again.
5:30And sure enough, we see that everything gets printed out
5:33in the right order.
5:34You can verify this, but it says users on the login page.
5:37User enters some valid user names, some valid password.
5:39User clicks the login button.
5:41And then we're checking those two things down at the bottom
5:44there.
5:44So all that would be left, if you wanted to actually
5:46use this for real testing, is implementing
5:51the actual functionality for each of these things.
5:53So there's lots of libraries that you
5:55could use for doing this, if this were a real page.
5:58And that's something that we're going
5:59to take a look at in a later skill.
6:01So anyway, that is the solution to the challenge.
6:04I hope this has been informative for you, and I'd like to thank you for viewing
6:06.
6:07[BLANK_AUDIO]
Team training path
Turn this skill into assignable team training
This free skill is a preview of the courses your team can assign, track, and report on with CBT Nuggets.
$749
seat / year