Loading...
New webinar: "The Remote Job Search: My Microverse Journey" with graduate Paul Rail
Watch Now

We have launched an English school for software developers. Practice speaking and lose your fear.

Topics

In my previous article, I wrote about the MVC model and how to create an application. Although it is not a requirement for this tutorial, I recommend taking a look at it. In this article, we will reinforce the understanding of the model but will now use Test-driven development (TDD) to create an app.

The objective here is not to deepen the understanding of TDD itself, but  to understand the model, and the way we are going to program will guide us to understand it. In this article we will also go through the tutorial Step By Step Ruby on Rails Tutorial by Eduardo Baike and Kasey Champion.

Introduction to TDD

TDD is a software development process where you start to write the test cases before the software is fully developed, then add features in order to pass all test cases. If you want to know more about TDD in Ruby on Rails, I strongly recommend the article Understanding Test-Driven Development with RSpec in Ruby on Rails by fellow Microverse student, Uduak Essien.

Building an App

First things first, you must set up your machine. To do this, make sure that you have installed RoR according to the Odin Project  tutorial on INSTALLING RAILS.

Now, let’s start running on your terminal the following commands:

{% code-block language="js" %}
$ rails new bookstore
$ cd bookstore/
{% code-block-end %}

Open the project in an editor (I useVSCode) then open the project running the server:

{% code-block language="js" %}
$ rails server
{% code-block-end %}

Next, open it in your browser (http://localhost:3000)  and you should see that it is working.

Diagram Automatically generated description

Installing Rspec

Now, go to the Gemfile and add the gem rspec-rails in the development test group.

Installing Rspec

 Follow the commands:

{% code-block language="js" %}
$ bundle install
$ rails g rspec:install

{% code-block-end %}

We are testing features, so go to the rspec folder and add a folder called features. Inside that, add the file called books_spec.rb and add the code: 

{% code-block language="js" %}
require 'rails_helper'
RSpec.describe 'Book' do
        context 'context' do
before do
    book = Book.create(title:'The Lord of the Rings', author:'Tolkien')
    visit '/'
end
it 'display a list books with the title and author' do
    expect(page).to have_text('The Lord of the Rings')
    expect(page).to have_text('Tolkien'')
    expect(page).to have_link('New Book')
   end
       end 
end 
{% code-block-end %}

Now you can run the command to test it: 

{% code-block language="js" %}
$ rspec spec/features/books_spec.rb
{% code-block-end %}

After running the test you will see the below error in your terminal:

books_spec.rb


What does that mean though? 

It means we have no Book model for the path '/'. Pay attention to the error message 'uninitialized constant Book'.

So, to solve this let's create a model called ‘book’, setting up our table with two columns (title and author) running the commands:

{% code-block language="js" %}
$ rails g model book title:string author:string --no-test-framework
$ rails db:migrate

{% code-block-end %}

(Using the code --no-test-framework-- we are saying not to create a test file since we are creating our own.)

Now you can run the test again: 

Books_spec.rb

The error now says that we have no route for the path '/'. Also, be sure to pay attention to the error message that says to use the method GET to set up the route. 

So, let's set up our routes to connect URLs to code.

  1. Go to the file routes.rb inside the folder config and add the line:

{% code-block language="js" %}
Rails.application.routes.draw do
     get '/',  to:  'books#index'
end
{% code-block-end %}

Where: 

  • get is the HTTP Verb;
  • '/' is the Path;
  • books#index is controller#action (we will add the index method inside the books_controller.rb file)

Run  the test again. 

Now the error says that we don't have a book controller. Do you see that we are missing the C from the MVC? 

Using Test-Driven Development
  1. Next, let's create a books controller file by typing the below command in your terminal:

{% code-block language="js" %}
$ rails generate controller books --no-test-framework
{% code-block-end %}

Now run your test again. You should see an error saying you don’t have any actions called ‘index’ in the controller.

books controller
  1. Add an empty method called ‘index’ in your players_controller.rb file following the below:

{% code-block language="js" %}
class BooksController < ApplicationController
                  def index
                  end
           end
{% code-block-end %}

  1. Run your test again. You will yet again get an error message because we are still missing a template (the V from MVC), so we do not have a view.
Coding Book Context Display a list


As you see when you create a controller, we also are creating a folder called ‘views(empty)’.

  1. Let’s create a new file inside the views/books called index.html.erb and add the code:

{% code-block language="js" %}
<h1>Books</h1>
<p>The Lord of the Rings</p>
<p>Tolkien</p>
<%= link_to 'New Book', '/books/new' %>
{% code-block-end %}

  1. Run your test again and you will see the test passed! Now we want to add more code to make it dynamic. 
  1. So, let’s try creating an instance variable in your controller to get all the books from the model ‘Books’. Remember that the model will hold our data. So, your index method is going to be like this: 

{% code-block language="js" %}
class BooksController < ApplicationController
       def index
@books = Book.all
        end
end
{% code-block-end %}

  1. Now add something in our index.html.erb file as:  

{% code-block language="js" %}
<h1>Books <%= pluralize(@books.length, 'Books')%></h1>
<tbody>
<% @books.each do |book| %>
      <table>
<tr>
  <th>Title</th>
   <th>Author</th>
</tr>
<tr>
   <td><%= book.title%></td>
    <td><%= book.author%></td>
</tr>
                 </table>
            <% end %>
</tbody>
<%= link_to "New Book, "/books/new" %>
{% code-block-end %}

  1.  Test again. You will see that the test will pass.
Check Test Result

However, the data we are testing is not from the database. If you run the server and open it in your browser, you will see it is empty.


Testing is not from the Database

Testing the Method New

Since the database is empty we have to create a method to populate it, this method will be called new. However, we are working with TDD, so let's create the test first. Follow the below steps:

  1. Go to the folder called features, create a file called new_books_spec.rb and add the code: 

{% code-block language="js" %}
require 'rails_helper'
RSpec.describe 'Book' do
        context 'context' do
before do
    book = Book.create(title:'The Lord of the Rings', author:'Tolkien')
    visit root_path
    click_link('New book')
end
it 'page to create a new book' do
  expect(page).to have_field('title')
    expect(page).to have_field('author')
   end
        end
end
{% code-block-end %}

  1. Go to the routes.rb and add the code: 

{% code-block language="js" %}
Rails.application.routes.draw do
      root 'books#index'
      get 'books',  to:  'books#index'
end
{% code-block-end %}

Before we test the new feature, let's change the books_spec.rb file by replacing the code visit '/' to visit root_path and test it. Now we can test the new feature running the command:

$ rspec spec/features/new_books_spec.rb

You will see the error regarding no route matches. Does it sound familiar?

Routing Error
  1. Now, let's add the route that we are missing in routes.rb as:

{% code-block language="js" %}
Rails.application.routes.draw do
                               root 'books#index'
                               get 'books',  to:  'books#index'
        get 'books/new', to: 'books#new'
          end
{% code-block-end %}

  1. Run the test again. You will see an error saying we are missing the method new. At this point, we are going to repeat all the previous steps, so let's add the method new in your books_controller.rb file as: 

{% code-block language="js" %}
def new
    @books = Book.new
end
{% code-block-end %}

  1. Run the test once more. You will see an error saying we are missing the template. At this point, go to the views/books and create a new file called new.html.erb and add a template and run it once more. 

For a full-video walk-through of this concept and tutorial, you can view the video below:

Conclusion

Now you should have a better understanding of the MVC model by using TDD. You are going to need to repeat the steps over and over again if you want to create new features like create, update and destroy. From this tutorial, you can also see that TDD is a great option to guide us through adding features.

As always, remember to check the Rails documentation.

Happy Coding!


We have launched an English school for software developers. Practice speaking and lose your fear.

Subscribe to our Newsletter

Get Our Insights in Your Inbox

Career advice, the latest coding trends and languages, and insights on how to land a remote job in tech, straight to your inbox.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
We use own and third party cookies to; provide essential functionality, analyze website usages, personalize content, improve website security, support third-party integrations and/or for marketing and advertising purposes.

By using our website, you consent to the use of these cookies as described above. You can get more information, or learn how to change the settings, in our Cookies Policy. However, please note that disabling certain cookies may impact the functionality and user experience of our website.

You can accept all cookies by clicking the "Accept" button or configure them or refuse their use by clicking HERE.