1. Framework-Qualit¨t: Tests als
a
Gutesiegel
¨
Benjamin Eberlei
SimpleThings GmbH
IPC Spring, Mai 2009
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 1 / 33
2. ¨
Uber Mich
¨
Uber mich
Volkswirt
PHP seit 2001
Software Entwickler bei
SimpleThings GmbH
Zend Framework Contributor
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 2 / 33
3. Warum Framework-Qualit¨t?
a
Warum sollte uns
Framework-Qualit¨t interesieren?
a
Framework soll Gewinn und keine
Last sein
Echten Mehrwert f¨r Programmierer
u
schaffen
Aber: Auch Frameworks haben Bugs!
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 3 / 33
4. Warum Framework-Qualit¨t?
a
Framework-Bugs
1. Bugs in fremden Code schwer zu finden
2. Framework-Code ist schwer zu debuggen
3. Komplexit¨t und Wartungsaufwand durch Userland
a
Fixes
4. K¨nnen Fertigstellung von End-Anwendungen
o
massiv verz¨gern
o
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 4 / 33
5. Wie Framework Qualit¨t messen?
a
Wie Framework Qualit¨t messen?
a
1. Einstellung zu Tests & Qualit¨tssicherung
a
2. Große Zahl von Unittests
3. Wahl des Unit-Testing Frameworks
4. Hohe Code-Coverage der Tests
5. Tests als Dokumentation
6. Testing Bad-Practices
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 5 / 33
6. Einstellung zu Tests & Qualit¨tssicherung
a
Einstellung zu Tests & Qualit¨tssicherung
a
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 6 / 33
7. Einstellung zu Tests & Qualit¨tssicherung
a Zend Framework
Zend Framework
Jede neue Komponente muss mindestens 80%
Code-Coverage haben
F¨r jeden Bug mindestens 1 Regression-Test
u
Wird leider nicht von allen
Komponenten-Maintainern eingehalten
Tests werden h¨ufig erst nach der kompletten
a
Entwicklung und wenige Tage vor dem Release
geschrieben
Coverage f¨r manche Komponenten sinkt nach
u
Release mit der Zahl neuer Features
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 7 / 33
8. Einstellung zu Tests & Qualit¨tssicherung
a eZ Components
eZ Components
Aufw¨ndige Design- und Konzeptionsphase, gefolgt
a
von Test-Driven Development
F¨r Bugs existieren Regression-Tests
u
Ausgefallene Teststrategien
Nur Release wenn alle Bugs gefixed sind
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 8 / 33
9. Einstellung zu Tests & Qualit¨tssicherung
a Symfony
Symfony
Alle Komponenten weitestgehend gestestet
Keine Regression-Tests f¨r Bugfixes - die
u
vorhandene Testsuite soll nur nicht fehlschlagen
Nur Release wenn keine Tests fehlschlagen
Nicht nur Unit-Tests sondern auch eine
Test-Anwendung f¨r Integrationstests
u
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 9 / 33
10. Einstellung zu Tests & Qualit¨tssicherung
a CakePHP
CakePHP
Erst seit CakePHP 1.2.x uberhaupt Tests
¨
Viele Tests r¨ckwirkend auf existierenden Code
u
aufgesetzt
Positiv: Seitdem Regressiontests f¨r behobene Bugs
u
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 10 / 33
11. Große Zahl von Unittests
Große Zahl von Unittests
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 11 / 33
12. Große Zahl von Unittests
Große Zahl von Unittests
Entwarnung: Alle großen Frameworks haben viele
Unittests!
Zend Framework: 6000-10000 Tests (Je nach
aktivierten Optionen)
eZ Components: 6583 Tests
Symfony: 500 Testsuites
CakePHP: 88 Testsuites mit 1274 Tests
Viele andere bekanntere Frameworks haben eine
große Zahl von Unittests, z.B. FLOW3, Doctrine,
Agavi, SolarPHP
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 12 / 33
13. Wahl des Unit-Testing Frameworks
Wahl des Unit-Testing Frameworks
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 13 / 33
14. Wahl des Unit-Testing Frameworks PHPUnit
PHPUnit
Integriert sich hervorragend in Continuous
Integration Tools
Zahlreiche Qualit¨ts-Reports und zeilenweise
a
Code-Coverage
Verwendet von: Zend Framework, eZ Components
(sowie Agavi, FLOW3, Doctrine 2, SolarPHP,
u.v.m.)
eZ Components leider mit einem unhandlichem
eigenen Test-Runner, der Zugang zu neueren
Features von PHPUnit blockiert
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 14 / 33
15. Wahl des Unit-Testing Frameworks Lime
Lime
Eigenbau f¨r das Symfony Framework
u
Nur fern verwandt mit xUnit Testing Frameworks
Code-Coverage nur auf Klassen-Ebene
Un¨bersichtliche prozedurale Test-Skripte
u
$t = new lime_test (2 , new li me_out put_co lor () ) ;
$v = new sfValidatorPass () ;
$t - > diag ( ’ -> clean () ’) ;
$t - > is ( $v - > clean ( ’ ’) , ’ ’ , ’ -> clean () always returns
the value unmodified ’) ;
$t - > is ( $v - > clean ( null ) , null , ’ -> clean () always
returns the value unmodified ’) ;
sfValidatorPassTest.php, SVN Revision 9991
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 15 / 33
16. Wahl des Unit-Testing Frameworks SimpleTest
SimpleTest
Wird verwendet von: CakePHP
L¨uft ebenso wie Cake auch unter PHP4
a
CakePHP mit eigenem unausgereiften Test-Runner
im Web-Browser
Nur Klassen/Datei basierte Test-Coverage
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 16 / 33
17. Hohe Code-Coverage der Tests
Hohe Code-Coverage der Tests
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 17 / 33
18. Hohe Code-Coverage der Tests
Hohe Code-Coverage der Tests
Coverage ist Abh¨ngig von den installierten Extensions,
a
Datenbank- und Serviceverbindungen
Zend Framework: Viele Komponenten mit mehr
als 80%, einige auch mit mehr als 90%
Symfony: Durchschnitt 76% (Doctrine und Propel
Plugins fast ungetestet)
eZ Components: Alle Komponenten mit mehr als
80-90%
CakePHP: Funktioniert nicht f¨r alle
u
Komponenten (Fatal Errors, Keine Ergebnisse)
Coverage aber im Bereich 70-90%
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 18 / 33
19. Wenig Code-Duplikation in Tests
Wenig Code-Duplikation in Tests
PHP Copy Paste Detector
pear channel - discover pear . phpunit . de
pear install PHPUnit / PHPCPD
Test auf kleine Mengen an Copy Paste Code zur
Fixturegenerierung oder Assertions:
phpcpd -- min - lines 4 -- min - tokens 20 .
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 19 / 33
20. Wenig Code-Duplikation in Tests
Wenig Code-Duplikation in Tests
symfony: 1.48% Duplikate bei 18.823 Codezeilen.
Zend Framework: 6.04% Duplikate bei 238.844
Codezeilen
CakePHP: 10.02% Duplikate bei 74.015 Codezeilen
eZ Components (ohne ezcWebdav): 12.39%
Duplikate bei 168.321 Codezeilen
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 20 / 33
21. Subjektive Einsch¨tzung
a
Subjektive Einsch¨tzung
a
Einstellung
Unit-Tests
Testing-Framework
Coverage
Code-Duplikation
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 21 / 33
22. Tests als Dokumentation
Tests als Dokumentation
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 22 / 33
23. Tests als Dokumentation
Tests als Dokumentation
Tests erlauben Verst¨ndnis der API eines
a
Frameworks
Special Cases meist nur in Tests dokumentiert
Schwer verst¨ndliche Tests sind Argument gegen
a
Framework
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 23 / 33
24. Tests als Dokumentation
Obskure und Gigantische Tests
Obskure Tests sind sehr komplex und
unverst¨ndlich
a
Giant Tests sind sehr groß und daher
unverst¨ndlich
a
Beispiel: CakePHP Model Test
Beispiel: Zend Soap AutoDiscover
Beispiel: Symfony Form Test
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 24 / 33
25. Testing Bad-Practices
Testing Bad-Practices
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 25 / 33
26. Testing Bad-Practices Testger¨che
u
Integration-, Web-Surfer-, Slow-Test
Zend Service Amazon OnlineTest
public function setUp () {
$this - > _amazon = new Z en d _ Se r v ic e _ Am a z on (
TESTS_ZEND_SERVICE_AMAZON_ONLINE_ACCESSKEYID
);
$this - > _query = new Z e n d _ S e r v i c e _ A m a z o n _ Q u e r y (
TESTS_ZEND_SERVICE_AMAZON_ONLINE_ACCESSKEYID
);
$this - > _ ht tp Cl ie nt Ad ap te r = new
Z e n d _ H t t p _ C l i e n t _ A d a p t e r _ S o c k e t () ;
$this - > _amazon - > getRestClient () -> getHttpClient ()
-> setAdapter ( $this - > _h ttp Cl ie nt Ad ap te r ) ;
// terms of use compliance : no more than one
query per second
sleep (1) ;
}
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 26 / 33
27. Testing Bad-Practices Testger¨che
u
Web-Surfer-, Assertionless
Zend Service Amazon OnlineTest
public function t e s t I t e m S e a r c h M u s i c M o z a r t ()
{
$resultSet = $this - > _amazon - > itemSearch ( array (
’ SearchIndex ’ = > ’ Music ’ ,
’ Keywords ’ = > ’ Mozart ’ ,
’ ResponseGroup ’ = > ’ Small , Tracks , Offers ’
));
foreach ( $resultSet as $item ) {
$this - > assertTrue (
$item instanceof Z e n d _ S e r v i c e _ A m a z o n _ I t e m
);
}
}
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 27 / 33
28. Testing Bad-Practices Testger¨che
u
Global State
Zend Controller Action Helper ViewRendererTest
protected function setUp ()
{
$this - > request = new Z e n d _ C o n t r o l l e r _ R e q u e s t _ H t t p () ;
$this - > response = new Z e n d _ C o n t r o l l e r _ R e s p o n s e _ H t t p () ;
$this - > front = Z e n d _ C o n t r o l l e r _ F r o n t :: getInstance () ;
$this - > front - > resetInstance () ;
$this - > front - > add Mo du le Di re ct or y ( $this - > somePath )
-> setRequest ( $this - > request )
-> setResponse ( $this - > response ) ;
$this - > helper = new
Z e n d _ C o n t r o l l e r _ A c t i o n _ H e l p e r _ V i e w R e n d e r e r () ;
Z e n d _ C o n t r o l l e r _ A c t i o n _ H e l p e r B r o k e r :: addHelper ( $this
- > helper ) ;
}
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 28 / 33
29. Testing Bad-Practices Testger¨che
u
Fragile and Indirect Tests
ezcMvcToolsConfigurableDispatcherTest
function t e s t E x t e r n a l R e d i r e c t ()
{
$config = new s im p l eC o n fi g u ra t i on () ;
$config - > route = ’ IRController ’;
$dispatcher =
new e z c M v c C o n f i g u r a b l e D i s p a t c h e r ( $config ) ;
$dispatcher - > run () ;
self :: assertEquals (
quot; BODY : Name : name , Vars : array ([ CR ] quot; .
quot; ’ nonRedirVar ’ = > 4 ,[ CR ] quot; .
quot; ’ ReqRedirVar ’ = > 4 ,[ CR ]) quot; ,
$config - > store
);
}
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 29 / 33
30. Testing Bad-Practices Testger¨che
u
Assertionless
Zend Pdf DrawingTest
public function testDrawing ()
{
$pdf = new Zend_Pdf () ;
// Etwa 150 Zeilen Bilder , Text usw . hinzufuegen
$pdf - > save ( dirname ( __FILE__ ) . ’/ _files / output .
pdf ’) ;
unset ( $pdf ) ;
$pdf1 = Zend_Pdf :: load ( dirname ( __FILE__ ) . ’/
_files / output . pdf ’) ;
$this - > assertTrue ( $pdf1 instanceof Zend_Pdf ) ;
unset ( $pdf1 ) ;
unlink ( dirname ( __FILE__ ) . ’/ _files / output . pdf ’) ;
}
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 30 / 33
31. Testing Bad-Practices Testger¨che
u
Erkenntnisse
Vor der Nutzung von Framework Komponenten in
die Tests schauen
Eigene Tests f¨r Anforderungen schreiben und wenn
u
m¨glich zum Framework beisteuern
o
Bei kritischen Business-Anwendungen eines schlecht
getesteten Frameworks nach Alternativen umsehen
oder selber implementieren
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 31 / 33
32. Testing Bad-Practices Testger¨che
u
Attribution
Snetterton Classic Car Racing, Martin Pettitt
http://www.flickr.com/photos/mdpettitt/2659028559/
House No More, nukeit1
http://www.flickr.com/photos/nukeit1/33325525/
March of the Baby Turtles, clearlyambiguous
http://www.flickr.com/photos/clearlyambiguous/48185613/
Cannon and Meade, unforth
http://www.flickr.com/photos/unforth/3414535842
Swiss Knife, airosan
http://www.flickr.com/photos/airosan/2232394342
Pile of Paper, pburghstever
http://www.flickr.com/photos/pburghstever/3328140917
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 32 / 33
33. Testing Bad-Practices Testger¨che
u
Thank You!
B. Eberlei (SimpleThings GmbH) Framework-Qualit¨t
a IPC Spring, Mai 2009 33 / 33