Functional Tests einer Rails 2.3.x Anwendung mit Paperclip und Clearance 0.8.8
Endlich habe ich mal Zeit gefunden, für eine etwas betagtere Rails-Anwendung (Rails 2.3.14) die Tests zu schreiben. Das Scaffolding erstellt zwar ein Grundgerüst, das aber bei fortgeschrittener Entwicklung immer angepasst werden muss. Die Unit-Tests waren kein großes Problem. Bei den Functional-Tests wurde es schon komplizierter. In der Anwendung kommt Paperclip als Gem zum Einsatz, um verschiedene Models mit einem Bild zu erweitern. Zur Authentifizierung wird Clearance als Plugin verwendet und liegt in Version 0.8.8 vor. Diese Version ist schon etwas älter und zum Testen wird Cucumber empfohlen. Paperclip hat sogenannte Matchers für RSpec. Ich wollte aber keines der beiden benutzen und stattdessen mit Rails-eigenen Mitteln (test/unit) Tests schreiben und die durch das Scaffolding automatisch erstellten Tests erweitern.
Mein erstes Problem waren die Fixtures. Da war es recht schwierig ein Bild festzulegen und somit automatisch laden zu lassen. FactoryGirl hat ein ziemlich gutes Konzept, um Fixtures zu erstellen und wird auch ziemlich häufig verwendet. Damit konnte ich dann ganz einfach Fixtures, sogenannte Factories, mit einer Bilddatei erstellen, die dann von meinem Model und damit von Paperclip anstandslos geschluckt wurden.
# test/factories/factories.rb
Factory.define :picture do |picture|
picture.data { File.new(RAILS_ROOT + '/test/factories/bg.jpg') }
picture.author { "test author" }
picture.gallery { Factory(:gallery) }
end
Um FactoryGirl anstatt der Standard-Fixtures zu verwenden, habe ich einfach das factory_girl gem zu meiner config/environments/test.rb hinzugefügt,
# config/environments/test.rb
config.gem 'factory_girl'
das Laden der Fixtures in der test_helper.rb auskommentiert,
# fixtures :all
den fixtures Ordner gelöscht und eine factories.rb angelegt. In dieser kann ich nun fleißig Factories mit allerlei Funktionen anlegen. Für weiteres einfach in die FactoryGirl Doku gucken.
Als das erledigt war, konnte ich anfangen die Tests zu schreiben. Da ich Clearance als Authentifizierung verwende, musste ich erst einmal herausfinden, wie ich das Ein- und Ausloggen mit den Tests berwerkstelligen kann. Das Gem ist schon recht alt und deswegen war es etwas schwierig darüber etwas Doku zu finden. Ich habe es wie folgt gelöst.
Meine test_helper.rb bindet die Helpers von Clearance ein.
# test/test_helper.rb
require File.join(File.dirname(__FILE__), '..', 'vendor', 'plugins', 'clearance', 'shoulda_macros', 'clearance')
Jetzt kann ich alle meine Tests mit einer setup und teardown methode ausstatten, die die Clearance Methoden signin und signout nutzen können, um das Ein- und Ausloggen zu bewerkstelligen.
# test/functional/pictures_controller_test.rb
def setup
sign_in
@picture = Factory.create(:picture)
end
def teardown
sign_out
@picture = nil
end
Dabei wird außerdem eine Instanzvariable angelegt, die ich in den Tests anstatt der Fixtures verwende. Andere Teile des Tests, die noch die alten Fixtures verwenden, musste ich noch austauschen.
# test/functional/pictures_controller_test.rb
test "should create picture" do
assert_difference('Picture.count') do
post :create, :picture => Factory.attributes_for(:picture)
end
assert_redirected_to picture_path(assigns(:picture))
end
test "should show picture" do
get :show, :id => @picture.id
assert_response :success
end
test "should get edit" do
get :edit, :id => @picture.id
assert_response :success
end
test "should update picture" do
put :update, :id => @picture.id, :picture => Factory.attributes_for(:picture)
assert_redirected_to picture_path(assigns(:picture))
end
test "should destroy picture" do
assert_difference('Picture.count', -1) do
delete :destroy, :id => @picture.id
end
assert_redirected_to pictures_path
end
Die kompletten functional-Tests gibt es hier. Damit laufen alle Tests für die Anwendung erfolgreich. Ich bin mir garnicht sicher, ob das der beste Weg ist, um die Tests so zu bauen und daher für Verbesserungsvorschläge dankbar.