Configurez RSpec pour tester un gem (pas Rails)

154

Il est assez facile avec le générateur ajouté de rspec-rails de configurer RSpec pour tester une application Rails. Mais que diriez-vous d'ajouter RSpec pour tester un bijou en développement? Je n'utilise pas de bijoutier ou de tels outils. Je viens d'utiliser Bundler ( bundle gem my_gem) pour configurer la structure du nouveau gem et éditer le * .gemspec manuellement. J'ai également ajouté s.add_development_dependency "rspec", ">= 2.0.0"à gemspec et fait un bundle install.

Existe-t-il un tutoriel intéressant, que faire ensuite pour que RSpec fonctionne?

Zardoz
la source
Je suppose que je dois en écrire un :-) ... Au moins il y a deux gemmes qui l'intègrent déjà bien: agit-as-taggable-on et actes_as_geocodable.
Zardoz

Réponses:

255

J'ai mis à jour cette réponse pour correspondre aux meilleures pratiques actuelles:

Bundler prend parfaitement en charge le développement de gemmes. Si vous créez une gemme, la seule chose que vous devez avoir dans votre Gemfile est la suivante:

source "https://rubygems.org"
gemspec

Cela indique à Bundler de rechercher dans votre fichier gemspec les dépendances lorsque vous exécutez bundle install.

Ensuite, assurez-vous que RSpec est une dépendance de développement de votre gemme. Modifiez le gemspec pour qu'il se lit comme suit:

spec.add_development_dependency "rspec"

Ensuite, créez spec/spec_helper.rbet ajoutez quelque chose comme:

require 'bundler/setup'
Bundler.setup

require 'your_gem_name' # and any other gems you need

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

Les deux premières lignes indiquent à Bundler de ne charger que les gemmes dans votre gemspec. Lorsque vous installez votre propre gemme sur votre propre machine, cela forcera vos spécifications à utiliser votre code actuel, pas la version que vous avez installée séparément.

Créez une spécification, par exemple spec/foobar_spec.rb:

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

Facultatif: ajoutez un .rspecfichier pour les options par défaut et placez-le dans le chemin racine de votre gem:

--color
--format documentation

Enfin: exécutez les spécifications:

$ rspec spec/foobar_spec.rb
iain
la source
75
Pour être juste, vous devriez plutôt appeler la commande init de RSpec pour générer les fichiers squelettes de spécifications plutôt que de les saisir manuellement. Cela assurerait la compatibilité avec la version de RSpec que vous utilisez: rspec --init
Attila Györffy
12
rspec --initn'était pas disponible quand j'ai écrit ceci, mais bon point!
iain
En fait, j'ai trouvé le meilleur moyen de faire les require dans l'assistant de spécification est le suivant: require 'rubygems' require 'bundler / setup' Bundler.require (: default
,:
Comment les trois lignes de code de @ mkon fonctionnent-elles différemment des trois lignes de code d'iain?
Nakilon
1
Les lignes de @mkon nécessiteront toutes les gemmes des groupes de développement et de test, tandis que mon approche consiste à exiger chaque gemme manuellement. Étant donné que vous devez avoir besoin de chaque bijou vous-même lorsque vous fabriquez des gemmes, je pense que c'est l'approche la meilleure / la plus claire, même si cela demande un peu plus de travail.
iain du
53

La solution d'Iain ci-dessus fonctionne très bien!

Si vous voulez également un Rakefile, c'est tout ce dont vous avez besoin:

require 'rspec/core/rake_task'

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

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

Vérifiez le RDoc pour RakeTask pour diverses options que vous pouvez éventuellement passer dans la définition de tâche.

Mirko Froehlich
la source
26

Vous pouvez générer votre nouvelle gemme avec rspec en exécutant bundler gem --test=rspec my_gem. Aucune configuration supplémentaire!

J'oublie toujours ça. Il est mis en œuvre ici: https://github.com/bundler/bundler/blob/33d2f67d56fe8bf00b0189c26125d27527ef1516/lib/bundler/cli/gem.rb#L36

StevenNunez
la source
1
Soigné! Cependant, je pense que le nom de votre gemme devrait être spécifié avec des traits de soulignement au lieu d'un étui de chameau. Sinon, Bundler crée des fichiers avec des lettres majuscules (Bundler 1.7.4)
Malte
Bundler s'est plaint --test=rspec, mais il m'a quand même demandé si je voulais utiliser Rspec lorsque je courais bundler gem my_gem.
Nicolas Mattia
7

Voici un moyen bon marché et facile (mais pas officiellement recommandé):

Faites un répertoire dans la racine de votre gemme appelé spec, mettez vos spécifications là-dedans. Vous avez probablement déjà installé rspec, mais si vous ne le faites pas, faites simplement un gem install rspecet oubliez Gemfiles et bundler.

Ensuite, vous allez créer une spécification, et vous devez lui indiquer où se trouve votre application, où se trouvent vos fichiers et inclure le fichier que vous souhaitez tester (ainsi que toutes les dépendances dont il dispose):

# 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

Ouvrez le Terminal et exécutez rspec:

~/awesome_gem $ rspec
..

Finished in 0.56 seconds
2 examples, 0 failures

Si vous voulez .rspecaimer certaines options, allez créer un .rspecfichier et placez-le dans le chemin racine de votre gemme. Le mien ressemble à ceci:

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

Facile, rapide, soigné!

J'aime cela parce que vous n'avez pas du tout à ajouter de dépendances à votre projet, et le tout reste très rapide. bundle execralentit un peu les choses, ce que vous devez faire pour vous assurer que vous utilisez la même version de rspec tout le temps. Ces 0,56 secondes qu'il a fallu pour exécuter deux tests ont été prises à 99% au moment où il a fallu à mon ordinateur pour charger rspec. L'exécution de centaines de spécifications devrait être extrêmement rapide. Le seul problème que vous pourriez rencontrer et dont je suis conscient est que si vous changez de version de rspec et que la nouvelle version n'est pas rétrocompatible avec une fonction que vous avez utilisée dans votre test, vous devrez peut-être réécrire certains tests.

C'est bien si vous faites des spécifications ponctuelles ou si vous avez une bonne raison de NE PAS inclure rspec dans votre gemspec, mais ce n'est pas très bon pour activer le partage ou appliquer la compatibilité.

wulftone
la source
Existe-t-il un moyen de ne pas mettre AwesomeGem :: avant les noms de classe chaque fois que vous faites référence à un objet de test? Ou lorsque vous créez un nouveau test comme dans votre exemple.
Misha Slyusarev
1
Bien sûr, vous pouvez soit définir le nom de votre classe sur quelque chose de plus court, comme Thing = AwesomeGem::Awesomeou vous pouvez faire le test à l'intérieur d'un module, commemodule AwesomeGem; it 'stuff' do; Awesome.new ... end; end
wulftone