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
- ./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’
Ú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
- ./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 aconfig/application.rbfá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.