Three different ways of testing your Rails App

Benito Serna
Mar 19, 2018 · 5 min read

What are we going to test?

Testing everything via “system tests”

feature "Users sees the catalog" do
scenario "with all products sorted by name" do
create :product, name: "product A"
create :product, name: "product B"

visit catalog_path

expect_ordered_products("product A", "product B")
end

scenario "with the name, description and price of each product" do
create :product,
name: "product 1",
description: "p1 - desc",
price: 1000

visit catalog_path

expect(page).to have_content "product 1"
expect(page).to have_content "p1-desc"
expect(page).to have_content "$1,000.00"
end

scenario "with a product without price" do
create :product, price: nil

visit catalog_path

expect(page).to have_content "Call for price"
end

scenario "with featured products" do
create :product, name: "product A"
create :product, name: "product B"
create :product, name: "product Featured", feature: true

visit catalog_path

expect_ordered_products(
"product Feature", "product A", "product B")
end
end

Testing controllers and views

RSpec.describe ProductsController do
describe "GET index" do
describe "assigns @products" do
it "with the products sorted by name" do
create :product, name: "B"
create :product, name: "A"

get :index
expect(assigns(:products).map(&:name)).to eq(["A", "B"])
end

it "with the featured products first" do
create :product, name: "B"
create :product, name: "A"
create :product, name: "Featured"

get :index
expect(assigns(:products).map(&:name))
.to eq(["Featured", "A", "B"])
end
end
end
end
RSpec.describe "products/index" do
it "shows the name, description and price of the products" do
assign(:products, [
create :product,
name: "Product-A",
description: "A-desc",
price: 1000
])

render

expect(rendered).to match /Product-A/
expect(rendered).to match /A-desc/
expect(rendered).to match /$1,000.00/
end

it "shows 'call for price' for products without price" do
assign(:products, [create :product, name: "A"])

render

expect(rendered).to match /Call for price/
end
end

Testing a non Rails function

def index
@products = Catalog.get_products(Product)
end
# products/index.haml
- products.each do |product|
%td= product.name
%td= product.description
%td
- if product.has_price?
= number_to_currency product.price
- else
Call for price
module Catalog
RSpec.describe "Get products" do
it "returns all the stored products sorted by name"
it "returns the featured products first"

describe "each product" do
it "with a name, description and price"
it "knows if has price or not"
end
end
end
module Catalog
RSpec.describe "Get products" do
def get_products(store)
Catalog.get_products(store)
end

it "returns all the stored products sorted by name" do
products = get_products(store_with([
product_with(name: "B"),
product_with(name: "A")
]))

expect(products.map(&:name)).to eq ["A", "B"]
end

it "returns the featured products first" do
products = get_products(store_with([
product_with(name: "B"),
product_with(name: "A"),
product_with(name: "Featured")
]))

expect(products.map(&:name)).to eq ["Featured", "A", "B"]
end

describe "each product" do
it "with a name, description and price" do
product = get_products(store_with([
product_with(name: "A", descrition: "A-desc", price: 1000)
])).first

expect(product.name).to eq "A"
expect(product.description).to eq "A-desc"
expect(product.price).to eq 1000
end

it "knows if has price or not" do
with_price, without_price = get_products(store_with([
product_with(name: "A", price: 1000),
product_with(name: "B", price: nil)
]))

expect(with_price).to have_price
expect(without_price).not_to have_price
end
end
end
end

Conclusion


Benito Serna

Written by

Building software at Briq.mx & JazzControls

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade