2011-11-04 4 views
15

Napisałem prostą metodę klasy Buy.get_days(string) i próbuję ją przetestować z różnymi wejściami tekstowymi. Jednak uważam, że jest bardzo gadatliwy.Jak testować metody klasy w RSPEC

  • Czy istnieje jakiś bardziej zwięzły sposób na sprawdzenie następujących elementów?
  • Czy istnieje odpowiednik subject dla metod, które mogę po prostu przekazać różnych parametrów i sprawdzić wyniki?
  • Czy istnieje sposób na uniknięcie niepotrzebnego opisu w każdym it?

dzięki

describe Buy do 
    describe '.get_days' do 
    it 'should get days' do 
     Buy.get_days('Includes a 1-weeknight stay for up to 4 people') 
     .should == 1 
     end 
    it 'should get days' do 
     Buy.get_days('Includes a 1-night stay in a King Studio Room with stone fireplace') 
     .should == 1 
    end 
    it 'should get days' do 
     Buy.get_days('Includes 4 nights/5 days at the Finisterra Hotel for up to two adults and two children (staying in the same room)') 
     .should == 4 
    end 
    end 
end 
+4

Jak jest niepotrzebny opis "to"? Tylko dlatego, że napisałeś ten sam tekst dla specyfikacji, które testują różne rzeczy, nie oznacza, że ​​opis nie powinien tam być - może możesz ponownie je sformułować, aby były przydatne? –

+0

kombinacja wejścia/wyjścia jest wystarczająco opisowa (przynajmniej dla mnie). – lulalala

+0

możesz podać przykład przeformułowania, aby był bardziej przydatny, @DaveNewton? – ahnbizcad

Odpowiedz

3

This to interesujący, ale być może bardziej rozwlekły sposób użycia bloku "przedmiot" przy użyciu metod klasy.

Edycja: Zepsuta link zgłoszona przez archiwum Wayback, która, jak przypuszczam, jest podatna na ten sam problem.

+1

[uszkodzony link] (http://posterous.timocracy.com/a-pattern-for-testing-class-methods-in-ruby-w) mówi "Posterous Spaces nie jest już dostępny" –

+0

@ JaredBeck edytowane. Podsumuję dzisiejszą odpowiedź. – TCopple

+0

Treść jest również dostępna jako ogólna: https://gist.github.com/timocratic/816049 – aingram

11

nie ma subject ekwiwalent za wywołanie metody, więc korzystanie it jest do zrobienia tutaj. Problem, który widzę z przedstawionym kodem, jest taki, że nie wyjaśnia on, co testujesz. Napisałbym coś bardziej podobnego:

describe Buy do 
    describe '.get_days' do 
    it 'should detect hyphenated weeknights' do 
     Buy.get_days('Includes a 1-weeknight stay for up to 4 people').should == 1 
    end 
    it 'should detect hyphenated nights' do 
     Buy.get_days('Includes a 1-night stay in a King Studio Room with stone fireplace').should == 1 
    end 
    it 'should detect first number' do 
     Buy.get_days('Includes 4 nights/5 days at the Finisterra Hotel for up to two adults and two children (staying in the same room)').should == 4 
    end 
    end 
end 

Podejmuję założenia dotyczące tego, o co tu chodzi, ale mam nadzieję, że pomysł jest jasny. Doprowadzi to również do znacznie bardziej użytecznego wyjścia błędu, gdy test się nie powiedzie. Mam nadzieję że to pomoże!

+0

Podejrzewam, że odpowiedź na końcu brzmi: nie ma bardziej zwięzłego sposobu jej napisania. – lulalala

+0

Tak, boję się. :) –

+0

@lulalala Nie chcesz *, żeby był zwięzły, chcesz, aby był dokładny i opisowy w kontekście specyfikacji. –

0

Alternatywą korzystania subject/it jest użycie before/specify:

describe '#destroy' do 
    context 'with children' do 
    before { @parent = FactoryGirl.create(:parent, children: FactoryGirl.create_list(:child, 2) } 
    specify { @parent.destroy.should be_false } 
    end 
end 

To będzie produkować wystarczającą opis w formacie -fd wyjściowego rspec za:

#destroy 
    with children 
    should be false 
5

To może być stary pytanie ale zawsze możesz użyć subject.class, aby uzyskać:

describe Buy do 
    describe '.get_days' do 
    it { expect(subject.class.get_days('Includes a 1-weeknight stay for up to 4 people')).to eq 1 } 
    end 
end 
+0

Dobry połów ! facepalm. Powinienem to wiedzieć. To jest poprawna odpowiedź! – ahnbizcad

+1

'subject.class'? Czy nie byłoby lepiej użyć opcji "Kup"? –

+0

@ahnbizcad Niezupełnie, ponieważ pokazuje tylko jeden test. Pomyśl o wynikach specyfikacji i o tym, co powinna pokazywać. Dodanie innych testów bez testów opisowych powoduje, że dane wyjściowe są zasadniczo bezużyteczne, ponieważ nie wiesz (a) o tym, co testuje specyfikacja, oraz (b) jakie są różne specyfikacje. –

7

Najwyraźniej istnieje metoda described_class.

https://www.relishapp.com/rspec/rspec-core/docs/metadata/described-class

Przypuszczam, że to czystsze niż subject.class, ponieważ nie wprowadza kolejną rozmowę . metoda, która zmniejsza czytelność.

Używanie albo described_class, albo może być bardziej SUCHE niż wymienianie klasy jawnie w każdym przykładzie. Ale osobiście uważam, że nieskładanie podświetlania składni, które towarzyszy wymienianiu nazwy klasy, jest pewnego rodzaju uciążliwością i myślę, że zmniejsza to czytelność, mimo że całkowicie wygrywa w dziale łatwości obsługi.

Powstaje pytanie dotyczące najlepszych praktyk:

należy użyć described_class miarę możliwości na zewnątrz i wewnątrz metody .expect(), czy tylko w ramach metody expect()?

+0

To jest to, co wolę używać w moich testach, pozostawiając przedmiot dla danych testowanych za pomocą wspomnianych metod. – DBrown