de Parth Modi
Conţinut
Cum să vă uscați testele RSpec folosind exemple partajate
„Acordați-mi șase ore pentru a tăia un copac și voi petrece primele patru ascuțind toporul. ” – Abraham Lincoln
Când am refactorizat un proiect în urmă cu câteva săptămâni, mi-am petrecut cea mai mare parte a timpului scriind specificații. După ce am scris câteva cazuri de testare similare pentru unele API-uri, am început să mă întreb dacă aș putea să scap de o mulțime de această duplicare.
Așa că m-am aruncat să citesc cele mai bune practici pentru testele de uscare (Nu te repeta). Și așa am ajuns să știu shared examples
și shared contexts
.
În cazul meu, am ajuns să folosesc exemple comune. Iată ce am învățat până acum de la aplicarea acestora.
Când aveți mai multe specificații care descriu un comportament similar, ar putea fi mai bine să extrageți exemple redundante în shared examples
și utilizați-le în mai multe specificații.
Să presupunem că aveți două modele Utilizator și Post, iar un utilizator poate avea multe postări. Utilizatorii ar trebui să poată vizualiza lista de utilizatori și postări. Crearea unei acțiuni index în utilizatorii și controlerele de postări va servi acestui scop.
Mai întâi, scrieți specificații pentru acțiunea dvs. de index pentru controlerul utilizatorilor. Va avea responsabilitatea de a prelua utilizatorii și de a-i reda cu un aspect adecvat. Apoi scrieți suficient cod pentru a trece testele.
# 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
De obicei, acțiunea index a oricărui controler preluează și agregă date din puține resurse, după cum este necesar. De asemenea, adaugă paginarea, căutarea, sortarea, filtrarea și extinderea.
În cele din urmă, toate aceste date sunt prezentate vizualizărilor prin HTML, JSON sau XML folosind API-uri. Pentru a simplifica exemplul meu, acțiunile de index ale controlerelor vor prelua datele, apoi le vor afișa prin vizualizări.
Același lucru este valabil și pentru acțiunea index din controlerul de postări:
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
Testele RSpec scrise atât pentru utilizatori, cât și pentru controlerul de postări sunt foarte similare. În ambele controlere avem:
- Codul de răspuns – ar trebui să fie „OK”
- Ambele acțiuni index ar trebui să redea parțial sau vizualizare corespunzătoare – în cazul nostru
index
- Datele pe care dorim să le redăm, cum ar fi postările sau utilizatorii
Să uscăm specificațiile pentru acțiunea noastră index folosind shared examples
.
Unde să-ți pui exemplele comune
Îmi place să plasez exemple comune în interiorul specs / support / shared_examples director, astfel încât toate shared example
-fișierele legate sunt încărcate automat.
Puteți citi despre alte convenții frecvent utilizate pentru localizarea dvs. shared examples
Aici: documente de exemple comune
Cum se definește un exemplu comun
Acțiunea dvs. de indexare trebuie să răspundă cu 200 de coduri de succes (OK) și să redea șablonul de indexare.
RSpec.shared_examples "index examples" do it { expect(subject).to respond_with(:ok) } it { expect(subject).to render_template(:index) }end
În afară de it
blocuri – și înainte și după cârlige – puteți adăuga let
blocuri, context și descrie blocuri, care pot fi definite și în interior shared examples
.
Personal, prefer să păstrez exemple simple și concise, și nu adaug contexte și nu las blocuri. shared examples
block acceptă, de asemenea, parametrii, pe care îi voi acoperi mai jos.
Cum se utilizează exemple comune
Se adaugă include_examples "index examples"
specificațiilor utilizatorului și a controlerului de postări include „exemple de index” la testele dvs.
# 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
Puteți utiliza, de asemenea it_behaves_like
sau it_should_behaves_like
în loc de include_examples
în acest caz. it_behaves_like
și it_should_behaves_like
sunt de fapt pseudonime și funcționează în același mod, astfel încât să poată fi utilizate în mod interschimbabil. Dar include_examples
și it_behaves_like
sunt diferite.
După cum se menționează în documentația oficială:
-
include_examples
– include exemple în contextul actual -
it_behaves_like
șiit_should_behave_like
include exemplele într-un context imbricat
De ce contează această distincție?
Documentația RSpec oferă un răspuns adecvat:
Când includeți exemple parametrizate în contextul curent de mai multe ori, puteți suprascrie definițiile metodei anterioare și ultimele câștiguri ale declarației.
Deci, atunci când vă confruntați cu situații în care exemplele parametrizate conțin metode care intră în conflict cu alte metode în același context, puteți înlocui include_examples
cu it_behaves_like
metodă. Acest lucru va crea un context imbricat și va evita acest tip de situații.
Consultați următoarea linie din specificațiile controlerului utilizatorilor și postează specificațiile controlerului:
it { expect(assigns(:users)).to match(User.all) }it { expect(assigns(:posts)).to match(Post.all) }
Acum, specificațiile controlerului dvs. pot fi re-luate în considerare, trecând parametrii la exemplul partajat, după cum urmează:
# 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
Acum, efectuați următoarele modificări ale specificațiilor utilizatorului și ale controlerului de postări:
# 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
Acum, specificațiile controlerului arată curat, mai puțin redundant și mai important, DRY. În plus, aceste exemple de index pot servi ca structuri de bază pentru proiectarea acțiunii de index a altor controlere.
Concluzie
Prin mutarea exemplelor obișnuite într-un fișier separat, puteți elimina duplicarea și îmbunătăți coerența acțiunilor controlerului în întreaga aplicație. Acest lucru este foarte util în cazul proiectării API-urilor, deoarece puteți utiliza structura existentă a testelor RSpec pentru a proiecta teste și a crea API-uri care aderă la structura dvs. comună de răspuns.
În general, când lucrez cu API-uri, îl folosesc shared examples
pentru a-mi oferi o structură comună pentru a proiecta API-uri similare.
Simțiți-vă liber să împărtășiți modul în care vă uscați specificațiile folosind shared examples
.
#Cum #să #vă #uscați #testele #RSpec #folosind #exemple #partajate
Cum să vă uscați testele RSpec folosind exemple partajate