Rubyn send-metodi auttaa tiivistämään testikoodia
Kuvitellaan että meillä on sovellus, jonka yksi tietomalli on lasku. Laskussa on tyypillisesti useita eri kenttiä, joiden kaikkien toiminta täytyy testata mallin yksikkötesteissä. Malli ei esimerkiksi saa hyväksyä tyhiä arvoja pakollisiin kenttiin.
Yksi vaihtoehto on kirjoittaa oma testi jokaisen kentän testaukselle:
test "invalid invoice if iban is empty or nill" do
@invoice.iban = ""
assert !@invoice.valid?
@invoice.iban = nil
assert !@invoice.valid?
end
test "invalid invoice if due date is empty or nill" do
@invoice.due_date = ""
assert !@invoice.valid?
@invoice.due_date = nil
assert !@invoice.valid?
end
...
Mutta jos testattavia kenttiä on paljon, on tämä tapa tarpeettoman työläs johtaa lähes identtisen koodin toistamiseen.
Rubyssä on kuitenkin näppärä ominaisuus, jonka avulla testit voidaan kirjoittaa tiiviimpää muotoon.
send
on Object-luokan metodi, joka yksinkertaisesti kutsuu sille parametrina annettavaa metodia. Normaalikäytössä tämä on aika tarpeeton toiminto – helpointa on vain kutsua haluttua metodia suoraan kierrättämättä kutsua send
in kautta. Mutta jos haluttu metodi onkin muuttuja, on send
tarpeellinen apukeino.
Nyt testikoodi voidaan kirjoittaa tiiviiseen ja toistoa välttävään muotoon:
test "invalid invoice if mandatory fields are empty" do
@invoice = invoices(:one)
[
"receiver_name",
"receiver_email",
"receiver_address",
"receiver_tax_id",
"sender_name",
"sender_email",
"sender_address",
"sender_tax_id",
"iban",
"bic",
"delivery_method",
"bill_number",
"reference",
"status",
"issue_date",
"due_date"
].each do |key|
invoice = @invoice.dup
invoice.send "#{key}=", ""
assert !invoice.valid?
invoice.send "#{key}=", nil
assert !invoice.valid?
end
end
Tällä tavalla voidaan ensin muodostaa lista halutuista kentistä, joille kutsutaan yhtä ja samaa koodilohkoa, joka tekee varsinaisen testauksen.
Yllä olevassa esimerkissä kentän nimi saapuu lohkolle key
-muuttujassa. Koska send
hyväksyy parametrinaan symbolin lisäksi myös merkkijonon, voidaan käyttää merkkijojon interpolointia eli #{}
-syntaksia lisäämään =-merkki parametrin perään. Tämä puolestaan liittyy Rails-frameworkin ominaisuuteen – jokaisella tietomallin kentällä on automaattisesti setter-metodi. Jos siis kentän nimi on foo
, on sitä vastaava setter-metodi foo=
.
Jälkimmäinen send
-metodin parametreista on kentälle asetettava arvo. Tässä tapauksessa haluamme testata sekä tyhjän merkkijonon että nil
-arvon.
Heti lohkon alussa oleva olion kopiointi dup-metodilla tehdään puolestaan siksi, jotta käytössä on tuore invoice-olio, jonka alkuarvot ovat joka testauskierroksella samat.
Lopputuloksena on entistä tiiviimpi, kauniimpi ja helpommin ylläpidettävä katkelma koodia.