Iteration C4: Functional Testing of Controllers

Now for the moment of truth. Before we focus on writing new tests, we need to determine if we’ve broken anything. Remembering our experience after we added validation logic to our model, with some trepidation we run our tests again:

 depot>​​ ​​bin/rails​​ ​​test

This time, all is well. We added a lot, but we didn’t break anything. That’s a relief, but our work isn’t done yet; we still need tests for what we just added.

The unit testing of models that we did previously seemed straightforward enough. We called a method and compared what it returned against what we expected it to return. But now we’re dealing with a server that processes requests and a user viewing responses in a browser. What we need is functional tests that verify that the model, view, and controller work well together. Never fear—Rails has you covered.

First, let’s take a look at what Rails generated for us:

 require ​'test_helper'
 
 class​ StoreControllerTest < ActionDispatch::IntegrationTest
  test ​"should get index"​ ​do
  get store_index_url
  assert_response ​:success
 end
 
 end

The should get index test gets the index and asserts that a successful response is expected. That certainly seems straightforward enough. That’s a reasonable beginning, but we also want to verify that the response contains our layout, our product information, and our number formatting. Let’s see what that looks like in code:

 require ​'test_helper'
 
 class​ StoreControllerTest < ActionDispatch::IntegrationTest
  test ​"should get index"​ ​do
  get store_index_url
  assert_response ​:success
» assert_select ​'nav.side_nav a'​, ​minimum: ​4
» assert_select ​'main ul.catalog li'​, 3
» assert_select ​'h2'​, ​'Programming Ruby 1.9'
» assert_select ​'.price'​, ​/$[,d]+.dd/
 end
 
 end

The four lines we added take a look into the HTML that’s returned, using CSS selector notation. As a refresher, selectors that start with a number sign (#) match on id attributes; selectors that start with a dot (.) match on class attributes; and selectors that contain no prefix match on element names.

So the first select test looks for an element named a that’s contained in a nav element that has the class side_nav. This test verifies that a minimum of four such elements are present. Pretty powerful stuff, assert_select, eh?

The next three lines verify that all of our products are displayed. The first verifies that there are three li elements inside a ul with the class catalog, which is itself inside the main element. The next line verifies that there’s an h2 element with the title of the Ruby book that we’d entered previously. The fourth line verifies that the price is formatted correctly. These assertions are based on the test data that we put inside our fixtures:

 # Read about fixtures at
 # https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
 
 one:
  title: ​MyString
  description: ​MyText
  image_url: ​lorem.jpg
  price: ​9.99
 
 two:
  title: ​MyString
  description: ​MyText
  image_url: ​lorem.jpg
  price: ​9.99
 
 ruby:
  title: ​Programming Ruby 1.9
  description:
 Ruby is the fastest growing and most exciting dynamic
 language out there. If you need to get working programs
 delivered fast, you should add Ruby to your toolbox.
  price: ​49.50
  image_url: ​ruby.jpg

Maybe you noticed that the type of test that assert_select performs varies based on the type of the second parameter. If it’s a number, it’s treated as a quantity. If it’s a string, it’s treated as an expected result. Another useful type of test is a regular expression, which is what we use in our final assertion. We verify that there’s a price that has a value that contains a dollar sign followed by any number (but at least one), commas, or digits; followed by a decimal point; followed by two digits.

One final point before we move on: both validation and functional tests will test the behavior of controllers only; they won’t retroactively affect any objects that already exist in the database or in fixtures. In the previous example, two products contain the same title. Such data will cause no problems and will go undetected up to the point when such records are modified and saved.

We’ve touched on only a few things that assert_select can do. More information can be found in the online documentation.[43]

That’s a lot of verification in a few lines of code. We can see that it works by rerunning just the functional tests (after all, that’s all we changed):

 depot>​​ ​​bin/rails​​ ​​test:controllers

Now not only do we have something recognizable as a storefront, but we also have tests that ensure that all of the pieces—the model, view, and controller—are all working together to produce the desired result. Although this sounds like a lot, with Rails it wasn’t much at all. In fact, it was mostly HTML and CSS and not much in the way of code or tests. Before moving on, let’s make sure that it’ll stand up to the onslaught of customers we’re expecting.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.179.186