Come affermare il numero di elementi utilizzando Capybara con un messaggio di errore appropriato?


86

So che in Capybara puoi fare qualcosa del genere:

page.should have_css("ol li", :count => 2)

Tuttavia, supponendo che la pagina abbia ad esempio un solo elemento corrispondente, l'errore non è molto descrittivo:

  1) initial page load shows greetings
 Failure/Error: page.should have_css("ol li", :count => 2)
 expected css "ol li" to return something

Invece di questo messaggio di errore piuttosto oscuro, c'è un modo per scrivere l'asserzione in modo tale che l'output dell'errore sia qualcosa del tipo "Quando corrisponde a" ol li ", atteso: 2, trovato: 1". Ovviamente potrei creare io stesso una logica personalizzata per un tale comportamento: sto chiedendo: c'è un modo per farlo "fuori dagli schemi"?

Per quello che vale, sto usando il driver Selenium e RSpec.


Solo per far sapere alle persone, "page.should have_css (" ol li ",: count => 2)" è stato implementato in capybara. Penso che sia altamente utilizzabile con gli scope: all'interno di ("ol.users-list") do page.should have_css ('li',: count => 3) end
rafaelkin

@rafaelkin, solo per chiarire: ora capibara segnala, ad esempio, la mancata corrispondenza dell'elemento con maggiore dettaglio? Non seguo capibara da un po 'di tempo, ma il problema all'epoca quando ho posto la domanda riguardava il formato del messaggio di errore, non che page.should have_css("ol li", :count => 2)non sarebbe stato già implementato.
Merryprankster

gente, ho la sensazione che la risposta attualmente accettata (= la mia) non sia più la migliore, ma non ho il tempo (non lavoro più con Ruby) per valutare quale delle soluzioni suggerite è la migliore. Cambierò la risposta accettata a quella di Richard solo perché include l'output dell'asserzione che affronta il problema originale.
Merryprankster

Risposte:



22

Bene, poiché sembra che non ci sia supporto immediato, ho scritto questo matcher personalizzato:

RSpec::Matchers.define :match_exactly do |expected_match_count, selector|
    match do |context|
        matching = context.all(selector)
        @matched = matching.size
        @matched == expected_match_count
    end

    failure_message_for_should do
        "expected '#{selector}' to match exactly #{expected_match_count} elements, but matched #{@matched}"
    end

    failure_message_for_should_not do
        "expected '#{selector}' to NOT match exactly #{expected_match_count} elements, but it did"
    end
end

Ora puoi fare cose come:

describe "initial page load", :type => :request do
    it "has 12 inputs" do
        visit "/"
        page.should match_exactly(12, "input")
    end
end

e ottieni un output come:

  1) initial page load has 12 inputs
     Failure/Error: page.should match_exactly(12, "input")
       expected 'input' to match exactly 12 elements, but matched 13

Per ora fa il trucco, cercherò di realizzare questa parte di Capybara.


Sembra che risolvere questo problema in Capybara non sia semplice: github.com/jnicklas/capybara/issues/331
merryprankster

14

Penso che quanto segue sia più semplice, fornisce un output abbastanza chiaro ed elimina la necessità di un abbinamento personalizzato.

page.all("ol li").count.should eql(2)

Questo quindi viene stampato in caso di errore:

      expected: 2
       got: 3

  (compared using eql?)
  (RSpec::Expectations::ExpectationNotMetError)

9
Questo non aspetta che l'aspettativa si avveri, ad esempio quando ci sono ancora richieste ajax in sospeso.
Clemens Helm

9

Modifica: come sottolineato da @ThomasWalpole, utilizzandoall disabilita l'attesa / Capybara, quindi la risposta sopra di @pandaPower è molto migliore.

Cosa ne pensi di questo?

  within('ol') do
    expect( all('.opportunity_title_wrap').count ).to eq(2)
  end

2
Ciò sconfigge completamente l'attesa / ripetizione di Capybaras e non dovrebbe mai essere una soluzione consigliata.
Thomas Walpole

@ThomasWalpole Non sono sicuro di cosa stai parlando. In che modo la ricerca di un elemento all'interno di un altro elemento tocca in qualche modo l'attesa / il nuovo tentativo in Capybara?
Constant Meiring,

2
@ConstantMeiring Non è il within, sta chiamando .counti risultati allche disabilita l'attesa / il nuovo tentativo. Richiamando counti risultati di all(per il quale un "array" vuoto è un ritorno valido) si converte in un numero intero e lo si confronta. Se il confronto fallisce, l'aspettativa fallisce. Se invece passi l'opzione di conteggio a uno degli abbinamenti di Capybara, capybara aspetterà / riproverà a trovare il selettore specificato fino a quando l'opzione di conteggio non corrisponde (o Capybara.default_max_wait_time scade).
Thomas Walpole

4

La migliore pratica corrente (9/2/2013) raccomandata da Capybara è la seguente ( fonte ):

page.assert_selector('p#foo', :count => 4)


-4

La risposta di @pandaPower è molto buona, ma la sintassi era leggermente diversa per me:

expect(page).to have_selector('.views-row', :count => 30)

5
L'utilizzo di razzi hash non si qualifica come "sintassi diversa".
premjg

2
Non sono uno sviluppatore di rubini e non mi rendevo conto che le due sintassi erano equivalenti. TBH Non sono sicuro che giustifichi il downvoting. È una valida alternativa. Per chi non ha un background Ruby potrebbe non sembrare ovvio. Non era per me.
Nick
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.