Ruby on Rails: Test-First Workflow | Cezar Halmagean | Skillshare

Ruby on Rails: Test-First Workflow

Cezar Halmagean, Software Development Consultant

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
7 Lessons (43m)
    • 1. Introduction

      0:57
    • 2. Project Setup

      8:15
    • 3. What You Will Learn

      6:31
    • 4. First Feature: Create a New Post

      13:58
    • 5. Second Feature: Create a Post with No Title

      7:15
    • 6. Third Feature: Review Post

      6:05
    • 7. Conclusion

      0:21

About This Class

The class focuses on teaching you the workflow used in building Ruby on Rails applications, test-first. This approach is also known as Behavior Driven Development (BDD), and it is (in my opinion) essential in building high-quality Ruby on Rails applications.

I go through the thinking and implementation process of building features into a Rails application. Starting with the business goals described as stories, and then diving into the actual implementation using the test-first workflow.

My goal is to teach you the basics of the test-first approach so that you can use it with your own projects.

The class assumes you already have some experience in working with Ruby on Rails. It doesn't take you through the absolute basics, but it does focus on the basics of the test-first workflow.

To follow up with the material, you need to have a computer already configured to run the latest version of Ruby.

Transcripts

1. Introduction : hi and welcome to how the build ruby on rails applications test first might Amy Caesar and I'll be your instructor. This class is for you if you do have some experience with rails, as it doesn't focus on the absolute basics. It does, however, focus on the basics of the test. First workflow. I've been working with Ruby on rails for over a decade, and in this course I'm going to show you one of the most effective ways are found for building and growing ruby on rails applications. And that is by writing your tests first. My goal here is to teach you how to think about the bigger picture before you write your code and how to write killed. It's easier to refract there later on. By the end of this course, you should feel comfortable writing every new feature you're going to build with the test. I hope you enjoy any for have any questions? Feel free to reach out to me. Let's get started 2. Project Setup: Okay, So the first thing you need to do is figure out the version of Rubio have installed on the way you do that. Use our VAM list. That's if you're using our VM. If you're using something else than you need to figure that out for yourself, RV, um, list will show you all the versions that you have installed. In my case, the latest one is 2.5 point three. And if you don't have it, you can use or vehemence stone and specify the version number. And then with our VM use, you can specify the version of Ruby Want and then Anat sign and then the name of the gem set with the dash dash, create flag. This command will create the jump set if it doesn't exist. And now weaken Stone. All the johns we need for this project because we're in a new gym said so everything is nice and clean. So once all the gems air installed, we can now go ahead and create a new app only in this new app sculpture. And I always like to skip the default testing because it creates test unit files and I prefer to use our spect, so I'll go ahead and at the Skip test flag. And I also like to skip the bungalow and use the past crass database. Another thing I like to do is to copy the database Yemen file to an example file, and that way I can then added to the get ignore file, and it will not be picked up by get. It's a way to make sure that no one else on the team can see your credentials or your database config. Foul is just something I picked up over the years, and I like to do it that way. So as you've seen, when I created a project, I skipped Bundle. And that's because I like Teoh, configure it project before I install the gems. But now we're in a good place, and I think it's a good point to run bundle install Andi. Once that's done, we have on the gems ready to go, and because all the gyms are installed now, the last thing we have to do to start the project is to migrate the database. And of course, the way you do that is to run rails, DB create and rails db migrate. So once I have my database is created. It's a good time to add everything to get and commit as initial commit this way I Congar oh , back to dis commit. If I want Teoh start again. Clean. Next up is to add the gym for respect that is called our spec rails. And the latest version is 3.7 at the time of this recording. So I'm gonna add a gym to the development group and then I'm gonna run bundle install. Next, I'm going to create the R spec installed files. This is going to create a few files for our specter run properly. So now, in order to install cucumber opened Jim final again and go to the bottom of a foul where I create a different group and this time is gonna be a group for test and I'm gonna add the two Kimber rails, gem and database cleaner Jam does to come together, so it's good idea to add them both. The only thing left to do right now, after you've added those gems here, Jim Far, is to run bundle install that way on the gyms are up to date and Now we can generate the cucumbers cellphone, which will make sure that your cucumber command runs properly on. Do all your tests are also running. One final step I like to do is to create a very minimal test to just to make sure that everything is working correctly. So what I'm gonna do is create a feature test called homepage, which tests that the homepages loading and the user can see the welcome message. So, as you can see, the future name is home page. And the scenario is, I see a welcome message. The two steps I need is going to the home page and then making sure that there's a welcome message there. So something nice about cucumber is once you've written your future file, if you run the tests, it will give you the steps you need so you can just copy paste them into your steps file. So, as you see here, those two steps are pending, and it tells me that they should look like that and they just select them here, go and create a new steps file, and then I can just paste them there. So the first step is to visit the home pitch and going toe slash route, which is the home page. And the second step is to make sure that the page has the content. Welcome. That's how I define my welcome message right now. That could change in the future. But it works for now. But the most important thing I want you to get out of this. Is that from this point on, all I do is run the cucumber command and see what the next step is. That this will. This process will drive my development going forward. So, for example, right now are missing a route. Cucumbers doesn't know what that slash means. So it doesn't know what the root travels this. So by knowing that I can go to their routes foul Adler out and around the cucumber command again. So this process is very nice because you can proceed, were with your development step by step. And every time you just build a tiny new step and you move forward. So, for example, right now it tells me I'm missing a side control. And so I go ahead, create a new file, create the class, save it, and then run the cucumber command again, and I know that the next error I'm getting is the one step I need to implement next. So that way, I don't have to keep everything in mind. I just focus on the current task or the current small step. Like, for example, this one on missing an index action because I didn't created when I created the class for the site control. And that was intentional because I only want to satisfy the current failure message. So to get the next failure message, I'm going to run the cucumber command again. And this time it says, I'm missing the index assembly. That's easy to fix. I just create a new directory for the site controller to store the view files there, and I'm also going to create a index template which will just have the content. Welcome. Once I do that, I can run the cucumber command again and hope for the next failure message. Only this time I don't get a fader, I get success. So right now I know that my feature is done and I'm ready to ship it. But this was just an example. It's just to make sure that the test are running properly, so the next thing you might want to do is drill down and create a request speck. That's useful when you want to test something that the user doesn't see. So, for example, right now I'm testing that view is rendering properly, and that's something that it's probably a technical detail like, for example, when you create a record to the database, that's not something that the user sees in the their face. But you may want to test that as a developer. So a request speck is a kind of integration spec that will help you with the things that user doesn't see. And the last thing is to run the rail server on Look at the Home Page, which says Welcome. 3. What You Will Learn: Here is a summary of what I will touch upon in this course. You will learn about roles and stories and why they matter in the context. Off test. First, we'll look at how to do story mapping and how these story maps will be the single source of truth for your entire application. Then we'll move on to talk a little bit about the testing wheel, which describes how you should build your test suit from outside in and lastly, will spend the majority of this course learning how to write feature tests. Now let's start with the first topic. The 1st 1 is defining roles and stories. Why would you want to go to all this trouble when you could actually jump in and write code ? Right? Well, the thing is, if you're a solo developer doing your own thing, you can pretty much get away with anything upto a point. But when your app gets big enough or you need to work in a team setting or when you work with a client, things you're going to learn here are going to help you. So let's imagine you're a part of a team that consists of a stakeholder, which could be a business analyst or client or your boss, a developer. That's you. And let's also throw in a key way. Okay, so we've got a small team of three people that need to talk to each other to be able to deliver a solid product. But before the discussions begin, you need to agree on a common language, and this could be the topic for an entire course. But we'll keep it simple. And to find just the roles, the roles would be the different types of users that are using your app. So, for example, in a common SAS application, you might have a guest, a user, remember, on admin and so on. So defining the roles at the beginning helps all three of you understand who you are talking about. When you describe the way someone interacts with your application, the way someone interacts with your application is called a user story. So basically what it comes down to is your in terror application will be described from the user's perspective, and those descriptions will be written down in the form of a user story. And here's a quick example off what a user story might look like it says, Given I am on the home page, then I should see a welcome message. So as you can see, a story is not complicated at all. It describes a user interaction from start to finish in a way that anyone could understand it. Even nontechnical people like your client or your boss. And that's actually the point. You want all your team members, not just developers to agree on written their own contract, so to speak. You want to set the requirements in stone or, in this case, in a user story such that they will be available later on when someone forgets he or she wanted a particular behavior. But let's take a look at how you come up with those stories. A story mapping section is usually a meeting in which all the members of the team are required to participate, and the first and the most important goal off the story mapping meeting is for everyone involved in building the product to understand why they are building it and how it will help the user or the business. This is very important. You don't want to know how much time is spent on building the wrong thing because someone didn't quite understood the goals of the project. So a story mapping session looks like the following. On the top line, you have the goals. That's what the user wants to achieve. Here you see a goal that says Create Post. So that means the goal of the user is to create a post. What else? Well, let's see. Another goal could be review posts, and another could be published post. Okay, so now that we have a few goals as examples, we can move on to break those goals down into actions. So in action is what the user has to do to get to his goal. So, for example, for the create post Go, the user will have to write the post and save it. That's what the team decides the user needs to do. In order to accomplish the goal and for review. Post the actions could be inspect, post and collaborate with other reviewers, and Mark Post has reviewed. And for the last goal, the action could be scheduled post to publish later and distribute on social media, for example. So these are a few example actions that the user might do in order to accomplish his goals . Now let's dig even deeper. Let's talk about everything that comes to mind for each action. For example, for the right post action to be implemented, a new post would need to be created in the database. Then, for saving it, you could make sure that the title has the right length and for inspecting the post, you would need to display the Post details. So while talking with the team about thes goals and actions, many more ideas will be added to the board. At this point, it's a good idea to dump everything in their let everything out. And once that's done, a project manager or stakeholder could come in and prioritize all those features. So, for example, with side to do the first three for the first version of our product. So now that we have our stories mapped out, let's look at how they fit into our workflow. This workflow is what I call the testing wheel. So from a development perspective, we've got three types of tests. We've got feature tests which map 1 to 1 with the user stories, and we will spend the majority of the course talking about them. Some people call these U. Y tests, but that's not important. What is important is to make sure that your only testing what the user can see nothing else and then digging deeper. There are requests specs. These tests are also testing integration, but they do it at the back and level, so to speak. You want these tests to complement future tests, but just for the things that the user does not see. For example, if you create a post a request, US might need to make sure that the record was safe to the database. You might want to have a test for that. But it's not something that the user can see. Something that happens on the back end and then digging even deeper. You've got unit tests, and these are the kind of tests that were covered to death in other courses. So I'm not gonna focus too much on these 4. First Feature: Create a New Post: Now what I like to do after each new feature is created commit with all the files. And that way I know I have a stable point. If I want to revert back to that commit because everything is working now and all the tests are passing, this is a good point to create a commit, and I'll do so right now. Okay, so once that's done, let's look at the features directory. We have the home peach feature done, and we're going to create a new one. This time it's gonna be about creating a new post. So I'm gonna create a new foul in the features rectory named Create Post That Feature. And inside of that file, I'll add feature create Post. This is the name of the future. And then I'll also add some description for this feature. The Description section is not run by cucumber. It's just there to give you some context about why you're building this feature. The feature description has three parts to it. The 1st 1 is the goal you want to achieve. 2nd 1 is the user role, and the 3rd 1 is how you're going to do it. So in this example, I've said, in order to add more content to the site as a user, want to be able to create a post. So the goal is to and content to the site, and the role is a user. And that's different from a visitor or a guest, because the user is someone who's registered on the site. So his a member, you could call that a member for this example. I've called it a user, and the third step here is I want to be able to create a post that some how I'm going to create the content. Okay, so for that feature to the implemented, I need some acceptance criteria, something that will tell me that this feature is complete. And for that I'm going to write the scenario, which says I create a new post. So I'm the user. I'm creating the post. That's what I'm gonna call the scenario. And so for that scenario, toe work, I also need at least three steps. 1st 1 is the context given on on the home page. That's enough for my current feature. I don't need anything else when I create a new post. That's the action I want to perform, then the post should be ready for review. That's all any. Those are the three steps I need for this scenario to pass. Now that we have our feature that find we're gonna do the same thing as we did with the previous test, we're gonna run cucumber, and it will give us the steps we need because we haven't implemented them yet. We're going to copy those steps, and we're gonna paste them into a new steps file. Then, after we've basted the steps there, we can define each step to do whatever we want. Okay, So for the first step for creating a new post, it's just about filling a form and submitting it. That's easy to do with Cappie. Borrow helpers. You just click buttons feeling forms, and you're done. So before you start creating steps, it's usually a good idea to think about the user interface and the user experience. So, for example, in this case for creating a new post, you want the user to click a link which will take him to ah, create post page and then fill in the title, filling the body and click a submit button that's all you need to do. It's easy to create a post, so that's gonna be enough for this example. On second step, what you want is to check that the title and the body show up on the page. That's because after you click the submit button, you're gonna be redirected to the Post Details page. One more thing you might want to add here is that the String Review post shows up on the page. That's because you might wanna have a button that says Review Post or a Link or just a new indication for the user to review this post. And now that we have our tests written, it's time to implement the coat. And the way we do that is run a cucumber, commend to see what the next error messages and implement enough code to make that error pass. So in this example, the create post link is missing. So what you do is just at a new link on the page that has that I d in it, and that should make this test pass, and then once this one is passing, we can focus on the next one and saw, so I'm gonna add a create post link with the specified I D. And they'll run the cucumber command again. So I got my failing tests. But this time I got to failing tests. And that's because the previous one uses the same page to receive that welcome message shows up, and it's failing because there are new routes named New Post. So we got two failures, but that's okay. We're gonna have a new route that should make both tests best or a T least. That's what I hope. And so but running the cucumber command again, I can see that the previous error is gone, but I now have a different one. I'm missing the posts controller, so I will just go ahead and create the file. Create the class so I can make that test happy and run the cucumber command again. And now, the air message says, missing the new action that's easy to fix. I go ahead and open the post control or file at the new action and run the cucumber command again, and I get a new error. I'm missing the template for my new action so I can fix that by creating a directory for the post controller to store its template files and create a template file for the new action. And now, if I run the cucumber tests again, I get a message about missing the post title field. And that's because I don't have a form yet and I'll go ahead and create one. It's not gonna be anything fancy is just a standard rails form, but it's enough to make that test pass. So the purpose here is to have the least amount of code that makes the test pass. And I'm good with that. I can add styling and whatever else I need later, as soon as my tests are passing. I know that the feature is done, and the easier can use the app, even if it doesn't look that great yet. So I'll run the cucumber command again. And now that I have a form, I'm getting a different error because the object that I'm using for my form is no. So to make that pass, I'll open the controller again and create that object to have something meaningful, meaningful in it. I'll create a simple new object that's enough to make my tests pass and right Now it's complaining that it doesn't know what post ISS because I haven't created the Post model yet , so I'm going to go ahead and create a new model cold posts. I'm gonna migrate my database and run my tests again. And now the error says, I'm missing a wrote for my posts form, and that's easy to fix A just at the create keywords in my routes file, and that should generate the correct route. But running the cucumber command, I see the same error message. It's missing the posts path. And so I'm checking my routes to see if anything is wrong here, and I don't see any posts path. It's because the resource I'm using in my route file is called post instead of posts so I can change that and around the cucumber command again. And now the previous routes that I've been using or the path helpers are wrong, So that's what the test tells me. So that's easy to fix. I go back, I change the views where I've used the previous helpers. I make sure that instead of new posts, I write new posts and run the cucumber command again, and now I get there or that I was hoping for. It's missing the submit button so I can have the submit button and make that test pass. But what's important to notice here is that everything was driven by my tests. So when I never occurs that I was not expecting, I can rely on the test that I've written to show me where that error is, so I can go back and fix it. Okay, so I've added the button to my form, and now I can run the cucumber commend again to see the next step, and the next step is about the create action in my controller, which is missing because I didn't write it yet. So I write the tree it action and around the Cucumber command again. Now the second step is passing, and the 3rd 1 is failing. But the difference now is that this failure message doesn't tell you that much. It's a little bit cryptic. I know that. What? I saw it. I was like, What? What's what's going on? It doesn't tell me what I need to do next. That just tells me that it cannot find some expat. So whenever you have a narrow like that and you don't know what to do. You just do something, anything, anything that will change the error message. So in this case, redirecting to my home page just to see that I get a different error message, and maybe that's going to provide a clue with about what's going on. And it does. It tells me that it cannot find the expected texts on my home page on That tells me that the create action is trying to render something, but because it doesn't have a template file, it cannot render anything. So what I'm going to do next is try to render the show template because it doesn't make sense for me to create a template file for my create action. And so I will redirect the user to the show page and while need to create that page because I don't have it right now and as usual, I'm going to start by running cucumber and see what her I get, and it tells me that there is a problem with the routes. That's because I don't have the show keyword in there. And so I'll add that and run cucumber again and while I'm at it, I'll change the view, help her to new posts instead of new post. And it looks like there is still there. And I know I'm using post path in my control. Or so that's using the singular. I'm going to change that to posts and see what happens. So cool. Now get the different there this time is complaining that it's missing the show action. So I'm gonna get into my controller and add that new action there. And this time I'm getting the missing ex Path message, and that's because it's got nothing to render. So I'm going to open the view file and add something there just to see the error change. And I can see that the error is different now, which means I need to add the right content in my template. So I'll go ahead and at the title and the body of the post to my template and run the cucumber command again. And because my posts object is now, it cannot find a title attribute on the no object. So I'm going to go to the controller action and find Anak actual post that I can render in my view, but interestingly, it cannot see the I d in the prams. So I'm not sure why that happens. Gonna go ahead and open dialogue files and see what's there. And when I opened the log files, what I can see is that the post path has a dot in it instead of a slash. And so that tells me there is a problem with the routes and I'm gonna open the routes and try to fix whatever is in there. Hopefully, this time I'm gonna get it right. And by running rail the rabbits. I can see that my routes are looking OK now. But now with the new routes, I know I've used the wrong route in my controller. So I'll open that file and make a change. Okay? And by running cucumber, I see that I've used the wrong route, help her and my view template. So I don't need to make a change there. Also, that's perfect. Now I know that the body and the title are in the template because that's what the error tells me. And I'm just missing the review post message, so I'll open the template file and add it in there just a simple text and then run the cucumber command again. And this is it. This feature is now complete. 5. Second Feature: Create a Post with No Title: Okay, so now that my feature is complete and all my tests are passing, it's a good time to add everything to get so that I can have a stable point if I ever want to go back. And this also communicates to other developers that this is another step in the history of the project. And now that my future is complete and the code is committed to get, I can go ahead and start a new feature, and this time it's gonna be about adding some validation errors. It's one of those easy to spot edge cases where the user does something you didn't expect so that we would do. It is your first at your happy path, which we did with the first test, and then you continue on and add edge cases to your tests. You don't want to go overboard with edge cases at this level just because tests at the U. Y level are really slow and you want to keep those edge cases as much as possible in your unit tests. Okay, so let's see what we have here were saying that if the user creates a post without a title , then he should see a validation error. So now that the test is written, we can continue with running cucumber and see what we get. And, of course, we get two missing steps and we can easily copy those and paste them into the steps file. So that's what I'm gonna do. I'm gonna add to my previous steps, file those two new ones and define what they mean. So for the first step, where I create a post with no title, I can pretty much copy the content from my previous step, which says I create a new post except for the filled title line, because we don't want to do that. And then for my second step, where I should see a validation, er it's just about having some content on the page and in this case, the missing title error. Okay, so now that the steps are defined, we can run cucumber again and see what we get. And what we get is what we actually expect to get a nearer about missing that validation. Err on the page. That's because we haven't implemented that yet, but this is a good error to have because it guides you True development to the implementation face. So now that the test is there to watch our back to make sure we are not building something we don't want, we can think about ways we could do the implementation. So one way we could do that is to instead of creating the post, we could make a new object and then have a condition. If the object is saved, then we do one thing, and if it doesn't save, then it means it's got some validation errors and we should display the page again. And those validation er's. And that means the form needs to have some kind of era rendering for the objects. So if the errors are present in the object, we need to show them to the user, and that's what I'm going to do now. I'm gonna add a section above the form that renders any errors present in the object. This is a copy and paste from a different project, so I'm just going to remove the more cup that it's not needed for this case and back to running cucumber again. And this time I'm getting two errors, and if you remember, I change something in the controller, and that's why I see those errors now. So the safe thing Teoh do right now is to go back to the controller and undo everything I've changed until my previous test passes. I'm not sure if you remember about what I had in my action was just a line with the post create and a render line. So that's what I'm gonna go back to and run cucumber again and see what I get. So, running cucumber, I see that my previous testes passing and now my second test skips me honor. And this is where I want to be. I want my entire implementation to be driven by tests as much as possible. So at this point, I know that I don't have any errors to display, and that's because I have no validation errors on my model, and that's what I'm gonna do next. I'm going to implement validations on my model. And for that I'll first create a unit test for my model and drive my model implementation with those unit tests. As you can see, I'm diving into tests. I'm going deeper than the high level U I tests, and as you can see, I prefer to use the shoot a way of writing validation tests on for that to work. I need to go ahead and install the shooter gym and configure our spec to use it. All right, now that I've installed the gym, I can run my tests again using our spec. And the error I get is the one I was expecting to get is the validation is not present on my model. And so I'll go ahead and implement that In this case, the implementation code is really simple because it's provided by rails. And all I need to do is just add the validation line and I'm done and my test is also passing. So I can now run the high level tests with cucumber and see what's happening. And I know that my model now does validations and my view does not. So it must be something at the view level, right? It's either view or controller. So I've narrowed it down to that area. So the first thing I'm gonna do is try to separate what create does into two different lines. So first I'm gonna create a new object, and then I'm going to try to save it and then run the test again to see if anything else is broken and running. The test doesn't give me anything different. It gives me the same error that I had previously, and that's okay. I can now go ahead into the controller and do some changes. Some behavior changes and they mainly I will render a different template. If the validations fail, I'll render the new action when the validations fail and I'll keep the show action for when the validations are passing. Running the Cucumber Command now tells me that all my tests are passing on. That's what I was expecting. I mean, all I did was to verify that. I do see that validation error on the page, and so this is a good point to wrap everything up and commit to get 6. Third Feature: Review Post: The last feature on our list is to view the Post details. So let's create a new future file and described what this new feature should look like. The name of the future. It's gonna be review post. And in the description we're gonna say in order to make sure that The Post is ready for publishing as a user, I want to be able to see the post before I publish it. As for the first scenario, we could name it. I inspect the Post because that's what the user does. So that would say, given I have already created a post, that's the context and the action would be when I go to the Post Details page, then I should see the post title and body. Of course, we've covered this already. Just in case you want to change the behavior of the of the create action. This test will cover the details page, so it's good to have it. So, as you probably got used to about by now, we're going to run the cucumber Command again and see what steps were missing. We're going to copy those steps, based them into a SEPs file, and then define each step in turn. So for the first step where I say I have already created a post, I'm going to reuse the previous steps from creating a new post. But I'm going to copy those actions the actions that the user does and move them into a helper file. So helper files are very useful to isolate common steps. So instead of adding the same actions in each step, you can create one of those helper files to hold those common steps in one place. You don't want to go overboard with this because it tends to complicate things, and it makes tests hard to understand. But if you can name the helper methods and suggest what they do, I think that's a good way to re factor some of the tests. And one thing I want to point out is that with testing, you don't want to be too clever and make your tests look like code because you want to easily understand what they do. So instead of trying to be too dry like you would in a rails up or rubia, you want to keep your tests, Moreover, boasts, even if you duplicated things so that's OK. So what I'm doing here is I first defined the helper method in a R spec. Fuller and cucumber doesn't see that. So I need to move it in the Cucumber Support folder and edited to Cucumbers World as they call it. So once I do that, I should be fine. Except I forgot that it needs a module instead of a class. So I'll change that and around the Cucumber Command again. Okay, so my test is telling me that the first step is done and the next step to be define is going to the details page, and that's very easy to do. All I have to do is click the name of the posts, and it should take me to the right page. So instead of relying on the actual text in a title, I prefer to use a class name or an I D to find the elements on the page and interact with them. So in this case, I'm going to use the class name and I'll find the first class and quick it so back to running cucumber again. I want to see what the next error is, and it tells me it cannot find that class name that I specified. And that's because I'm not displaying my posts on the page yet. So what I need to do is open up my index template and make sure I'm rendering all my posts in there. So I will add an HTML table and for each post in my database, I will at a link that goes to that posts page. And one more thing I want to add here is that if there are no posts than the table should not be rendered. Okay, so now that my template looks better, I want to run the cucumber command again and see what the errors tell May. And it looks like my errors tell me the same thing. They cannot find that class name. And of course, that's because I don't have a cost name yet, so I'm gonna go ahead and add that class name to my link just to make sure what the class name is. I'm gonna open the test file and copy the name from there. Okay, So running the cucumber command again, I still see their error. And now I remember that my index action doesn't match. Oh, my posts on DSO the posts object is empty and that's why it doesn't render the table. So now that I've added that and ran cucumber again, I see the error has changed. It now tells me that it cannot find a title. And if I opened posts control or that renders the details page, I can see that it doesn't fetch the post by a D. So I'm gonna have to add that to my action and then run the test again. So running the tests now shows me that the second step is now passing. So all I have to do is define my last step. So I'm gonna open the steps file and for last step, I'm gonna create an expectation that the page should have the title and the body. And if I run a cucumber command again, I see that all my tests are now passing. So my feature is complete and ready to be committed to get, and that's what I'm going to do next. 7. Conclusion: Well, this is the end of the course, but don't go away just yet. If you feel like you're like a challenge and dive deeper into this approach, feel free to pick a few more stories from the board and try to implement them yourself. If you ever feel stuck or need any help, feel free to reach out to me or share your work with the community. Good luck.