TDD?
Picit belenéztem a phpunit használatába.
Arra lennék kíváncsi, jó-e az elképzelésem róla?
A TDD (egészen nagy vonalakban, vázlatosan) valahogy úgy működik, hogy
1. megtervezem, hogy nagyjából milyen osztályokra bontom az alkalmazást
2. kitalálom az egyes osztályok interface-ét
3. ezen interface-ekhez megírom a teszteket
4. elkészítem az osztály kódját
5. futtatom a tesztet és addig javítom a kódot, míg nem lesz hibátlan valamennyi
?
Ebből nekem hiányzik a privát/protected metódusok működésének tesztelése. Unit teszt esetén ez szükséges egyáltalán? (érzésem szerint nem, hiszen ha az adott interface/API publikus alkatrészei helyesen működnek, az csak úgy lehet, ha a nem publikus részek is megfelelően üzemelnek)
Bónusz kérdés (költői! ;-) ) : létezik élő ember, aki képes egy komolyabb rendszerre átfogó tesztet írni úgy, hogy közben a határidőket is be tudja tartani? :-)
----------------------------------
Félreértések elkerülése végett: a saját elképzeléseimet foglaltam össze (ebben a pillanatban botlottam egy angol nyelvű cikkbe, ahol közelítőleg ezt írták... szóval valószínűleg így működik, de nem onnan másoltam :-) )
■ Arra lennék kíváncsi, jó-e az elképzelésem róla?
A TDD (egészen nagy vonalakban, vázlatosan) valahogy úgy működik, hogy
1. megtervezem, hogy nagyjából milyen osztályokra bontom az alkalmazást
2. kitalálom az egyes osztályok interface-ét
3. ezen interface-ekhez megírom a teszteket
4. elkészítem az osztály kódját
5. futtatom a tesztet és addig javítom a kódot, míg nem lesz hibátlan valamennyi
?
Ebből nekem hiányzik a privát/protected metódusok működésének tesztelése. Unit teszt esetén ez szükséges egyáltalán? (érzésem szerint nem, hiszen ha az adott interface/API publikus alkatrészei helyesen működnek, az csak úgy lehet, ha a nem publikus részek is megfelelően üzemelnek)
Bónusz kérdés (költői! ;-) ) : létezik élő ember, aki képes egy komolyabb rendszerre átfogó tesztet írni úgy, hogy közben a határidőket is be tudja tartani? :-)
----------------------------------
Félreértések elkerülése végett: a saját elképzeléseimet foglaltam össze (ebben a pillanatban botlottam egy angol nyelvű cikkbe, ahol közelítőleg ezt írták... szóval valószínűleg így működik, de nem onnan másoltam :-) )
Igen
null
illetve üres string érkezik, valamint amennyiben számokkal dolgozunk, akkor az működik-e azok speciális esetére is.Kevés olvasnivaló magyarul:
Tankjú! (A diasor picit
TDD By Example
Megelőztél, pont most akartam
A TDD (egészen nagy
1. megtervezem, hogy nagyjából milyen osztályokra bontom az alkalmazást
2. kitalálom az egyes osztályok interface-ét
3. ezen interface-ekhez megírom a teszteket
Az a design-driven testing... Nekem az jött le, hogy a TDD lényege elvileg az, hogy tesztírással kezded, és a struktúra természetesen alakul ki, ahogy haladsz vele. (Veszed az első tesztet, megvalósítod (közben készül valami osztály), veszed a következő teszted, módosítod, hogy az is átmenjen, refaktorálsz, veszed a következő tesztet stb. A teszteket a specifikáció nagyjából meghatározza.) Hogy használják-e élőben ebben a formában, azt nem tudom.
Na ezt nem értem
Mire kezdesz tesztet írni, ha nincs egy terved arra nézve, hogy milyen darabokra akarod szétszedni az adott feladatot és ezek a darabok milyen interface-en kapcsolódnak egymáshoz?
Vagy csak szimpla félreértésről van szó?
Amikor interface-ről beszélek, akkor nem a PHP kulcsszóra gondolok, pusztán egy elméleti felületre.
Tehát kb. kitalálom, hogy milyen bejövő paraméterekre lehet szükség egy adott objektum működéséhez és mit várnék el tőle - kódot egy sort sem írok.
Félreértetted - szerintem
Az csak idézet
Ja-ja bocs
Az a design-driven testing...
Igen, szerintem is ez áll közelebb a TDD-hez. Egyébként használják ilyen formában, legalábbis nekem van olyan ismerősöm, aki igen. Én megpróbálkoztam vele, de szerintem túl kevés még a tapasztalatom hozzá, és nem tudom rendesen átgondolni egy projekt elején, hogy pontosan mit akarok, így viszont amint eszembe jut egy-egy új ötlet, dobhatom kukába a tesztjeim egy részét, mert az új ötlet teljesen más interface-t használ.
Red Green Refactor Red Green
Green
Refactor
Red
Green
Refactor
Red
Green
Refactor…
(Írsz egy tesztet a legegyszerűbb interfészre, ami megoldaná a problémád. Futtatod, és konstatálod, hogy nem működik.
Belekódolod a megoldást, hogy működjön.
Észreveszed, hogy a megoldásod redundáns, így hát általánosítod.)
Kent Beck-et olvasd el.
Red...
No ez nem tiszta. Elkezdem írni a tesztet úgy, hogy (maradjunk PHP környezetben) a tesztelendő osztályból még egy üres forráskód fájl sem létezik, ergo az első require_once elhasal rajta -> javítom, hogy már létezzen, majd folytatom a tesztírást az osztály példányosításával, ami megint elakad, mert még csak egy üres .php fájl van a tesztelendő osztály helyén -> megírom az osztályt konstruktorig -> mikor ez a teszt már sikeres, akkor írom a publikus metódusok tesztjeit ugyanilyen ciklusban stb.
Ez valahogy így?
Pontosan.
Így, de pont, hogy nem ez az
A könyv
(mivel már letettem arról, hogy a programozásból megéljek, már nem fér a keretbe - nem panasz, pusztán tényközlés, hogy nem ignorálom a javaslatot)
először a teszt írás és utána a kód
Bár ehhez az is kell, hogy amikor olvassa az ember a Tiszta kódot, akkor "érezze a katarzis"-t, mint ahogy egy másik fórumtémában írtad, hogy ez elmaradt... :)
A probléma az, hogy ha nincs rutin, akkor ez sokkal lassabb, mintha kihagynánk, vagy csak utólag írnánk teszteket. Ami nálam probléma, hogy a TDD-nél sokkal előrébb kell gondolkodni. A tervezés során nem tudom megtippelni, hogy egy osztály átlépi-e a 100 sort vagy sem? Nem látom, hogy ebből majd fél óra múlva két osztály lesz stb.
De a lényeg a lényeg, a nagykönyv szerint a teszt írás az első, a kód írás a második. Ám nem nagyon kell szégyenkezned, ha nem ebben a sorrendben csinálod, a legtöbben egyáltalán nem használnak teszteket, akik igen, azoknak is a legtöbbje utólag ír tesztet, és Bob bácsi és néhány haverja meg elsőre írja a tesztet. :)
A lépéseidet azért mégis annyiban módosítanám, hogy az utolsó lépésben nem addig javítom, amíg valamennyi teszt jó nem lesz, hanem addig alakítom a kódot, amíg a lényeges pontok tesztelhetővé vállnak. (bár ez is csak lehet, hogy nálam igaz, és szintén a rutintalanság miatt, hogy az elkészült osztályszerkezet nehézkesen tesztelhető, és itt jön elő, hogy egy osztály csak egy dolgot csináljon)
Egy óriási probléma...
Programozással csak "coder"-ként foglalkoztam, a tervezést sohasem tanultam, pláne nem gyakoroltam.
Ebbe a témába azért esik nehezemre belerázódni, mert még a legegyszerűbb feladatok megtervezése is iszonyatosan sok munkába kerül és egyszerűen nincs hozzá türelmem.
Szomszéd Pistikét nem akarok játszani még így, hobbi szinten sem, viszont a hiányzó alapismeretek+türelmetlenség... hát nem jósolok nagy jövőt magamnak... :-)
Tegnap belebotlottam (ki tudja hanyadszor) a phpunitba és úgy döntöttem, kipróbálom. Most itt tartok. Próbálgatom.
Tervezés
Igazad van: egy jó program- (és adatbázis-) terv sok munkába és türelembe kerül. Azt hiszem Janoszentől olvastam, hogy egy projektnek ez több mint a fele. Egyet is értek vele.
Ha van egy jó terved, akkor a programozás max. a fele annak, mint ha nincs terved. De inkább negyede.
Ha nincs terved, akkor csak kókányolás lesz belőle millió javítgatással - tehát akkor bizony olyan vagy, mint Szomszéd Pistike.
Ha nagyon nem megy a tervezés, akkor talán még nem a TDD a következő lépés számodra. Én - hősiesen bevallom - eddig megvoltam a phpunit nélkül, de érzem, hogy valamire nagy szükségem van, csak még nem tudom (biztosan), hogy mire.
Szerk.: ja, és egy kicsike honlapnál - nálam - az adatbázis- és a programterv gyakorlatilag egyszerre készül, nem is nagyon válik szét.
Ez az első. Enélkül mihez
Igazad van: egy jó program- (és adatbázis-) terv sok munkába és türelembe kerül. Azt hiszem Janoszentől olvastam, hogy egy projektnek ez több mint a fele. Egyet is értek vele.
+1, a terv a legfontosabb része. Runtin nélkül elég nehéz elsőre úgy összerakni, akár még egy adatbázist, hogy az tényleg jó legyen. Nekem előfordul még, hogy hozzá kell csapni egy-egy táblát is akár, még csak tanulom :-)
PhpUnit nálam azért nem vált be, mert windows alatt fejlesztek, és képtelenség telepíteni rá. Pár napot próbálkoztam vele, aztán úgy döntöttem, hogy hatékonyabb, ha keresek mást. A simpleTest, amit találtam, kb 10 perc alatt fent volt... Nálam az egyik legfőbb mérce azzal kapcsolatban, hogy jó e egy program, vagy lib, hogy mennyire egyszerű telepíteni. Elhiszem, hogy ez a Sebastian Bergmann gyerek egy nagy linux meg pear fun, de nálam nagyon durván elbukott... :-)
Akkor nálam is elbukott
Szerintem adatbázis összerakásban senkinek nincs rutinja, hacsak nem pontosan ugyanazokat a feladatokat oldod meg többször.
Ha meg beficcen egy-egy plusz tábla, akkor sincs semmi baj, ha amúgy jó a db, akkor könnyen illeszthető. A feladatspecifikáció viszont pontatlan volt, ha kellett plusz tábla.
Szerintem adatbázis-tervezésnél elsősorban lekérdezési oldalról kell közelíteni (mármint ha már meg van, hogy mit akarok tárolni, csak még nem tudom hogyan), nekem legalábbis sokat segít annak eldöntésében, hogy mi kerüljön az egyes táblákba, hogy tudom a gyakori lekérdezéseket minél egyszerűbbé (és gyorsabbá) tenni.
Bizony, ha jó az adatbázistervem, velem előfordul, hogy a programterv "csak fejben van"... Ez persze nagy hiba.
Hát itt konkrétan az volt,
Nem egeszen
Pont hogy elore nem kell ezzel foglalkoznod. Amikor ugy erzed hogy az osztalyod mar tul sok mindenert felelos, vagy duplikacio van benne egyszeruen refaktoralod. A meglevo tesztek meg biztsitjak, hogy refaktoralas kozben nem rontasz el semmit.
Ez oké, de mi van, ha úgy
A tesztek refaktorálása
Megint tanultam valamit :-)
1. megtervezem, hogy
2. kitalálom az egyes osztályok interface-ét
3. ezen interface-ekhez megírom a teszteket
4. elkészítem az osztály kódját
5. futtatom a tesztet és addig javítom a kódot, míg nem lesz hibátlan valamennyi
Ez nem így megy szerintem. Én úgy állnék neki TDD-vel, hogy nagyjából elgondolom, hogy mit várok el, aztán létrehozok az elvárásaimmal összehangban egy vagy több interface-t, ami nagyjából lefedi az alkalmazást. Utána kiválasztom a legegyszerűbb metódust valamelyik interface-en, és írok hozzá egy tesztet, utána pedig megpróbálom megvalósítani egy osztályban. Ilyenkor jön általában az, hogy kiderül, hogy az a metódus mégsem annyira egyszerű, mint elsőre tűnt, és elkezdesz új interface-eket, teszteket és osztályokat gyártani, hogy szétosszad a feladatait, és megteremtsd az előkövetelményeket neki. Aztán néhány ilyen ciklus után már tényleg elég aprók lesznek az osztályok ahhoz, hogy meg tudd valósítani őket, és akkor ahogy elkezd épülni a kód szép lassan egyre feljebb halad ezen a kiépült osztály hálón, míg végül megint felérsz az eredetileg kiválasztott "legegyszerűbb" metódusodhoz. Utána fogod a következőt, azzal viszont már könnyebb dolgod lesz, mert az első metódushoz tartozó segéd osztályokat és interface-eket újrahasznosíthatod hozzá. Így minél későbbi fázisában vagy a kódolásnak, annál könnyebben megy minden, mert a segédosztályok egyre nagyobb hányada lesz már elve készen. Ha egy meglevő keretrendszert használsz, és ismered is a lehetőségeit, akkor meg még könnyebb dolgod van, mert abban már a segéd osztályaid nagy többsége már kész van. (Ettől függetlenül érdemes azokhoz is teszteket írnod, ha a keretrendszer készítői nem tették volna meg.)