Não foi possível carregar o Diqus. Se você é o moderador, por favor veja o nosso guia de problemas.

Davis Zanetti Cabral • 18 anos atrás

Muito bom o artigo. Uma dica para visualizar melhor os testes é o uso do RadRails ou então a instalação do gem RedGreen. Dá uma força bacana na hora de visualizar.

Abraço!

Klaus Paiva • 18 anos atrás

Muito bom (Ferdi)Nando!

Matou a pau no texto! Ficou muito claro e didático. O trio migrate, tests e fixtures (que eu realmente só conhecia por pouco mais do que o nome) agora me parecem muito mais interessantes!

Valeu! :D

Silfar • 18 anos atrás

Muito show, mas me tira uma dúvida:

def test_should_require_longer_password
user = create(:password => 't')
assert user.errors.invalid?(:password), ":password should be 4 characters or longer"
assert_invalid user, "User shouldn't be created"
end

Pq usar as duas linhas:

assert user.errors....
assert_invalid user......

não entendi pq precisa das duas. Pode me explicar ?

Nando Vieira • 18 anos atrás

Silfar, não precisa. Mas é como eu falei: você pode deixar o seu teste tão completo quanto você queira. Paranoicamente, eu poderia ainda ter adicionado uma asserção para verificar se uma mensagem de erro foi definida. Precisa? Teoricamente, não. Mas é tão simples de fazer que eu realmente não me importo. Ah, mencionei que eu uso snippets para meus testes e que eu só preciso colocar "ai + tab"? :)

Eduardo Fiorezi • 18 anos atrás

Nando, parabéns pela excelente abordagem.

Igual vc falou no comentário, com TDD não é necessário cobrir "100%" das situações, mas é bom cobrir todas necessárias naquele momento... Ficar imaginando tudo que pode acontecer é prejudicial e essas milhões de situações imaginadas talvez nunca apareçam.

Espero os próximos...

Shairon • 18 anos atrás

Muito bom. Estou ansioso para ver o de funcionalidade

Luciano Pacheco • 18 anos atrás

def test_should_require_name
comment = create(:name = nil)
assert comment.errors.invalid?(:name), ":name should have had an error"
assert_invalid comment, "Comment shouldn't be created"
end

":name should have had an error"

Nas mensagens não devemos utilizar mensagens mais explicativa, tipo "name can't be blank" ou algo parecido ?

Estou perguntando, pois também estou iniciando nesse mundo de XP e TDD. :)

Valeu pelo artigo. ;)

Nando Vieira • 18 anos atrás

@Luciano: Melhor do que isso, você pode fazer algo assim:

assert comment.errors.invalid?(:name), ":name should have had an error\n#{comment.errors.full_messages.to_sentence}"

Você decide como quer fazer! ;)

Renato Elias • 18 anos atrás

Mandou bem nando ! Vlw, como você me falou no "praianha" ruby é babaca de tão fácil =)

Diogo Lopes • 18 anos atrás

Parabens cara... nao sei como vim parar aqui, mas estou assinando.
Tem muita gente falando que ABC , XCD , ZZZ é bacana, fundamental, etc... Mas tu mostrou na pratica que vale a pena.
E tudo em Ruby, que é melhor ainda. (até hj, só tinha visto TDD em JAVA em pt)

abcs!

rapha • 18 anos atrás

Fantástico velho. Acabei de escrever os testes de um projeto aqui, e realmente facilita a vida. Agora eu fico muito mais seguro de implementar qualquer funcionalidade, porque eu sei que posso testar tudo de novo em um instante. :D

Rails sem tdd? Nem a pau!

davi • 18 anos atrás

Excelente artigo, Nando... :-)

Estou usando isso e o Agile Web Development With Rails e estou gostando.

Mas eu vi uma coisa no livro que você não citou (para simplificar?), o Hash default_error_messages do ActiveRecord::Errors:

@@default_error_messages = {
:inclusion => "is not included in the list",
:exclusion => "is reserved",
:invalid => "is invalid",
:confirmation => "doesn't match confirmation",
:accepted => "must be accepted",
:empty => "can't be empty",
:blank => "can't be blank",
:too_long => "is too long (maximum is %d characters)",
:too_short => "is too short (minimum is %d characters)",
:wrong_length => "is the wrong length (should be %d characters)",
:taken => "has already been taken",
:not_a_number => "is not a number"
}

Eu coloquei o seguinte no meu RAILS_ROOT/test/test_helper.rb:

def assert_activerecord_errors(expected, got, message='')
assert_equal ActiveRecord::Errors.default_error_messages[expected], got, message
end

E agora posso testar as mensagens de erro usando um "simples" assert_activerecord_errors :taken, OBJECT.errors.on(:name).

Abraço

Nando Vieira • 18 anos atrás

@davi, como eu altero as mensagens-padrão do Rails através do atributo :messages, eu utilizo outra forma para validar tais mensagens. Dá uma olhada nos meus helpers[1], para ver como ficou!

[1] http://pastie.caboo.se/114671

Frolim • 17 anos atrás

Ficou muito bom!
Finalmente iniciei testes unitários com a sua explicação.
Vlw!

Eleudson • 17 anos atrás

Primeiro, parabéns pelo post que me fez encarar o uso de TDD.

Gostaria de tirar uma dúvida com algun de vocês que tenham utilizado os helpers sugeridos pelo Nando em http://pastie.caboo.se/114671. É o seguinte:

A) Quando utilizo a rotina da seguinte forma...

test "should_belongs_to_publication" do
publication = create
assert_associated publication, "editor"
end

... acontece a seguinte falha..

1) Failure: test_should_belongs_to_publication(ReviewTest)
[./test/test_helper.rb:93:in `assert_associated'
...
expected but was
<#>.

B) Quando ponho, na criação de publication, um publication_id que não existe, dá certo...

test "should_belongs_to_publication" do
publication = create(:publication_id => 100)
assert_associated publication, "editor"
end

Minha dúvida é se o uso correto é este mesmo da opção B ou tem algo errado?

Perdão por por esta dúvida aqui, é que não encontrei referencias sobre o uso destas rotinas na web.

Nando Vieira • 17 anos atrás

Eleudson, na documentação tem uma nota sobre isso. Validar a associação não significa que o objeto deve estar presente. Experimente adicionar também na sua validação algo como validates_presence_of :publication, :publication_id.

Eleudson • 17 anos atrás

O model está assim:
class Review true
validates_presence_of :body
end

A mensagem de erro do post anterior ficou incompleta, por isso a repito a seguir:
1) Failure:
test_should_belongs_to_publication(ReviewTest)
[./test/test_helper.rb:93:in `assert_associated'
./test/unit/review_test.rb:14:in `test_should_belongs_to_publication'
...
-nil- expected but was
Publication id: 1322847960, editor_id: 1050302101, title: "The great saga of Naruto", isbn: "333333-GHI", source: "www.manganiponweb.net", media: "DVD", idiom: "English", license: "Creative Common", created_at: "2009-02-20 17:50:01", updated_at: "2009-02-20 17:50:01"

Quando eu não ponho um publication_id que não existe, as mudanças deste campo dentro de assert_associated, exemplo record.send("#{attribute}=", nil), não faz mudar o valor de record.publication, que continua apontando para o objeto criado no metodo create. Daí, a assertiva assert_nil(record.send(relationship)) se torna falsa.

Pelo que você falou, tenho mesmo que criar um objeto sem referencia (ex. :publication_id => 100)?

A qual documentação você se refere?

Grato por sua atenção!

Eleudson • 17 anos atrás

Ops!! Model correto sem maior e menor que.

class Review ActiveRecord::Base
belongs_to :publication

validates_associated :publication
validates_presence_of :publication, :publication_id
validates_numericality_of :publication_id, :only_integer => true

validates_presence_of :body
end

Flávio Alves • 16 anos atrás

MUITO bom, Nando!
Parabéns e MUITO obrigado!
[]s

Luiz • 15 anos atrás

Nando, na criação das colunas não deveria ser " :null => false " ao invés de " :nil => false " ? Uso o MySQL e fez diferença, o :nil não fez cócegas nele.

Ao usar :null , logo no primeiro teste - !user.valid? - apareceu um erro e não uma falha como no seu resultado, já que o gerenciador do banco não permite a gravação, óbvio.

E as coisas não tomariam um caminho um pouco diferente da sua sequência a partir daí? Sou novato nessa área, estou aprendendo. Obrigado.

Nando Vieira • 15 anos atrás

Luiz, bem visto! Já atualizei o post.

Luiz • 15 anos atrás

Legal, Nando, só que a repercussão desse acerto, na prática do seu laboratório, criará a necessidade de outro(s) acerto(s) no seu post.

No segundo teste, quando se verifica se o usuário é "válido" executando o "User.create", com o banco configurado com aqueles campos para não aceitarem "null", a execução do teste acusaria um erro e não a falha que você mostrou. Com algum erro, o teste para. Acontece erro porque o gerenciador do banco não aceita salvar "null" nos campos em questão.

Seria muito legal se você refizesse a sequência do seu roteiro e atualizasse o post, pois esse seu material é um dos raros que encontrei na net que tenta ser o mais completo possível na demonstração da (boa) prática do TDD. Tenho encontrado só material incompleto, até mesmo o material do "Guides" nesse assunto é cheio de lacunas. Obrigado

Mateus • 15 anos atrás

Estou usando ubuntu, Rails 2.3.5, ruby 1.8.6 e ao seguir o tutorial ao chegar na criação do teste me foi criado o arquivo test/unit/user_test.rb com a seguinte classe:

"class UserTest < ActiveSupport::TestCase"

diferente da mostrada no tutorial que era class UserTest < Test::Unit::TestCase alguém pode me clarear? Thanks!

Mateus • 15 anos atrás

Também tive os mesmo problemas do amigo de cima, se você esta usando o mysql e colocando os campos como not null o desc do mysql fica assim:

http://pastebin.com/V3U8Cq9F

E ele não permite fazer uma inserção com 'nil' e da um Error não uma Failure no ActiveRecorder

Outra coisa que aconteceu aqui no metódo test_should_deny_duplicate_user é que ele não encontrou o metódo `assert_valid

cjapes • 14 anos atrás

Acho que me está a faltar algum testa na parte em que fazemos 8 testes… alguém pode enunciar os 8 testes?

Luiz • 14 anos atrás

Muito bom o posto parabens, vai me ajudar muito no TCC =)

Luiz Alberto Cattani • 11 anos atrás

post muito foda! Parabéns.

Jonas Elan • 9 anos atrás

Me ajudou muito, parabéns pelo trabalho, amigo!