Como vocês fazem o "describe" das suas specs?

Isso pra mim sempre foi uma dúvida ao usar o rspec. Realmente não há forma correta. É uma opção pessoal no caso de um projeto particular ou de decisão em conjunto no caso de um projeto onde vários desenvolvedores participam.

Mas o fato é que eu nunca adotei nenhum padrão para isso. É uma coisa que tem me deixado um pouco incomodado. Em alguns modelos sigo o padrão de um describe para cada método, em outros segui padrões ligeiramente diferentes, como por exemplo testes relacionados a attributos em um describe, relacionamentos em outro describe e assim por diante. Ou seja, não há padrão. Há tempos atrás ouvi uma frase que nunca esqueci:

Quando dois padrões existem, não há padrão.

No Lucidus usávamos Test::Unit(quando o projeto começou o rspec ainda era muito pouco difundido) então o “padrão” para nós era pelo menos colocar os testes relativos juntos. Então os testes relativos a um mesmo método normalmente estavam juntos, em um “bloco”, um abaixo do outro. O rspec nos permite um pouco mais de organização. Mas fazer essa organização extra através dos describes proporciona algum benefício?

Então seguindo a idéia… nós precisamos discutir testes.

Qual opnião de vocês? Como vocês organizam seus describes? E o que vocês escrevem nele?

3 comentários : 28.11.2008 03:18 AM

Um "setup" global para todas as suas specs

Ficou bem difundido no rspec a forma em como fazer o setup antes das specs executarem, assim como existe também no Test::Unit.

describe Act do
  before(:each) do
    (...)
  end

  it "should have many persons associated" do
   (...)
  end
end

Eu estava precisando fazer o setup para todas as minhas specs (do planeta :), então descobri uma forma que está mal documentada(pelo menos eu não achei bom), mas é super simples de usar. É só editar o spec/spec_helper.rb e adicionar dentro do bloco:

Spec::Runner.configure do |config|
  (...)
end

O seguinte:

config.before(:each) do
  your_global_setup_here
end

Você também pode executar o setup somente para os controllers, models ou helpers assim:

config.before(:each, :behaviour_type => :controller) do
  your_global_controllers_setup_here
end

Ou

config.before(:each, :behaviour_type => :helper) do
  your_global_helpers_setup_here
end

Ou

config.before(:each, :behaviour_type => :model) do
  your_global_models_setup_here
end

Como se chama o “setup” no bdd? É setup mesmo?

4 comentários : 27.11.2008 02:50 AM

Fazendo o will_paginate traduzir o "Previous" e "Next"

Eu precisei traduzir para várias línguas os links de “Previous” e “Next” do will_paginate, mas não seria nada dry passar os parâmetros em todas as chamadas a will_paginate(). Outra solução seria criar um método helper que faria a chamada ao will_paginate() passando os parâmetros e nas minhas views eu chamaria esse helper no lugar de chamar will_paginate(). O problema é que sempre que fosse criada uma nova tela com paginação a pessoa teria que lembrar de chamar o método helper e não chamar o will_paginate() diretamente.

Então pra mim a melhor solução foi criar uma extensão, que deixa tudo transparente. Eu coloquei em /lib dentro do projeto rails.

module WillPaginate
  module ViewHelpers
    def will_paginate_with_translate(collection = nil, options = {})
      options, collection = collection, nil if collection.is_a? Hash
      options.merge!(:prev_label => _("« Previous"), :next_label => _("Next »"))

      if collection
        will_paginate_without_translate(collection, options)
      else
        will_paginate_without_translate(options)
      end
    end
    alias_method_chain :will_paginate, :translate
  end
end

O método _() que é chamado é o método que faz a tradução no plugin de localização que estou utilizando, você deve alterar para a forma como você faz a localização no seu projeto. Também criei as specs para assegurar o funcionamento:

require File.dirname(__FILE__) + '/../spec_helper'

describe WillPaginate::ViewHelpers do
  describe "will_paginate translations" do
    before(:each) do
      @expected = 'paginate_mock'
      @model = mock('model-mock')

      @translation_options = {:prev_label => _("« Previous"), :next_label => _("Next »")}
      @options = {:option1 => '1', :option2 => '2', :next_label => 'next-fake'}
    end

    it "should will_paginate only with translations" do
      helper.should_receive(:will_paginate_without_translate).with(@translation_options).and_return(@expected)
      helper.will_paginate == @expected
    end

    it "should will_paginate with @model parameter" do
      helper.should_receive(:will_paginate_without_translate).with(@model, @translation_options).and_return(@expected)
      helper.will_paginate(@model) == @expected
    end

    it "should will_paginate with @model parameter and options" do
      helper.should_receive(:will_paginate_without_translate).with(@model, @options.merge(@translation_options)).and_return(@expected)
      helper.will_paginate(@model, @options) == @expected
    end
  end
end

Espero que seja útil para alguém ;)

4 comentários : 24.11.2008 12:52 PM

Palestra Utilizando Ruby com Bluetooth

Na semana passada eu apresentei no Latinoware a palestra “Utilizando Bluetooth com Ruby: A forma mais fácil de programar com Bluetooth”. Foi um sucesso total, a sala estava lotada e o pessoal se amarrou nas demonstrações ao vivo.

Coloquei os downloads na seção de artigos.

1 comentário : 07.11.2008 08:22 PM