Cześć, ogarniam Rspec Book i przy testowaniu controllera mam kilka pytań.
mam model Ad name:string title:string price:integer … stworzony został przez scaffold
describe AdsController do
before do @ad = mock_model(Ad, :save => true)
Ad.stub!(:new).and_return(@ad)
#@params = {}
end
def do_post
post :create,
#:ad => @params
end
describe "#create" do
it "creates a new ad" do
Ad.should_receive(:new).
#with(@params).
and_return(@ad)
do_post
end
it "save a new ad" do
end
it "redirects to Ad index" do
post :create
response.should redirect_to(:action => "index")
end
end
end[/code]
Takie testy napisałem do tej pory, wszystkie przeszły.
Nie wiem narazie jak napisać test sprawdzający czy ogłoszenie zostało zapisane.
Czy przy testowaniu kontrolera stosujecie jeszcze jakieś inne testy?
Rozumiem, że mock_model tworzy mi Ad z wypełnionymi wszystkimi polami i nie muszę tego robić ręcznie.
Co jednak robi stub!? i część and_return
Wyhaszowałem część, którą znalazłem w którymś tutorialu dotyczącą #params, testy przechodzą z nią i bez niej, mógłby mi ktoś wytłumaczyć za co ona odpowiada?
“1. Nie wiem narazie jak napisać test sprawdzający czy ogłoszenie zostało zapisane.”
Najłatwiej sprawdzić to poprzez sprawdzenie czy zwiększyła się liczba:
it "should save a new ad" do
lambda do
post :create
end.should change(Ad, :count).by(1)
end
“5. Wyhaszowałem część, którą znalazłem w którymś tutorialu dotyczącą #params, testy przechodzą z nią i bez niej, mógłby mi ktoś wytłumaczyć za co ona odpowiada?”
Zmienną @params masz pustą, więc nic dziwnego, że testy przechodzą poprawnie z nią i bez niej
Przekazujesz to co normalnie dostajesz w GET czy POST z formularza.
Funkcja kontrela nie jest zapisanie ogłoszenia tylko wysłanie rzadania zapisania gdzies indziej. Teraz testujesz czy Ad wykouje metedę new z paramaterami z params. Możesz jeszcze dodac sprawdzanie czy utworzony obiekt otrzymuje motode save (przed do_post w describe “#create”):
@ad.should_receive(:save).and_return(true)
generalnie testujsz to co robi kontroler. Np redirecty, pzypisywanie zmiennych dla widoku, czy wykonuja sie filtry, ograniczanie dostepu jesli jest itp.
Nie, mock_model tworzy mock’a ze stub’ami na niektórych motodach ActiveRecord’a. stub_model tworzy instancje twojego obiektu ze stub’ami na niektórych motodach ActiveRecord’a. Jeśli chcesz mieć instancje obiektu z powypelnianymi polami mozesz uzyc Factory Girl, Machinist albo Fabrication.
stub dodaje metode to obiektu, and_return określa co stub (albo exceptation) zwraca. Np:
Ad.stub!(:new).and_return(@ad)
Spowoduje ze każde wywolanie Ad.new zwróci @ad, ale nic sie nie stanie jesli podczas testu nie bedzie wywolania Ad.new
Ad.should_receive(:new).with({}).and_return(@ad)
Na Ad powinna byc wykonana metoda new z parametrem {} i zwróci @ad
Ad.should_receive(:new).and_return(@ad)
Na Ad powinna byc wykonana metoda new (z dowolnymi parametrami lub bez) i zwróci @ad
Wykomentuwując wszystkie odwołania do @params testujesz bardziej obolny scenariusz.
Nie wiem co masz na myśli pod pojęciem „testy integracyjne”, ale założę, że chodzi Ci o to co ja rozumiem pod „akceptacyjne”, np. cucumber, czy inne capybara-webkit, etc. One są po prostu wolniejsze niż testy kontrolerów i nie ma sensu ich używać do testowania wszystkich możliwych zachowań kontrolera.
Ja szczerze mówiąc testuję kontrolery głównie w przypadku kiedy mają jakieś niestandardowe rzeczy, które chcę sprawdzić (np. czy cookie się ustawiło). Ostatnio nie pisałem żadnej aplikacji z rozbudowanym systemem uprawnień, ale w takim przypadku też bym to zrobił jako testy kontrolerów. Jeżeli kontroler jest dosyć standardowy, tzn. najczęściej wywołanie jednej metody, to zostawiam to dla testów akceptacyjnych (chyba, że z jakiegoś powodu nie chcę pisać testów akceptacyjnych dla danego przypadku).