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

Ruby on Rails: Test-First Workflow

Cezar Halmagean, Software Development Consultant

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
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

67

Students

--

Projects

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.

Meet Your Teacher

Teacher Profile Image

Cezar Halmagean

Software Development Consultant

Teacher

I help Ruby on Rails teams ship high-quality code faster

See full profile

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Your creative journey starts here.

  • Unlimited access to every class
  • Supportive online creative community
  • Learn offline with Skillshare’s app

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

phone

Transcripts

1. Introduction : Hi, and welcome to how to build Ruby on Rails Applications Test-First. My name is Cesar 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 have 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 code that's easier to reflect later on. By the end of this course, you should feel comfortable writing every new feature you are going to build with a test. I hope you enjoy and if you have any questions, feel free to reach out to me. Let's get started. 2. Project Setup: The first thing you need to do is figure out the version of Ruby you have installed and the way you do that, you use RVM list. That's if you're using RVM, if you're using something else, then you need to figure that out for yourself. RVM list will show you all versions that you have installed. In my case, the latest one is 2.5.3 and if you don't have it, you can use RVM install and specify the version number. Then with RVM use, you can specify the version of Ruby you want, and then an at sign, and then the name of the gem set with a dash, dash create flag. This command will create the jump set if it doesn't exist. Now we can install all the gems we need for this project because we're in a new gem set, so everything is nice and clean. Once all the gems are installed, we can now go ahead and create a new app, only, this new app skill share. I always like to skip the default testing because it creates Test Unit files and I prefer to use RSpec. I'll go ahead and add the skip test flag. I also like to skip the bundle and use the Postgres database. Another thing I like to do is to copy the database YAML file to an example file. That way I can then add it to the get ignored file and it will not be picked up by good. It's a way to make sure that no one else on the team can see your credentials or your database config file is just something I've picked up over the years and I like to do it that way. As you've seen when I created a project, I skipped bundle. That's because I like to configure the 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. Once that's done, we have all the gems ready to go. Because all the gems are installed now, the last thing we have to do to start the project is to migrate the database. Of course, the way you do that is to run rails DB create and rails DB migrate. Once I have my database created, it's a good time to add everything to get and commit as initial commit. This way I can go back to this commit if I want to start again clean. Next step is to add the gem for RSpec, that is called Rspec rails and the latest version is 3.7 at the time of this recording. I am going to add a gem to the development group and then I'm going to run bundle install. Next I'm going to create the RSpec install files. This is going to create a few files for our spectral run properly. Now in order to install cucumber, opened gem file again and go to the bottom of the file where I created different group and this time is going to be a group for test. I'm going to add the cucumber rails gem and the database cleaner gem. Those two come together, so it's a good idea to add them both. The only thing left to do right now after you've added those jumps to your gem file is to run bundle install their way, all the gems are up to date and now we can generate the cucumber is cellphones, which will make sure that your cucumber command runs properly and all your tests are also running. One final step I like to do is to create a very minimal test tool, just to make sure that everything is working correctly. What I'm going to do is create a feature test called homepage, which tests that the homepage is loading and the user can see the welcome message. As you can see, the feature name is Homepage and the scenario is, I see a welcome message and the two steps I need is going to the homepage and then making sure that there is a welcome message there. Something nice about cucumber is once you've written your feature file, if you run the test, it will give you the steps you need so you can just copy paste them into your steps file. As you see here, those two steps are pending and it tells me that they should look like that. Then I'll just select them here, go and create a new steps file and then I can just paste them there. The first step is to visit the homepage and going to slash route, which is the homepage. 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. This process will drive my development going forward. For example, right now I'm missing a route, cucumber doesn't know what that slash means, so it doesn't know what the root route is. By knowing that I can go to their routes file at the route and around the cucumber command again. This process is very nice because you can proceed with your development step-by-step and every time you just build a tiny new step and you move forward. For example, right now it tells me I'm missing a site control. I go ahead create a new file, create the class, save it, and then run the cucumber command again. I know that the next error I am getting is the one step I need to implement next. 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, I'm missing an index action because I didn't create it when I created the class for the site controller. That was intentional because I only want to satisfy the current failure message. 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 template. That's easy to fix. I just create a new directory for the site control to store the view files there. 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 failure, I get success. 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 tests are running properly. The next thing you might want to do is drill down and create a request spec that's useful when you want to test something that the user doesn't see. For example, right now I'm testing that the 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 their phrase, but you may want to test that as a developer. A request spec is a integrations spec that will help you with the things that the user doesn't see. The last thing is to run the rail server and look at the homepage which says welcome. 3. What You Will Learn: Here is the summary of what I will touch upon in this course. You will learn about roles in stories and why they matter in the context of 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 the outside in. Lastly, we'll spend the majority of this course learning how to write feature tests. Now let's start with the first topic. The first one is defining roles and stories. Why would you want to go through all this trouble when you could actually jump in and write codes. Well, the thing is if you're a solo developer doing your own thing, you can pretty much get away with anything up to 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, the things you're going to learn here are going to help you. Let's imagine you're a part of a team that consists of a stakeholder, which could be a business analyst or a client or your boss, a developer, that's you. And let's also throw in a QA. 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. This could be the topic for an entire course, but we'll keep it simple and define just the roles. The roles would be the different types of users that are using your app. For example, in a common SAS application, you might have a guest, a user, or a member, an admin and so on. 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 our application is called a user story. Basically what it comes down to is your entire application will be described from the user's perspective and those descriptions will be written down in the form of a user story. Here's a quick example of what a user story might look like. It says, given I'm on the homepage, then I should see a welcome message. As you can see, a story is not complicated at all. It describes the user interaction from start to finish in a way that anyone could understand it. Even non technical 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 down contracts, 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. Let's take a look at how you come up with those stories. A story mapping session is usually a meeting in which all the members of the team are required to participate. First and most important goal of 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 understand the goals of the project. 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. 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 publish post. Now that we have a few goals as examples, we can move on to break those goals down into actions. An action is what the user has to do to get to his goal. For example, for the create post goal, 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, collaborate with other reviewers and mark posts as reviewed. For the last goal, the action could be scheduled post to publish it later and distribute on social media, for example. 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. For inspecting the post, you would need to display the post details. While talking with the team about these goals and actions, many more ideas will be added to the board. At this point, it's a good idea to dump everything in there, let everything out. Once that's done, a project manager or stakeholder could come in and prioritize all those features. For example, we decide to do the first three for the first version of our product. 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. From a development perspective, we've got three types of tests. We've got feature tests which map one-to-one with the user stories. We will spend the majority of the course talking about them. Some people call these UI tests, but that's not important. What is important is to make sure that you're only testing what the user can see, nothing else, and then dig in deeper, there are request specs. These tests are also testing integration, but they do it at the back end level, so to speak. You want these tests to complement feature tests, but just for the things that the user does not see. For example, if you create a post, a request test might need to make sure that the record was saved 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 dig in even deeper. You've got unit tests. These are the tests that were covered to depth in other courses. I'm not going to focus too much on these. 4. First Feature: Create a New Post: Now what I like to do after each new feature is create a 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. Once that's done, let's look at the features directory. We have the homepage feature done, and we're going to create a new one. This time it's going to be about creating a new post. So I'm going to create a new file in the features directory, named create_post.feature, and inside of that file, I'll add feature create post. This is the name of the feature. 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 first one is the goal you want to achieve. The second one is the user role, and the third one is how you're going to do it. So in this example, I've said in order to add more content to decide as a user wants to be able to create a post. So the goal is to add 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 he's a member. You could call that a member. For this example, I've called it a user. The third step here is I want to be able to create a post because that's how I'm going to create the content. For that feature to be implemented, I need some acceptance criteria, something that will tell me that this feature is complete. 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 posts, that's what I'm going to call the scenario. So for that scenario to work, I also need at least three steps. First one is the context. Given I'm on the homepage, 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 posts should be ready for review, that's all I need. Those are the three steps I need for this scenario to pass. Now that we have our feature defined, we're going to do the same thing as we did with the previous test. We're going to 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 going to paste them into a new steps file. Then after we've pasted the steps there, we can define each step to do whatever we want. 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 the capybara helpers. You just click buttons, fill in forums 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 a create post page, and then fill in the title, fill in the body, and click a submit button. That's all you need to do. It's easier to create a post, so that's going to be enough for this example. The 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 going to 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 want to have a button that says review post or a link, or just an indication for the user to review this post and now that we have our tests written, it's time to implement the code and the way we do that is run a cucumber command to see what the next error of 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 add a new link on the page that has that ID in it and that should make this test pass. Then once this one is passing, we can focus on the next one and so on. So I'm going to add a create post link with the specified ID and now run the cucumber command again. So I got my failing tests, but this time I got two failing tests, and that's because the previous one uses the same page to see if 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 going to add a new route that should make both tests pass, or at least that's what I hope. So by 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. Now the error message says, missing the new action, that's easier to fix. I go ahead and open the Post Controller file, add the new action and run the cucumber command again. 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. 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 going to be anything fancy is just a standard rails form, but it's enough to make that test pass. 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 and noted the feature is done and the user 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 nil. So to make that pass, I'll open the controller again and create that object to have something 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 is because I haven't created the post model yet. So I'm going to go ahead and create a new model called post. I'm going to migrate my betabase and run my tests again. Now the error says I'm missing a route for my posts form and that's easy to fix, adjust, add 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 post path. So 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 run the cucumber command again. Now the previous routes that I've been using or the path helpers are wrong, 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 post, I write new posts and run the cucumber command again. Now I get there for our data i was hoping for. It's missing the submit button. So I can add a submit button and make that test pass. But what's important to notice here is that everything was driven by my tests. So when an error occurs that I was not expecting, I can rely on the tests 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 command again to see the next step. 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 create action and run the cucumber command again. Now the second step is passing and the third one 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 when I saw it, I was like, what's going on? It doesn't tell me what I need to do next, it just tells me that it cannot find some X Path. So whenever you have an arrow like that and you don't know what to do, you just do something, anything that will change the error message. So in this case, redirecting to my homepage just to see that I get a different error message and maybe that's going to provide a clue about what's going on and it does. It tells me that it cannot find the expected text on my homepage, and 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, cause it doesn't make sense for me to create a template file for my create action. So I will redirect the user to the show page and I'll need to create that page because I don't have it read now. As usual, I'm going to start by running Cucumber and see what error I get, and it tells me that there's 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. While I'm at it, I'll change the view helper to new posts instead of new post. It looks like the error is still there and I know I'm using post path in my controller, so that's using the singular. I'm going to change that to posts and see what happens. Cool, now i get the different error. This time it is complaining that it's missing the show action. So I'm going to get into my controller and add that new action there. This time I'm getting the missing x-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. 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 add the title and the body of the post to my template and run the cucumber command again. Because my posts object is new, it cannot find a title attribute on the no object so I'm going to go to the controller action and find an actual posts that I can render in my view. But interestingly, it cannot see the ID and the prams, so I'm not sure why that happens. I'm going to go ahead and open the log files and see what's there. When I open the log files, what I can see is that the post-path has a dot in it instead of slash and so that tells me there is a problem with the routes and I'm going to open the routes and try to fix whatever is in there. Hopefully this time I'm going to get it right. By running rails routes, I can see that my routes are looking okay 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 helper in my view template, so I'll need to make a change there are 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 that template file and add it in there just a simple text and I run the cucumber command again and this is it. This feature is now complete. 5. Second Feature: Create a Post with No Title: 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. This also communicates to other developers that this is another step in the history of the project. Now that my feature is complete and the code is committed to git, I can go ahead and start a new feature. This time it's going to 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. The way you would do is, you first add 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 UI level are really slow and you want to keep those edge cases as much as possible in your unit tests. Let's see what we have here. We are saying that if the user creates a post without a title, then he should see a validation error. Now that the test is written, we can continue with running cucumber and see what we get. Of course we get two missing steps, and we can easily copy those and paste them into the steps file. That's what I'm going to do, I'm going to add to my previous steps file those two new ones, and define what they mean. 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 fill title line because we don't want to do that. Then for my second step, or I should see a validation error ,it's just about having some content on the page, and in this case the missing title error. Now that the steps are defined, we can run cucumber again and see what we get. What we get is what we actually expect to get an error about missing the validation error on the page. That's because we haven't implemented that yet. But this is a good error to have because it guides you through development, through the implementation phase. 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. 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 errors. That means the form needs to have some error rendering for the object. If the errors are present in the object, we need to show them to the user. That's what I'm going to do now I'm going to add a section above the form that renders any errors present in the object. This is a copy and paste from a different projects, I'm just going to remove the markup data because It's not needed for this case. Back to running cucumber again and this time I'm getting two errors. If you remember, I changed something in a controller, and that's why I see those errors now. The safe thing to 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 post create and a render line. That's what I'm going to go back to and run cucumber again and see what I get. Running cucumber, I see that my previous test is passing and now my second test gives me an error. This is where I want to be, I want my entire implementation to be driven by tests as much as possible. 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. That's what I'm going to do next I'm going to implement validations on my model and for that, I will 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 UI tests. As you can see, I prefer to use the shooter way of writing validation tests and for that to work, I need to go ahead and install the shooter gem and configure r spec to use it. Now that I've installed the gem, I can run my tests again using r spec, and the error I get is the one I was expecting to get as the validation is not present on my model. I'll go ahead and implement that. In this case, the implementation code is really simple because it's provided by rayon s. All I need to do is just add the validation line and I'm done. My task is also passing I can now run the high level tests with cucumber and see what's happening. I know that my model now does validations and my view does not, it must be something at the view level. It's either view or controller. I've narrowed it down to that area. The first thing I'm going do is try to separate what create does into two different lines. First, I'm going to create a new object, and then I'm going to try to save it. 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 head into the controller and do some changes, some behavior changes. Namely I will render a different template if the validations fail. I will 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 and that's what I was expecting. All I did was to verify that I do see that validation error on the page. So this is a good point to wrap everything up and commit to Git. 6. Third Feature: Review Post: The last feature on our list is to view the post details. Let's create a new feature file and describe what this new feature should look like. The name of the feature is going to be review post, and in the description, we're going to 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 posts. Because that's what the user does. 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 create action. This test will cover the details page, so it's good to have it. As you've probably got used to by now, we're going to run the cucumber command again and see what steps we're missing. We're going to copy those steps, paste them into a steps file, and then define each step in turn. 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. Helper files are very useful to isolate common steps. 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 up tests harder to understand. But if you can name the helper methods and suggest what they do, I think that's a good way to refactor or some of the tests. 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. Instead of trying to be too dry like you would in a Rails app or Ruby app. You want to keep your tests more verbose even if you duplicate things. So that's okay. What I'm doing here is, I first define the helper method in a R Spec folder, and cucumber doesn't see that and so I need to move it in cucumber support folder and add it to cucumbers world as they call it. Once I do that, I should be fine. Except I forgot that it needs a module inside of a class. I'll change that and run the cucumber command again. My test is telling me that the first step is done and the next step to be defined is going to the details page, and that's very easy to do. All I have to do is click the name of the post and it should take me to the right page. Instead of relying on the actual texts in a title, I prefer to use the class name or an ID to find the elements on the page and interact with them. In this case I'm going to use the class name and I'll find the first-class and click it. 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. That's because I'm not displaying my posts on the page yet. What I need to do is open up my index template and make sure I'm rendering on my posts in there. I will add an HTML table, and for each post in my database, I will add a link that goes to that posts page and one more thing I want to add here is that if there are no posts then the table should not be rendered. Now that my template looks better, I want to run the cucumber command again and see what the errors tell me. 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 class name yet. I'm going to go ahead and add that class name to my link, just to make sure what the class name is, I'm going to open the test file and copy the name from there. Running the cucumber command again, I still see that error, and now I remember that my index action doesn't fetch all my posts. The post's object is empty, and that's why It doesn't render the table. Now that I've added that and run cucumber again, I see the error has changed. It now tells me that it cannot find a title, and if I open the posts controller that renders the details page, I can see that it doesn't fetch the posts by D. I'm going to have to add that to my action and then run the test again. Running the tests now shows me that the second step is now passing. All I have to do is define my last step. I'm going to open the steps file and for the last step, I'm going to create an expectation that the page that have the title and the body. 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'd 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.