EDIT: Neeh ik ben niet |dronken|
Ik hou complexe functie defenities met evt onderliggende complexe scope altijd private, evenzo als data members van een classe zoveel mogelijk private word gehouden door mij.
Ik test bij functies waarvan moet worden vastgesteld of ze goed werken en die complex zijn zodat ik de correcte werking niet per definitie kan overzien.
Mijn tests maak ik met een speciale class die alleen bij een bepaalde DEFINE word meegecompileerd.
#ifdef(DEBUG_PRIVATE_MEMBERS)
// test code hier
#endif
Meestal in de constructor om alle private functies afzonderlijk te testen. Hierbij houd ik me aan de regel dat een private functie zo min mogelijk afhankelijk is van de staat van de class, en indien er toch afhankelijkheid is, dan zorg ik dat de class eerst in een bepaalde staat verkeert voor ik ga testen.
Mijn mening is dus, BIJ EEN SPECIALE DEFINE bijvoorbeeld in STDAFX.H dan worden alle functies getest die ENABLED worden in de build door die DEFINE. Als uitvoer van debug resultaten gebruik ik een BESTAND bij heel veel uitvoer, of een CONSOLE.
Maak dus code die naar wens wel of niet meegecompileerd word.
En ja, ik vind testen belangrijk.
Een voorbeeld, je hebt een string: hoi|dit|is|een|test
Je moet een functie schrijven als volgt:
BOOL ParserGetArg(LPCSTR lpszDataString, UINT nArg, LPSTR lpszResult, UINT cbResult);
Dan zie je in dat je die functie wel moet testen, als lpszDataString="hoi|dit|is|een|test", en nArg=1, dan kan je als programmeur kiezen dat ie lpszResult="hoi" geeft of zerobased index "dit", afhankelijk van wat je wenst, maar je moet dan wel controleren bij een simpele string of alle nArg={0...n} valide zijn. Als je voor een kleine string goede resultaten hebt, kan je zelfs een compleet boek naar de functie sturen en verwachten dat het goed werkt.
TESTEN MOET SOMS, kan jij een functie schrijven (zonder te testen) en garanderen dat je in dit voorbeeld altijd goed resulteert? Neeh, pas als je hebt getest is het bewijs voldoende.
Ik zie dat anderen vaak aan de buitenkant van een class testen, maar ik geef zo weinig public functies dat ik alles wel intern test.
Voorbeeld is HANDLE StyleCreateDevice(HWND hEventWindow);
Ik maak dan een grafische window die met photoshop is gemaakt, in dit geval voor mijn mediacentre project. Op die grafische window zitten knopjes, faders, en ruimte voor filmpjes (RECTS...) Omdat alles styleable is, heeft het programma weinig anders te doen, dan de door de gebruiker gemaakte style te creeeren. Met 1 functiecall is de mediaspeler gemaakt.
[Window]
szImage_Background="main.bmp"
[Button]
szPresentByName=Play|Stop
Play_rcPlacement=0,0,100,15
Play_szImage_StateMouseOver=playmo.bmp
Play_szImage_StateMouseDown=playmd.bmp
Stop_rcPlacement=0,30,100,15
Stop_szImage_StateMouseOver=stopmo.bmp
Stop_szImage_StateMouseDown=stopmd.bmp
Dit is een voorbeeld van een style voor de CStyleable Device van mijn project, er zijn 2 knopjes Play en Stop
void CMediaCallbackDialog::InitDialog(......)
{
StyleCreateDevice(m_hWnd);
}
void CMediaCallbackDialog::WindowProc(UINT message, WPARAM wparam, LPARAM lparam)
{
switch(message)
{
case SCB_LBUTTONUP:
{
if(!strcmp( (char*)wparam,"Play"))
{
// play ingedrukt
}
break;
}
}
Zo kan je met een heel klein iets gewldig grote complexe windows ontwerpen met photoshop, in mijn project heb ik gekozen voor RGB(255,0,255) als transperant, dus je kan ook windows maken die niet perse vierkant zijn.
Wat je ziet is dat mijn CStyleable class device wel 100 procent goed moet werken, maar de class is te complex om zomaar te maken uti het niks, dus heb ik tijdens het maken van de CStyleable class echt zorg gemaakt om helemaal gecontroleerd en getest binnen in de class te werk te gaan.
Nu snap je misschien voorbeeld 1 , als je naar [Butons] kijkt daar onder szPresentByName=PLAY|STOP, dan zie je dat ik die 1e functie hier helemaal bovenin nodig heb.
Verder is duidelijk dat die allereerste voorbeeld functie in deze toepassing van de CStyleable class niet getest kan worden buiten de class.
[
Voor 39% gewijzigd door
Verwijderd op 17-09-2004 23:53
]