Skonfiguruj RSpec, aby przetestować gem (nie Rails)

154

Dzięki dodanemu generatorowi rspec-rails skonfigurowanie RSpec do testowania aplikacji Rails jest całkiem proste. Ale co powiesz na dodanie RSpec do testowania perełki w rozwoju? Nie używam jubilera ani takich narzędzi. Właśnie użyłem Bundler ( bundle gem my_gem), aby ustawić strukturę dla nowego klejnotu i ręcznie edytować * .gemspec. Dodałem również s.add_development_dependency "rspec", ">= 2.0.0"do gemspec i zrobiłem bundle install.

Czy jest jakiś fajny poradnik, co dalej zrobić, aby RSpec działał?

Zardoz
źródło
Chyba muszę jeden napisać :-) ... Przynajmniej są dwa perełki, które już ładnie go integrują: act-as-taggable-on i act_as_geocodable.
Zardoz,

Odpowiedzi:

255

Zaktualizowałem tę odpowiedź, aby była zgodna z aktualnymi sprawdzonymi metodami:

Bundler doskonale obsługuje rozwój klejnotów. Jeśli tworzysz klejnot, jedyne , co musisz mieć w swoim Gemfile, to:

source "https://rubygems.org"
gemspec

Mówi to Bundlerowi, aby po uruchomieniu zajrzał do pliku gemspec w poszukiwaniu zależności bundle install.

Następnie upewnij się, że RSpec jest zależnością programistyczną twojego klejnotu. Edytuj gemspec tak, aby brzmiał:

spec.add_development_dependency "rspec"

Następnie utwórz spec/spec_helper.rbi dodaj coś takiego:

require 'bundler/setup'
Bundler.setup

require 'your_gem_name' # and any other gems you need

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

Pierwsze dwie linijki mówią Bundlerowi, aby załadował tylko klejnoty z twojego gemspec. Kiedy zainstalujesz swój własny klejnot na własnym komputerze, zmusi to twoje specyfikacje do użycia twojego obecnego kodu, a nie wersji, którą zainstalowałeś oddzielnie.

Utwórz specyfikację, na przykład spec/foobar_spec.rb:

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

Opcjonalnie: dodaj .rspecplik z domyślnymi opcjami i umieść go w ścieżce głównej twojego klejnotu:

--color
--format documentation

Na koniec: uruchom specyfikacje:

$ rspec spec/foobar_spec.rb
iain
źródło
75
Aby być uczciwym, powinieneś zamiast tego wywołać polecenie init RSpec w celu wygenerowania plików szkieletu specyfikacji, zamiast konieczności ręcznego wpisywania ich. Zapewniłoby to zgodność z wersją RSpec, której używasz: rspec --init
Attila Györffy
12
rspec --initnie było dostępne, kiedy to pisałem, ale słuszna uwaga!
innymi
Właściwie znalazłem najlepszy sposób na spełnienie wymagań w pomocniku specyfikacji: Wymagaj 'rubygems' wymaga 'bundler / setup' Bundler.require (: default
,:
Jak dokładnie trzy wiersze kodu @ mkon działają inaczej niż trzy wiersze kodu iain?
Nakilon
1
Linie z @mkon będą wymagały wszystkich klejnotów w grupach deweloperskich i testowych, podczas gdy moje podejście polega na ręcznym wymaganiu każdego klejnotu. Ponieważ podczas tworzenia klejnotów musisz samodzielnie wymagać każdego klejnotu, myślę, że jest to lepsze / jaśniejsze podejście, nawet jeśli może to wymagać trochę więcej pracy.
innymi
53

Powyższe rozwiązanie Iaina działa świetnie!

Jeśli chcesz również Rakefile, to wszystko, czego potrzebujesz:

require 'rspec/core/rake_task'

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

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

Sprawdź RDoc dla RakeTask pod kątem różnych opcji, które możesz opcjonalnie przekazać do definicji zadania.

Mirko Froehlich
źródło
26

Możesz wygenerować swój nowy klejnot za pomocą rspec, uruchamiając bundler gem --test=rspec my_gem. Bez dodatkowej konfiguracji!

Zawsze o tym zapominam. Jest zaimplementowany tutaj: https://github.com/bundler/bundler/blob/33d2f67d56fe8bf00b0189c26125d27527ef1516/lib/bundler/cli/gem.rb#L36

StevenNunez
źródło
1
Schludny! Uważam jednak, że nazwa klejnotu powinna być oznaczona podkreśleniami zamiast wielkością wielbłąda. W przeciwnym razie Bundler tworzy pliki z dużymi literami (Bundler 1.7.4)
Malte
Bundler narzekał --test=rspec, ale nadal pytał mnie, czy chcę używać Rspec, kiedy biegałem bundler gem my_gem.
Nicolas Mattia
7

Oto tani i łatwy (choć oficjalnie niezalecany) sposób:

Zrób katalog w katalogu głównym swojego klejnotu o nazwie spec, umieść tam swoje specyfikacje. Prawdopodobnie masz już zainstalowany rspec, ale jeśli nie, po prostu zrób gem install rspeci zapomnij o Gemfiles i bundlerze.

Następnie stworzysz specyfikację i musisz powiedzieć, gdzie jest twoja aplikacja, gdzie są twoje pliki i dołączyć plik, który chcesz przetestować (wraz z wszelkimi zależnościami, które ma):

# 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

Otwórz Terminal i uruchom rspec:

~/awesome_gem $ rspec
..

Finished in 0.56 seconds
2 examples, 0 failures

Jeśli chcesz, aby niektóre .rspecopcje były miłe, zrób .rspecplik i umieść go w ścieżce głównej swojego klejnotu. Mój wygląda tak:

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

Łatwo, szybko, schludnie!

Podoba mi się to, ponieważ nie musisz w ogóle dodawać żadnych zależności do swojego projektu, a całość działa bardzo szybko. bundle exectrochę spowalnia działanie, co musisz zrobić, aby mieć pewność, że cały czas używasz tej samej wersji rspec. To 0,56 sekundy, które zajęło wykonanie dwóch testów, było w 99% zajęte przez załadowanie rspec przez mój komputer. Uruchomienie setek specyfikacji powinno być niezwykle szybkie. Jedyny problem, na jaki możesz się natknąć, o którym wiem, to to, że jeśli zmienisz wersje rspec, a nowa wersja nie jest wstecznie kompatybilna z jakąś funkcją, której użyłeś w teście, może być konieczne ponowne napisanie niektórych testów.

Jest to fajne, jeśli robisz jednorazowe specyfikacje lub masz dobry powód, aby NIE włączać rspec do swojego gemspec, jednak nie jest zbyt dobre do włączania udostępniania lub wymuszania zgodności.

wulftone
źródło
Czy istnieje sposób, aby nie umieszczać AwesomeGem :: przed nazwami klas za każdym razem, gdy odwołujesz się do obiektu testowego? Lub kiedy tworzysz nowy test, jak w swoim przykładzie.
Misha Slyusarev
1
Jasne, możesz albo ustawić nazwę swojej klasy na coś krótszego, na przykład, Thing = AwesomeGem::Awesomealbo możesz przeprowadzić test wewnątrz modułu, na przykładmodule AwesomeGem; it 'stuff' do; Awesome.new ... end; end
wulftone