Skip to content
fevereiro 6, 2010 / cassiomarques

Criando example groups personalizados no Rspec

Quem usa o Rspec com o Rails sabe que existem alguns tipos de specs pré-definidos. Estes tipos de spec são chamados de ‘example groups’ e no Rails são associados aos tipos de classe que visam testar. Temos então o ‘models example group’, o ‘controller example group’, etc. Para cada grupo, o Rspec (e mais precisamente o rspec-rails) cuida de incluir alguns helpers específicos, além de dar ao desenvolvedor a change de incluir seus próprios helpers e macros, criar hooks para executar código antes ou depois da execução de cada exemplo, etc. Tudo isso de forma controlada, para tipos de specs específicos.

Por exemplo, se você escreveu um conjunto de macros e helpers para as specs dos seus models, você poderia simplesmente colocar todo mundo em um arquivo e fazer um require disso no seu spec_helper.rb. O problema disso é que, além de feio e bagunçado, estes helpers e macros de model ficariam também disponíveis para as specs de controllers, views, helpers, etc. Então para organizar as coisas, podemos alterar nosso spec_helper.rb e adicionar o seguinte no bloco do método Spec::Runner.configure:

require 'spec/my_cool_model_macros'

Spec::Runner.configure do |config|
  config.include(MyCoolModelMacros, :type => :model)
end

e todas as macros definidas no seu module MyCoolModelMacros estariam disponíveis nas suas specs, mas somente para models!

Além de poder incluir novos modules de forma contralada, também é possível usar este recurso para executar código antes ou depois de cada exemplo, mas somente para exemplos que façam parte de um example group específico:

Spec::Runner.configure do |config|
  config.before(:each, :behaviour_type => :controller) do
    # ...
  end
end

Isso executará o código dentro do bloco config.before antes de cada exemplo executado, mas somente nas suas specs de controllers.

Legal, isso já me dá bastante controle e flexibilidade. Mas e se eu quiser criar meus próprios example groups? Considere o meu caso por exemplo: Eu tenho uma aplicação Rails com um banco próprio mas que também precisa acessar uma base legada. Para rodar os testes, eu tenho uma cópia dessa base legada, mas só com a estrutura, sem dados. Exatamente como ocorre com a base de dados de teste padrão do Rails. A cada novo exemplo, preciso limpar todos os dados criados nessa base legada de teste para poder preparar o próximo cenário. É óbvio que seria perda de tempo ficar limpando essa base legada para todos os exemplos, mesmo aqueles que não tem relação alguma com as partes do código que acessam este outro banco. Para isso, podemos criar um exemple group específico e limitar a funcionalidade.

Como dito anteriormente, o rspec-rails já possui alguns example groups pré-definidos. O problema de criar um exemple group totalmente novo é que se a sua spec for referente a um model, você não terá acesso a todos aqueles helpers e macros bacanas que existem em uma spec de model normal dentro de sua aplicação Rails. Por isso, ao invés de criar do zero, vamos aproveitar o que o rspec-rails já fornece.

Normalmente, para criar um novo example group basta criarmos uma nova classe que herde de Spec::Example::ExampleGroup (na verdade isso já acontece por baixo dos panos toda vez que você cria um bloco describe()) e dentro dessa classe registrar o nosso novo tipo. Algo mais ou menos assim:

class MyCustomExampleGroup < Spec::Example::ExampleGroup
  Spec::Example::ExampleGroupFactory.register(:foobar, self) 
end

Com isso ganhamos um novo example group :foobar e podemos associar nossas specs ao mesmo. Uma vez feito isso, fica fácil configurarmos o Rspec para executar código de forma restrita às specs que pertencem a este grupo, como descrito acima.

O rspec-rails fornece alguns example groups a partir dos quais podemos derivar nossas próprias classes.

  • Spec::Rails::Example::ModelExampleGroup para models
  • Spec::Rails::Example::ControllerExampleGroup para controllers
  • Spec::Rails::Example::HelperExampleGroup para helpers
  • Spec::Rails::Example::ViewExampleGroup para views

Para não perder nenhuma das facilidades do rspec-rails, vamos herdar desses example groups, ao invés de herdar do ExampleGroup padrão do Rspec.

class MyCrazyModelExampleGroup < Spec::Rails::Example::ModelExampleGroup
  Spec::Example::ExampleGroupFactory.register(:crazy_stuff, self) 
end

Já temos nosso example group e já sabemos como específicar configurações para nossas specs que valem somente para testes dos models. Mas e como definir quais specs farão parte do grupo :crazy_stuff? Simples:

describe MyModel, :type => :crazy_stuff do
  #...
end 

2 Comentários

Deixe um comentário
  1. Daniel Lopes / fev 10 2010 4:37 pm

    Muito bom, como sempre.

    Eu uso o before global em sistemas que precisam de coisas como current_account em todos os controllers.

    • cassiomarques / fev 10 2010 4:52 pm

      Mas neste caso ele vai passar por esse before global para os testes dos models também, não?

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: