RSpec let protiv before

U RSpec-u postoje dva različita načina za pisanje SUVIH testova, koristeći before ili let . Njihova svrha je da kreiraju promenljive koje su uobičajene u testovima. U ovom postu ćemo istražiti razlike između pre i let i objasniti zašto rubi zajednica preferira let .

let

Neka kreiramo lenjo procenjene lokalne promenljive. To znači da se let() ne vrednuje dok se metoda koju definiše ne pokrene prvi put. SUŠI specifikaciju i čini je čitljivijom.

$count = 0
describe "let" do
  let(:count) { $count += 1 }

  it "stores the value" do
    expect(count).to eq(1)
    expect(count).to eq(1)
  end

  it "is not cached across examples" do
    expect(count).to eq(2)
  end
end

Neka se ne koristi za lokalne promenljive, koje se moraju sačuvati u bazi podataka, jer one neće biti sačuvane u bazi podataka ako na njih već nije referenca. U ovom slučaju, trebalo bi da koristite let! ili before blokove.

Testovi koje kreiramo rade se pomoću RSpec-a i Capibare.

Takođe, nikada nemojte imati blok let unutar bloka pre bloka, ovo je ono što je dozvoljeno! je stvoren za!

let!

Za razliku od let, možete koristiti let! da prisili na pozivanje metode pre svakog primera . To znači da će se, čak i ako niste pozvali pomoćnu metodu unutar primera, pozvati pre nego što se vaš primer pokrene.

$count = 0
describe "let!" do
  invocation_order = []

  let!(:count) do
    invocation_order << :let!
    $count += 1
  end

  it "calls the helper method in a before hook" do
    invocation_order << :example
    expect(invocation_order).to eq([:let!, :example])
    expect(count).to eq(1)
  end
end

Kao i kod blokova let, ako je višestruko let! blokovi su definisani sa istim imenom, izvršiće se najnoviji. Suštinska razlika je u tome što let! blokovi će se izvršiti više puta ako se koriste na ovaj način, dok će se blok let izvršiti samo poslednji put.

before(:each)

before(:each) blok će se pokrenuti pre svakog primera, čak i ako primer ne koristi nijednu promenljivu instance definisanu u bloku. Ovo može primetno usporiti podešavanje promenljivih instance.

class User
  def tests
    @tests ||= []
  end
end

describe User do
  before(:each) do
    @user = User.new
  end

  describe "initialized in before(:each)" do
    it "has 0 tests" do
      @user.should have(0).tests
    end

    it "can accept new tests" do
      @user.tests << Object.new
    end

    it "does not share state across examples" do
      @user.should have(0).tests
    end
  end
end

U skoro svakoj situaciji je bolje koristiti let pre before blokova. U zavisnosti od vaših ličnih preferencija koje biste mogli da koristite pre blokade kada:

  • Postoji razumna količina promenljivih.
  • Postoje promenljive na koje ne treba direktno upućivati, ali su obavezne.
  • Postoji mnogo naredbi koje treba izvršiti, jer je njegova sintaksa jasnija kada se radi o mnogim naredbama.
  • Stvaranje podsmeha.

Pokušajte i napravite sopstveni test modela ili kontrolera !

before(:all)

Ovaj blok se izvršava samo jednom, pre svih primera u grupi. Postoje određene situacije koje mogu smanjiti izvršenje i napor.

class User
  def tests
    @tests ||= []
  end
end

describe User do
  before(:all) do
    @user = User.new
  end

  describe "initialized in before(:all)" do
    it "has 0 tests" do
      @user.should have(0).tests
    end

    it "can get accept new tests" do
      @user.tests << Object.new
    end

    it "shares state across examples" do
      @user.should have(1).tests
    end
  end
end

Korišćenje before(:all) u RSpec-u će vam stvoriti mnogo problema ukoliko ne znate šta radite! Radi izvan transakcija, tako da će se ovde stvoreni podaci preliti u druge specifikacije.

Zaključak

Let blokovi donesu više na sto nego before blokovi. Sve zavisi od toga šta i kako treba da učinite da RSpec testovi rade ili razmislite o korišćenju FactoryGirl za kreiranje podataka.

Pored toga što su sporiji, jedan od glavnih problema sa before blokovima je taj što pravopisne greške mogu dovesti do grešaka i lažnih pozitivnih rezultata, omogućavajući određenim vrstama testova da prođu kada ne bi trebalo.

before(:each) do
    @user = User.find(username: "kolosek")
    @user.logout
end

it "should log the user out" do
    expect(@usr).to be_nil
end

Budući da @usr nije prethodno definisan, test će proći, @usr je podrazumevano nula. Isti test koji koristi let podigao bi NameError jer @usr nije definisan.

Nadam se da će vam ovo pomoći da bolje razumete razlike između blokova let i before.

Hvala vam za čitanje!

Pratite našu prugu pretplatom na naš bilten! Znamo put!