Lesson 10 of 15

Acceptance Tests with Cucumber

Duration: 13:41 Watch on YouTube (external link, opens in new tab)

Markdown version

Learn how to use cucumber features to starting doing real Behavior Driven Development (external link, opens in new tab) with your customer. BDD is all about communication, and here we learn the basics of writing the glue between what the customer or product owner writes, and what developers implement.

In this lesson

Roy Osherove describes BDD (external link, opens in new tab) as having real conversations with the customer and introduces Cucumber (external link, opens in new tab), which turns plain-text specifications, such as the drills written for the course, into executable specifications. He installs the gem, adds a feature file, pastes the step definitions that Cucumber suggests into a Ruby steps file, and shows how text in double quotes becomes a block argument and how pending steps are reported. He explains that the steps can attach to any level of the application, from string calculator (external link, opens in new tab) objects to a Sinatra application, while the scenarios stay abstract because more technical scenarios are less maintainable (external link, opens in new tab).

Transcript

1,749 words

[00:04] (external link, opens in new tab) So up until now we've we've done specification based testing but it wasn't really BDD (external link, opens in new tab) behavior driven development because BDD in its core is not about just developers being in a bubble talking to themselves and writing specs for themselves. It's about having real conversations with the customer. So what we're going to look at is one tool that enables having easier conversations with the customer or the product owner. That's a tool called Cucumber (external link, opens in new tab).

[00:36] (external link, opens in new tab) Now the nice thing about tools like Cucumber is that they allow you to write in almost plain text language things that you would like to have in your product just like I did in the drills that you've worked on. So, I actually wrote these drills in the same format that you would use in Cucumber. So, what we're going to do is we're going to see how we can actually make these specifications that I wrote here in the document that you've actually worked on and turn them into executable specifications.

[01:12] (external link, opens in new tab) So, imagine that I was the product owner. I wrote this and now you're taking this and you're putting it to automated use. Okay. And in the process, we'll take a look at the tool called cucumber. So cucumber is a gem. You basically do gem install cucumber. And what I've done already is that I've added a new features

[01:43] (external link, opens in new tab) Directory here. And in the features directory, I'm going to add one's file. And I just named it something whatever is the feature name is and called dot feature. And in there I basically pasted the text as it was. Now it works. You see? No actually still still a bit a bit to go. But this is the first step. What we're going to do is we're going to execute this scenario using cucumber and see what happens.

[02:19] (external link, opens in new tab) If I go to if I just type cucumber here, cucumber automatically detects that there is a features directory. He detects the feature and he tells me, "Look, there's a scenario here part of the feature title and he detects a scenario and he detects the special words when and then and it says look there's a scenario here that you haven't implemented yet." So, it's really undefined

[02:54] (external link, opens in new tab) And it has two substeps that you have to define. And it tells me what I can do to then translate these plain text language steps into Ruby steps and it gives me a piece of text here which I can basically copy. Okay. And what do these actually mean? Let's take a look by pasting them in a special folder called

[03:35] (external link, opens in new tab) In the step definitions, I'm going to add one file. You can call it first feature or we can say called spec say calculator steps. RB that's a regular Ruby file. And in that file, I'm just pasting in what I just got from cucumber. So, let's take a look at that. It basically has these for each step for each line under the scenario.

[04:10] (external link, opens in new tab) We don't need the extra end. And what it does is that it tries to to look for special strings inside the step. And it says, "Look, this is a regular expression. Look for these words in the feature file." And when it encounters these double quotes, it automatically thinks, "Oh, you put a string inside the feature. You might want to change this string later." So let me give you that string as an argument to a block in your Ruby code.

[04:47] (external link, opens in new tab) So it tries to generate a regular expression that captures whatever is inside double quotes here. And then I can have it as an argument. I can rename it to text. And by default the feature is pending. If I just save this and I go back and I run cucumber again, what I get back is a different type of message. It says I have a to-do. I have a pending

[05:17] (external link, opens in new tab) Pending here and a pending there. And then I have something that didn't run. Okay, so it was skipped. Now if I remove the word pending just from this line and I save it and I run that again you can see now that this has become green when the string calculator (external link, opens in new tab) add method is called and the rest is yellow. If I remove that,

[05:50] (external link, opens in new tab) You can see that it says scenario passed with two steps that passed. But that's not good because it hasn't really passed. We're just lying to ourselves. So, we're going to put back the word pending here. But here, we get to do whatever we want in this step. We can use integration testing (external link, opens in new tab) to go using selenium or Capybara to web page scrape the page. We can use we can execute command lines that use nodejs zombiejs to use a web browser scraping.

[06:21] (external link, opens in new tab) We can use Sinatra and Capybara to run things in memory without a web server. And we can literally just execute objects from our application such as creating a calculator. Okay. So if I say here string calculator dot new street calculator two depths new with

[06:53] (external link, opens in new tab) A logger and a web service. I can say add and I just give it text. It says I do need to fake (external link, opens in new tab) the logger. So I might say logger equals and I might put it in a class variable. So I might say logger equals fake slow.

[07:34] (external link, opens in new tab) Let's do the web service web service. Because I have them with the ad sign now I can actually go and say look this is a piece of text. So I can now actually assert that logger should have received

[08:10] (external link, opens in new tab) Right with text. Okay. So it's right now what I'm doing is I'm translating my unit tests into running them through cucumber because the point I want you to see is that you can write whatever you want in those steps. It's up to you to decide which level of the application you're actually attaching to. But the abstraction of pure text belongs to the customer. So you let the customer write things in the in an abstract way.

[08:43] (external link, opens in new tab) You do not have to know anything about the technical features of the application. Okay. So if I if I save it and I try to run it, I'm going to have a lot of dependency issues. I need to do all their requires etc. But you see undefined method fake etc. But it does run the code inside the webs. So now it's just a matter of getting all the code to run correctly. But it's almost like asserting because I can use RSpec matchers, use whatever matching mechanism I want.

[09:16] (external link, opens in new tab) Okay. Now the same thing can go for an application like Sinatra applications. So if I do and I go back refresh that show you a bit more of a complete demo. If I have a this is more of the feature that I planned.

[09:49] (external link, opens in new tab) So I have string called steps here. This is what it would look like. I might fake the logger, fake the calculator, call add. But I can also do the same with the Sinatra application. So I can say using Sinatra with Capybara. In order to easily test our web app, we will use Capybara. But that's not something that the customer would write. This is just a demo. The customer might say feature having a main page and then scenario main page.

[10:20] (external link, opens in new tab) When I go to the main page, notice that the customer doesn't care what is the URL of the main page. I could have specified it here, but I don't want the scenarios to be very very technical. I want them to be abstractions. The more technical the scenarios are, the less maintainable (external link, opens in new tab) they become. Okay. So, when I go to the main page is better than when I go to this URL and I should see the default greeting is better than I should see this exact text. because the default greeting is something that might change a long time.

[10:54] (external link, opens in new tab) Okay. And then I just put more steps here. When I go to the main page, I would use a gem called Capybara and say just visit this. And if I wanted to check the default reading, I would say page.sh should have content and I would just look at this default reading. Now to enable things like Sinatra I would have an extra directory called support and in there I would have an n.rb RB

[11:26] (external link, opens in new tab) Where we do all the requires and then there is a world do and in the world do this is part of the cucumber thing and Capybara as well is that I would configure Capybara to use my SAP application so it doesn't have to run a web server or anything like that but I could just as well have connected to a Rails application to a command line application to anything as long as I can automate it. I can do whatever I want through the cucumber scenarios.

[12:01] (external link, opens in new tab) For example, in cucumber, I might say I'm not going to use RSpec at all. I might just use objects and say this object I call it and then I this object has that the database is has that state. And then it would fail and then to make it pass I would have a lot of specs subspecs going until finally that feature passed. Okay. So what I want you to do now is to literally copy the

[12:31] (external link, opens in new tab) Create a feature page from the first feature with two scenarios that we have and I want you to implement them through cucumber. Okay, you can I want you to prove that they work for me as a customer instead of just a technical person. Okay, questions. >> The relationship between when

[13:04] (external link, opens in new tab) >> Yeah. When is the range and then is >> there has to be. Yeah. But you don't have to do a given and you don't have to do end. You don't have to do any of them really, right? But you usually need them at least because they're they're the thing that you would need to to say something about the application, about the state of the world. >> Other questions? >> You start from that like the first >> Yeah, you start from the first one. >> Yeah. >> Well, you can just add features directory to the current directory you're working on.

[13:37] (external link, opens in new tab) >> Whatever you want. >> Okay, good luck.