Configure o RSpec para testar uma gema (não o Rails)

154

É muito fácil, com o gerador adicionado de rspec-rails, configurar o RSpec para testar um aplicativo Rails. Mas que tal adicionar o RSpec para testar uma jóia no desenvolvimento? Eu não estou usando joalheiro ou tais ferramentas. Acabei de usar o Bundler ( bundle gem my_gem) para configurar a estrutura da nova gema e editar o * .gemspec manualmente. Eu também adicionei s.add_development_dependency "rspec", ">= 2.0.0"ao gemspec e fiz a bundle install.

Existe algum tutorial interessante sobre o que fazer a seguir para que o RSpec funcione?

Zardoz
fonte
Eu acho que tenho que escrever um :-) ... Pelo menos existem duas jóias que já o integram muito bem: age como taggable-on e act_as_geocodable.
Zardoz

Respostas:

255

Atualizei esta resposta para corresponder às práticas recomendadas atuais:

Bundler suporta perfeitamente o desenvolvimento de gemas. Se você estiver criando uma gema, a única coisa que você precisa ter no seu Gemfile é a seguinte:

source "https://rubygems.org"
gemspec

Isso diz ao Bundler para procurar dentro do seu arquivo gemspec as dependências quando você executar bundle install.

Em seguida, verifique se o RSpec é uma dependência de desenvolvimento da sua gema. Edite o gemspec para que ele leia:

spec.add_development_dependency "rspec"

Em seguida, crie spec/spec_helper.rbe adicione algo como:

require 'bundler/setup'
Bundler.setup

require 'your_gem_name' # and any other gems you need

RSpec.configure do |config|
  # some (optional) config here
end

As duas primeiras linhas dizem ao Bundler para carregar apenas as gemas dentro do seu gemspec. Quando você instala sua própria joia em sua própria máquina, isso forçará suas especificações a usar seu código atual, não a versão que você instalou separadamente.

Crie uma especificação, por exemplo spec/foobar_spec.rb:

require 'spec_helper'
describe Foobar do
  pending "write it"
end

Opcional: adicione um .rspecarquivo para as opções padrão e coloque-o no caminho raiz da sua jóia:

--color
--format documentation

Finalmente: execute as especificações:

$ rspec spec/foobar_spec.rb
iain
fonte
75
Para ser justo, você deve invocar o comando init do RSpec para gerar os arquivos de esqueleto de especificações em vez de precisar digitá-los manualmente. Isso garantiria compatibilidade com a versão do RSpec que você está usando: rspec --init
Attila Györffy
12
rspec --initnão estava disponível quando eu escrevi isso, mas bom ponto!
30512 iain
Na verdade, eu encontrei a melhor maneira de fazer o exige na helper especificação é esta: require 'rubygems' exigem 'bundler / setup' Bundler.require (: padrão,: Desenvolvimento)
mkon
Como exatamente as três linhas de código do @ mkon funcionam de maneira diferente das três linhas de código do iain?
Nakilon
1
As linhas do @mkon exigirão todas as gemas nos grupos de desenvolvimento e teste, enquanto minha abordagem é exigir todas as gemas manualmente. Como você precisa exigir todas as pedras preciosas ao fazer gemas, acho que é a abordagem melhor / mais clara, embora possa ser um pouco mais trabalhoso.
iain
53

A solução de Iain acima funciona muito bem!

Se você também deseja um Rakefile, é tudo o que precisa:

require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new(:spec)

# If you want to make this the default task
task default: :spec

Verifique o RDoc do RakeTask para obter várias opções que você pode opcionalmente passar para a definição da tarefa.

Mirko Froehlich
fonte
26

Você pode gerar sua nova gema com o rspec executando bundler gem --test=rspec my_gem . Nenhuma configuração adicional!

Eu sempre esqueço isso. É implementado aqui: https://github.com/bundler/bundler/blob/33d2f67d56fe8bf00b0189c26125d27527ef1516/lib/bundler/cli/gem.rb#L36

StevenNunez
fonte
1
Arrumado! No entanto, acho que o nome da sua gema deve ser especificado com sublinhados em vez de caixa de camelo. Caso contrário, o Bundler cria arquivos com letras maiúsculas (Bundler 1.7.4)
Malte
Bundler reclamou --test=rspec, mas ainda me perguntou se eu queria usar o Rspec quando corria bundler gem my_gem.
Nicolas Mattia
7

Aqui está uma maneira barata e fácil (embora não oficialmente recomendada):

Faça um dir na raiz da sua gema chamada spec, coloque suas especificações lá. Você provavelmente já possui o rspec instalado, mas se não o fizer, faça um gem install rspece esqueça o Gemfiles e o bundler.

Em seguida, você fará uma especificação e precisará informar onde está seu aplicativo, onde estão seus arquivos e incluir o arquivo que deseja testar (junto com todas as dependências existentes):

# spec/awesome_gem/awesome.rb
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
$: << File.join(APP_ROOT, 'lib/awesome_gem') # so rspec knows where your file could be
require 'some_file_in_the_above_dir' # this loads the class you want to test

describe AwesomeGem::Awesome do
  before do
    @dog = AwesomeGem::Awesome.new(name: 'woofer!')
  end
  it 'should have a name' do
    @dog.name.should eq 'woofer!'
  end
  context '#lick_things' do
    it 'should return the dog\'s name in a string' do
      @dog.lick_things.should include 'woofer!:'
    end
  end
end

Abra o Terminal e execute o rspec:

~/awesome_gem $ rspec
..

Finished in 0.56 seconds
2 examples, 0 failures

Se você quer algumas .rspecopções, crie um .rspecarquivo e coloque-o no caminho raiz da sua jóia. O meu fica assim:

# .rspec
--format documentation --color --debug --fail-fast

Fácil, rápido, limpo!

Eu gosto disso porque você não precisa adicionar nenhuma dependência ao seu projeto e a coisa toda permanece muito rápida. bundle execdiminui um pouco as coisas, e é isso que você precisa fazer para garantir que você esteja usando a mesma versão do rspec o tempo todo. Aqueles 0,56 segundos necessários para executar dois testes foram 99% utilizados no momento em que meu computador levou para carregar o rspec. A execução de centenas de especificações deve ser extremamente rápida. O único problema em que você pode se deparar é que, se você alterar as versões do rspec e a nova versão não for compatível com algumas funções usadas em seu teste, talvez seja necessário reescrever alguns testes.

Isso é bom se você estiver executando especificações únicas ou tiver algum bom motivo para NÃO incluir o rspec no seu gemspec, no entanto, não é muito bom para ativar o compartilhamento ou reforçar a compatibilidade.

wulftone
fonte
Existe uma maneira de não colocar AwesomeGem :: antes dos nomes das classes sempre que você se referir a um objeto de teste? Ou quando você cria um novo teste como no seu exemplo.
Misha Slyusarev 02/07/19
1
Claro, você pode definir o nome da sua classe como algo menor, como Thing = AwesomeGem::Awesome ou você pode fazer o teste dentro de um módulo, comomodule AwesomeGem; it 'stuff' do; Awesome.new ... end; end
wulftone