Functional test: testowanie kontrolera post

Witam,

to są moje pierwsze kroczki w railsach. Stworzyłem bloga wg tutka stąd http://rubyonrails.pl/screencasty. Chciałem teraz napisać testy. Więc napisałem:

[code]require ‘test_helper’

class PostsControllerTest < ActionController::TestCase
test “should create post” do
post :new, :title => ‘Tytuł postu’, :body => ‘jakaś tam treść’
p = Post.first
assert_equal ‘Tytuł postu’, p.title
assert_redirected_to post_url§
end
end[/code]
lecz dostaję błąd w linii 7 dostaję w p.title ciągle nil…
wyłączyłem na chwilę autoryzację, aby 401 nie rzucało :slight_smile:

a przy okazji jak zasymulować logowanie?

logowanie możesz zrobić, tak, że zrobić stuba dla metody authenticate! (jeśli używasz devisa) i zwrócisz true po wywoałniu, ale to nie jest sprawdzenie czy osoba jest zalogowana a jedynie symulacja.

i tak nie rozumiem połowy rzeczy o których mowisz :smiley:
a co z tym testem?

Zastanów i/lub sprawdź:

  • czy post :new w twojej aplikacji tworzy nowy rekord w bazie? Może chcesz raczej testować post :create, w tym przypadku?
  • czy na pewno Post.first pobiera z bazy to co chesz? Może lepsze będzie Post.last, albo sprawdzenie Post.count przed i po teście oraz sprawdzenie assigns?

Poczytaj http://guides.rubyonrails.org/testing.html#functional-tests-for-your-controllers

post :new, :post => {:title => 'Tytuł postu', :body => 'jakaś tam treść'}

?

Pytasz się jak zasymulować logowanie, a nie pokazujesz jak wygląda mechanizm logowania. Zarzuć jakimś kodem, bo w przeciwnym razie cieżko będzie zgadnąć.

symulowanie mam tak jak z ww filmu, czyli do kontrollera dodałem:

before_filter :authenticate :except => [:inde, :show]

a na końcu:

def authenticate do [name, password] authenticate_or_request_http_basic do [name, password] name = 'admin' && password = 'secret' end end
@tiwi
no tworzenie nowego posta :slight_smile:

@kabanek
Zauważ subtelną różnicę w Twojej linijce kodu i tej zaproponowanej przeze mnie :wink: Jeśli w formularzu używasz form_for i masz model Post, to paramsy domyślnie będą przekazywane w ten sposób :slight_smile:

#EDITED:

Aaaa, też głupoty piszę, sory. Obstawiam, że to powinno wyglądać mniej więcej tak:

post :create, :post => {:title => 'Tytuł postu', :body => 'jakaś tam treść'}

Z tego względu, że dane z formularza lecą do metody create, a nie new :smiley:

[quote=kabanek]def authenticate do [name, password] authenticate_or_request_http_basic do [name, password] name = 'admin' && password = 'secret' end end
@tiwi
no tworzenie nowego posta :)[/quote]
jesteś na 100% pewien, że tak wygląda ten kawałek kodu? :smiley:

def authenticate authenticate_or_request_http_basic do |name, password| name == 'admin && password == 'secret' end end
nawiasy kwadratowe oznaczają tablice a nie parametry przekazywane do bloku. te oznacza się przez tą (|) pionową kreskę która nie wiem jak się nazywa :wink:

@tiwi

u mnie to teraz wygląda tak:

[code=ruby]require ‘test_helper’

class PostsControllerTest < ActionController::TestCase
test “should create post” do
post :create, :post => {:title => ‘Tytuł postu’, :body => ‘jakaś tam treść’}
p = Post.last
assert_equal ‘Tytuł postu’, p.title
assert_redirected_to post_url§
end
end[/code]
i nadal mam

[quote]test_should_create_post(PostsControllerTest) [test/functional/posts_controller_test.rb:7]:
<“Tytuł postu”> expected but was
.[/quote]
czyli jednak do bazy nie zapisuje nadal

@up

to nie był kopiowany kod a przepisywany :slight_smile: sory za wprowadzenie w błąd. Mój kod wygląda tak:

private def authenticate authenticate_or_request_with_http_basic do |name, password| name = "admin" && password = "secret" end end

To pokaż jeszcze metodę create z kontrolera i jeszcze pytanie: czy w modelu Post masz gdzieś attr_accessible?

to co w kontrolerze

[code=ruby] # GET /posts/new

GET /posts/new.xml

def new
@post = Post.new

respond_to do |format|
  format.html # new.html.erb
  format.xml  { render :xml => @post }
end

end

GET /posts/1/edit

def edit
@post = Post.find(params[:id])
end

POST /posts

POST /posts.xml

def create
@post = Post.new(params[:post])
@post.createSlug

respond_to do |format|
  if @post.save
    format.html { redirect_to(@post, :notice => 'Post was successfully created.') }
    format.xml  { render :xml => @post, :status => :created, :location => @post }
  else
    format.html { render :action => "new" }
    format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
  end
end

end[/code]
a model wygląda tak:

[code=ruby]class Post < ActiveRecord::Base
validates_presence_of :body, :title, :slug => {:required => false, :unique => true }
has_many :comments

attr_accessor :title, :slug

def createSlug
	@slug = @title.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
end

end[/code]

Zamieniłbym kolejność asercji w teście na:

assert_redirected_to post_url(p) assert_equal 'Tytuł postu', p.title
wykonując Twój kod dostałem 401 Unauthorized, więc tak na prawdę nawet nie uderzyło w akcję #create (wymagany jest przecież HTTP Basic), a Post.last zwrociło to co akurat było w bazie danej testowej; mi ostatni fixture.

ja zmieniłem testy na:

[code=ruby]require ‘test_helper’

class PostsControllerTest < ActionController::TestCase
test “should create post” do
post :create, :post => {:title => ‘Tytuł postu’, :body => ‘jakaś tam treść’}
p = Post.last
assert_redirected_to post_url§
assert_equal ‘Tytuł postu’, p.title
end
end[/code]
i wykomentowałem linijkę

[code=ruby]class PostsController < ApplicationController

before_filter :authenticate, :except => [:index, :show][/code]

lecz nadal dostaję

[quote]1) Failure:
test_should_create_post(PostsControllerTest) [test/functional/posts_controller_test.rb:8]:
<“Tytuł postu”> expected but was
.[/quote]
kurcze nie wiem co jest nie tak;P a pomysły mi się już kończa :slight_smile:

Zamień attr_accessor na attr_accessible, to dwie różne rzeczy.

[code=ruby]class Post < ActiveRecord::Base
validates_presence_of :body, :title, :slug => {:required => false, :unique => true }
has_many :comments

def createSlug
	self.slug = title.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
end

end[/code]

nie ma co koła na nowo wymyślać i uproszczać:

@up
tak, tylko ja przy okazji chcę się nauczyć Railsów więc to będzie dobre ćwiczenie dla mnie

zajrzyj wiec do gems, lub poczytaj bo pewnie samo ’ ', ‘-’ nie wyczerpuje wszystki opcji

niby zaczęło działać, tylko wywalało mi błąd, że metoda slug jest nieznana

test "create slug based on title" do post = Post.new post.body = 'some body' post.title = 'My title' post.createSlug assert_equal 'My-title', post.slug end
w przed ostatniej linijce.
zmieniłem za to klasę post

[code]class Post < ActiveRecord::Base
validates_presence_of :body, :title, :slug => {:required => false, :unique => true }
has_many :comments

attr_accessible :title, :slug, :body

def createSlug
	@slug = title.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
end

def slug
	@slug
end

end[/code]
i testy przechodzi :slight_smile: