Rails tesztek Rspec-el

Geri 2011-11-26 20:10:58 UTC

A tesztelés egy nagyon fontos része a fejlesztésnek (legalábbis én annak tartom). Arra most nem szeretnék kitérni, hogy miért, helyette be szeretném mutatni napjaink de-facto Rails teszt eszközét, az Rspec-et.

Kezdésnek generáljuk egy friss Rails app-ot, de Test::Unit nélkül: rails new rspec_test --skip-test-unit. Ha ezzel megvagyunk, adjuk hozzá az alábbiakat a Gemfile-hoz:

group :test do
    gem "rspec-rails", "~> 2.4"
end

Miután lefuttatjuk a bundle parancsot, a rails generátorok közé bekerül néhány Rspec generátor. Futtassuk le az rspec:install-t, ami létrehoz nekünk néhány fájlt, illetve regisztrálja az rspec generátorokat. Adjuk hozzá az alábbiakat az application.rb konfigurációs fájlhoz:

config.generators do |g|
g.test_framework :rspec
end

Így innentől, ha generálunk egy scaffold-ot, akkor Test:unit tesztek helyett rspec teszteket fog nekünk a Rails generálni. Egyelőre viszont ne használjuk a scaffold generátort, hanem kóstoljunk bele a BDD-be.
Tegyük fel, hogy az app-unk egy blog lesz. Tehát lesznek post-jaink és ezeknek lesz egy title és egy content tulajdonsága. Ezek közül, a title-t szeretnénk kötelezővé tenni. Miután nagyjából kitaláltuk hogy mit szeretnénk, irjunk egy tesztet, ami ennek a viselkedésnek a működését ellenőrzi. Az rspec generátorát használva generáljunk egy spec skeletont:
rails g rspec:model Post

Az rspec spec-ek, describe blokk-okból állnak. A describe rész maga a viselkedés leírása, amit egy it blokk-al tesztelünk. Például esetünkben valahogy így néz ki a spec fájl:
require ‘spec_helper’

describe ‘Post’ do
describe “Post has to be valid” do
it “needs to have a title at least” do
post = Post.new
post.valid?.should be false
end
end
end


Futtassuk le a tesztet az rspec parancs segítségével és nézzük meg mi lesz az eredmény:
Failures:

1) Post Post has to be valid needs to have a title at least Failure/Error: post = Post.new NameError: uninitialized constant Post
  1. ./spec/models/post_spec.rb:6

Az eredmény igazából nem meglepő. Mivel nincs Post model definiálva, így kapunk uninitialized constant hibát. Ez a problémát könnyedén tudjuk orvosolni egy model generálásával:
rails g model Post title:string content:text

Futtassuk újra a tesztünket:
 1) Post Post has to be valid needs to have a title at least
Failure/Error: post = Post.new
ActiveRecord::StatementInvalid:
Could not find table ‘posts’
  • ./spec/models/post_spec.rb:6:in `new’
  • ./spec/models/post_spec.rb:6

  • Újabb hibát kaptunk, mivel nincs tábla az adatbázisban a Post modelhez. Javítsuk ezt is:
    rake db:migrate RAILS_ENV=test

    Tesztünk futtatása után ezt az eredmény kapjuk:
    1) Post Post has to be valid needs to have a title at least
    Failure/Error: post.valid?.should be false expected # => false got # => true Compared using equal?, which compares object identity, but expected and actual are not the same object. Use ‘actual.should == expected’ if you don’t care about object identity in this example.
    1. ./spec/models/post_spec.rb:7

    Végre eljutottunk odáig, hogy maga az aktuális tesztelendő funkció hibázik csak, ugyanis a Post model valid title attributum nélkül is. Ennek a javításához nem kell mást tennünk, mint ezt az attributumot kötelezővá tenni:
    #app/models/post.rb
    class Post < ActiveRecord::Base
    validates_presence_of :title
    end

    Ha most újra futtatjuk a tesztünket akkor az alábbi eredményt kapjuk:
    1 example, 0 failures

    Hurrá, sikerült implementálnunk a kivánt viselkedést. A BDD szerintem egy nagyon jó fejlesztési módszer, és az rspec nagyon sok segítséget nyújt hozzá. Ha a config/application.rb fájlhoz hozzáadjuk az alábbiakat, akkor a scaffold generálásnál a rails generálni fog nekünk rspec minta teszteket is amiből sokat tanulhatunk:
    config.generators do |g|
    g.test_framework :rspec
    end

    Ez a cikk csak egy bevezető, de igyekszem a functional és integrational tesztekről is írni a jövőben.

    Hozzászólások


    Ajánló

    Ajánló archivum
    ruby rvm git github verziókezelés rails rspec tesztelés ruby on rails