( hrgy84 | 2015. 11. 23., h – 13:47 )

"Ha megváltozik az implementáció egy teljesen szabályos refaktorálás miatt, akkor nem kell átírni"

Nem feltetlen ertem, mire gondolsz teljesen szabvanyos refaktoralas alatt, gyakorlatilag ketto darab IExchangeService implementaciod van, es otletunk nincs, hogy az MNBExchangeService jol mukodik-e, azt teszteltuk, hogy tudunk-e olyan osztalyt irni, ami implementalja az IExchangeService interfeszt. Ez egy tok alap Java tudas tesztelesre hasznos, de hogy az MNBService mit csinal es mit nem csinal, azt senki sem tudja. Elkepzelheto persze, hogy az alkalmazas oldalan a TestExchangeService-t fogjuk hivogatni, de valljuk be, ez a ritkabbik eset.

Tegyuk fel, hogy az alabbi modon irom at az MNBExchangeService-t:


abstract class BasicExchangeService implements  IExchangeService {
  public abstract double echange(double price);
}
class MNBExchangeService extends BasicExchangeService {

}

A teszt sikerrel le fog futni, az app pedig hibas lesz. Hogy miert? Mert senki nem teszteli a valos mukodest, senkit nem erdekel, hogy az app egyebkent mukodik-e.

De ez csak a megoldasod egyik problemaja.

A masik, hogy tegyuk fel, az alkalmazasba beleinjektalod a TestExchangeService peldanyt (hogy most az app inicializaciojanak konstruktorban adod at, vagy DI-vel benyomod, az irrelevans), miben lesz ez jobb, mint egy stub? A TestExchangeService-t ugyanugy at kell irni, ha valtozik 1) az interfesz definicioja 2) a kalkulacios logika (peldaul ha a valtas soran hozza kell adni egy fix atvaltasi koltseget), vagyis valojaban ket ExchangeService-t kell karbantartani, ebbol az egyiket csak azert tartjuk karban, mert vicces, ha ket ExchangeService-nk van egy helyett, ugyanis az egyiket senki elo ember nem hasznalja, az masikat pedig senki elo ember nem teszteli. Soha.

Na tipikusan ezek azok a helyzetek, amikor a modularizacio nem ekvivalens a jol szervezettseggel. Nem eleg csak arra verni, hogy nekem modularis az alkalmazasom, azt is meg kell indokolni, hogy ez miert jo. Jelen esetben ez nem jo, es nem is latom az indokat, hogy az ExchangeService-t ennyire szetbonyolitsam, foleg ugy, hogy ezzel el fogom vesziteni azt, hogy az MNBService barmilyen modon tesztelheto legyen.

Itt a helyes megoldas az, hogy ugyan szetmodularizalom (ez eddig jo irany!), de az MNBExchangeServiceTest-ben kistubolom az MNB altal biztositott API egyes osztalyait, es megnezem, hogy maga az MNBExchangeService egyaltalan mukodokepes-e, ugyanis _ez_ az, ami az alkalamzas szempontjabol fontos, nem pedig az, hogy a TestExchangeService tud-e barmit csinalni.

Tbh egyebkent ha nem varhato egyszerre tobb Exchange szolgaltato megjelenese a kodban, nem is erdemes szetmodularizalni, mert ez csak felelsegesen bonyolitja a projektet, egy egyszeru refaktoralassal kicserelheto az osztaly neve, ha erre barmikor szukseg mutatkozik.

Az app tobbi resze szempontjabol pedig tokeletesen irrelevans, hogy egy valodi stubot injektalok be az alkalmazasba, vagy egy ilyen moricka-implementaciot, a stubnak csak annyi elonye van, hogy azt nem kell kulon osztalykent megirni es karbantartani, eleg csak az adott teszt igenyeihez felkesziteni.

Nem szabad elvesziteni szem elol azt, hogy miert irjuk a teszteket: hogy az alkalmazashibakat meg fejlesztesi idoben megfogjuk. Nem azert, mert fapolni akarunk arra, hogy nekunk vannak tesztjeink.
--
Blog | @hron84
Üzemeltető macik