Kuinka kuivata RSpec-testit jaettujen esimerkkien avulla

" Anna minulle kuusi tuntia kaataa puu, ja vietän neljä ensimmäistä kirveen teroittamiseen." - Abraham Lincoln

Kun muutin projektia muutama viikko sitten, käytin suurimman osan ajastani kirjoittamalla teknisiä tietoja. Kirjoitettuani useita vastaavia testitapauksia joillekin sovellusliittymille aloin miettiä, pystynkö pääsemään eroon paljon tästä päällekkäisyydestä.

Joten heitin itseni lukemaan parhaita käytäntöjä testien kuivattamiseen (älä toista itseäsi). Ja näin sain tietää shared examplesja shared contexts.

Minun tapauksessani päädyin käyttämään jaettuja esimerkkejä. Ja tässä on mitä olen oppinut toistaiseksi näiden soveltamisesta.

Kun sinulla on useita teknisiä tietoja, jotka kuvaavat samanlaista käyttäytymistä, saattaa olla parempi poimia turhat esimerkit shared examplesja käyttää niitä useissa teknisissä tiedoissa.

Oletetaan, että sinulla on kaksi mallia User ja Post , ja käyttäjällä voi olla useita viestejä. Käyttäjien pitäisi voida tarkastella käyttäjien luetteloa ja viestejä. Hakemistotoiminnon luominen käyttäjiin ja viestien ohjaimiin palvelee tätä tarkoitusta.

Kirjoita ensin tekniset tiedot hakemistotoiminnolle käyttäjien ohjaimelle. Sen vastuulla on hakea käyttäjät ja tehdä heistä oikea asettelu. Kirjoita sitten tarpeeksi koodia, jotta testit läpäisevät.

# users_controller_spec.rbdescribe "GET #index" do before do 5.times do FactoryGirl.create(:user) end get :index end it { expect(subject).to respond_with(:ok) } it { expect(subject).to render_template(:index) } it { expect(assigns(:users)).to match(User.all) }end
# users_controller.rbclass UsersController < ApplicationController .... def index @users = User.all end ....end

Tyypillisesti minkä tahansa ohjaimen hakemistotoiminto hakee ja yhdistää tietoja muutamasta resurssista tarpeen mukaan. Se lisää myös sivutus, haku, lajittelu, suodatus ja kattavuus.

Lopuksi kaikki nämä tiedot esitetään näkymille HTML: n, JSON: n tai XML: n kautta API: n avulla. Esimerkin yksinkertaistamiseksi ohjainten hakemistotoiminnot vain hakevat tietoja ja näyttävät ne sitten näkymien kautta.

Sama koskee hakemistotoimintoa viestien ohjaimessa:

describe "GET #index" do before do 5.times do FactoryGirl.create(:post) end get :index end it { expect(subject).to respond_with(:ok) } it { expect(subject).to render_template(:index) } it { expect(assigns(:posts)).to match(Post.all) }end
# posts_controller.rbclass PostsController < ApplicationController .... def index @posts = Post.all end ....end

Sekä käyttäjille että viestien ohjaimelle kirjoitetut RSpec-testit ovat hyvin samanlaisia. Molemmissa ohjaimissa meillä on:

  • Vastauskoodin - pitäisi olla 'OK'
  • Molempien hakemistotoimintojen tulisi tehdä oikea osittainen tai näkymä - meidän tapauksessamme index
  • Tiedot, jotka haluamme tehdä, kuten viestit tai käyttäjät

Kuivataan hakemistotoimintomme tiedot käyttämällä shared examples.

Mihin laittaa jaetut esimerkit

Haluan sijoittaa jaettuja esimerkkejä hakemistoon specs / support / shared_examples niin, että kaikki siihen shared exampleliittyvät tiedostot ladataan automaattisesti.

Voit lukea muista yleisesti käytetyistä käytännöistä paikantamiseksi shared examplestäältä: jaettujen esimerkkien dokumentaatio

Kuinka määritellä jaettu esimerkki

Hakemistotoimintasi tulisi vastata 200 onnistumiskoodilla (OK) ja tehdä hakemistomalli.

RSpec.shared_examples "index examples" do it { expect(subject).to respond_with(:ok) } it { expect(subject).to render_template(:index) }end

Lohkojesi lisäksi it- ja ennen koukkujasi ja niiden jälkeen - voit lisätä letlohkoja, kontekstia ja kuvata lohkoja, jotka voidaan määrittää myös sisällä shared examples.

Henkilökohtaisesti pidän mieluummin pitää jaetut esimerkit yksinkertaisina ja ytimekkäinä, enkä lisää konteksteja ja anna lohkojen. shared examplesLohko hyväksyy myös parametrejä, jota peittävät alla.

Kuinka käyttää jaettuja esimerkkejä

Lisääminen include_examples "index examples"käyttäjiin ja viesteihin ohjaimen tekniset tiedot sisältävät "hakemistoesimerkkejä" testeihisi.

# users_controller_spec.rbdescribe "GET #index" do before do 5.times do FactoryGirl.create(:user) end get :index end include_examples "index examples" it { expect(assigns(:users)).to match(User.all) }end
# similarly, in posts_controller_spec.rbdescribe "GET #index" do before do 5.times do FactoryGirl.create(:post) end get :index end include_examples "index examples" it { expect(assigns(:posts)).to match(Post.all) }end

Voit käyttää myös tässä tapauksessa it_behaves_liketai it_should_behaves_likesen sijaan include_examples. it_behaves_likeja it_should_behaves_likeovat tosiasiallisesti aliaksia ja toimivat samalla tavalla, joten niitä voidaan käyttää keskenään. Mutta include_examplesja it_behaves_likeovat erilaisia.

Kuten virallisissa asiakirjoissa todetaan:

  • include_examples - sisältää esimerkkejä nykytilanteesta
  • it_behaves_likeja it_should_behave_likesisällytä esimerkit sisäkkäiseen kontekstiin

Miksi tällä erotuksella on merkitystä?

RSpecin dokumentaatio antaa oikean vastauksen:

Kun sisällytät parametrisoituja esimerkkejä nykyiseen asiayhteyteen useita kertoja, voit ohittaa aiemmat metodimääritykset ja viimeinen julistus voittaa.

Joten kun kohtaavat tilanteessa, jossa parametroitu esimerkit sisältävät menetelmiä, jotka ovat ristiriidassa muiden menetelmien samassa yhteydessä voit korvata include_exampleskanssa it_behaves_likemenetelmällä. Tämä luo sisäkkäisen kontekstin ja välttää tällaisia ​​tilanteita.

Tarkista seuraava rivi käyttäjien ohjainten teknisissä tiedoissa ja ohjainten teknisissä tiedoissa:

it { expect(assigns(:users)).to match(User.all) }it { expect(assigns(:posts)).to match(Post.all) }

Ohjaimen tekniset tiedot voidaan nyt tarkentaa edelleen siirtämällä parametrit jaettuun esimerkkiin alla esitetyllä tavalla:

# specs/support/shared_examples/index_examples.rb
# here assigned_resource and resource class are parameters passed to index examples block RSpec.shared_examples "index examples" do |assigned_resource, resource_class| it { expect(subject).to respond_with(:ok) } it { expect(subject).to render_template(:index) } it { expect(assigns(assigned_resource)).to match(resource_class.all) }end

Tee nyt seuraavat muutokset käyttäjiin ja julkaisevat ohjaimen tekniset tiedot:

# users_controller_spec.rbdescribe "GET #index" do before do ... end include_examples "index examples", :users, User.allend
# posts_controller_spec.rbdescribe "GET #index" do before do ... end include_examples "index examples", :posts, Post.allend

Ohjaimen tekniset tiedot näyttävät nyt puhtailta, vähemmän tarpeettomilta ja mikä tärkeintä, KUIVA. Lisäksi nämä hakemistoesimerkit voivat toimia perusrakenteina muiden ohjainten indeksitoiminnan suunnittelussa.

Johtopäätös

Siirtämällä yleisiä esimerkkejä erilliseen tiedostoon, voit poistaa päällekkäisyydet ja parantaa ohjaintoimintojesi johdonmukaisuutta koko sovelluksessasi. Tämä on erittäin hyödyllistä sovellusliittymien suunnittelussa, koska voit käyttää RSpec-testien olemassa olevaa rakennetta testien suunnittelussa ja luomassa yhteisen vasterakenteen mukaisia ​​API: ita.

Enimmäkseen, kun työskentelen sovellusliittymien kanssa, käytän shared examplestarjoamaan minulle yhteisen rakenteen samanlaisten sovellusliittymien suunnitteluun.

Voit vapaasti jakaa kuinka kuivaat tekniset tiedot käyttämällä shared examples.