Het verschil tussen unit tests en integratietests (en functionele tests als de derde trap) wordt nog wel eens aangehaald, maar ik vind het persoonlijk best wel belangrijk om te weten waar je het over hebt, omdat je namelijk een idee moet hebben van
wat je precies aan het testen bent.
Een van de belangrijkste aspecten van een test is namelijk een idee van wat de test precies
covert. Met andere woorden, als datgene wat hij covert stukgaat, dan moet de test falen. Je zou zeggen dat het handig is als een test zoveel mogelijk covert, maar daarmee identificeert de test ook des te minder goed wat er precies stuk is zodra dat aan de orde is. Bijvoorbeeld: door een applicatie heenklikken covert heel veel, maar als je foutmeldingen krijgt moet je stacktraces gaan napluizen om te zien wat er nou precies aan de hand is.
Daarom is het een goed idee om zoveel mogelijk te coveren met
unit tests. Met een
unit test maak je een test met een aantal cases (omstandigheden), die 1 stukje code
onafhankelijk van andere "werkzame" componenten testen. Het voordeel van je "units under test" zo klein mogelijk (atomair) te houden is dat als een unit test faalt, de case (de omstandigheden) heel duidelijk identificeert waarin de unit (het stuk code dat getest wordt) faalt.
Als je unit test daarvoor data nodig heeft, dan zijn dat in principe dus gewoon verschillende testcases. PHPUnit (het testing framework dat ik het beste ken) heeft daarvoor iets dat je een 'dataprovider' noemt die 'data fixtures' levert voor een testcase. Dat is handig als je verschillende stukjes data nodig hebt om dezelfde testcode mee uit te voeren. Maar tenzij je een enorme hoeveelheid testdata aan relevante (en onderscheidende) test cases hebt, is dat eigenlijk alleen maar een convenience en niet eens per se een best practice.
Voor unit tests zijn termen als "Principle of Least Knowledge" en "Design by Contract" handig om op te googlen. Als je iets niet goed kunt unit testen, is er waarschijnlijk sprake van een overtreding van "Demeter's Law" en geen of slecht geimplementeerd "Design by Contract". Andersom, als je heel makkelijk ergens een test voor kunt maken is er waarschijnlijk sprake van weinig dependencies, of dependencies die zich netjes aan een "design by contract" houden.
Daarom komen in het kader van unit tests ook altijd de termen "mock" en "stub" aan de orde. In het kort komt het er op neer dat als je een "stub" maakt, je een soort voorgeprogrammeerde implementatie van een dependency aan de unit under test meegeeft . Een mock gebruik je om de interne werking van de unit under test te verifieren (denk aan "Houdt de unit er wel rekening mee dat de return value van deze method ook
null kan zijn in sommige gevallen?"). [1]
Heb je het echter over integratietests, dan wil je weten of al die units die je aan elkaar knoopt als geheel doen wat ze moeten doen. Meestal gebruik je bij integratietests geen stubs en/of mocks meer maar ga je na of een "real life" implementatie doet wat het moet doen. Daarom heb je bij integratietests ook vaak externe dependencies (zoals een database, een internetverbinding, of zelfs een filesystem). Dat neigt al een beetje naar functioneel testen. In principe is het een good practice (vind ik

) om integratietests alleen toe te passen waar je situaties mee covert die
wel kritisch zijn maar
niet of relatief lastig in een unit test of een functionele test te vatten zijn.
Voor webapplicaties en websites is het in de praktijk namelijk het meest praktisch en toekomstvast om vooral te streven naar hoge code coverage met unit tests, en daarnaast vooral functionele (eindgebruikers) tests te maken waarmee je vaststelt of de geleverde functionaliteit werkt. Daarvoor kun je bijvoorbeeld selenium inzetten, en ik ben zelf wel gecharmeerd van Behat (en gebruik dat ook regelmatig) om selenium (of andere web drivers) mee aan te sturen. Je kunt ook functionele tests maken met behulp van PHPUnit, en dat is natuurlijk verwarrend, maar dat wil niet zeggen dat de tests dan ook automatisch unit tests zijn. Ik weet van vrijwel alle webplatforms dat er analoge tools beschikbaar zijn, ik weet niet precies wat je aan het bouwen bent en waarmee, maar ga vooral op onderzoek uit. If the tool fits your purpose well, you're probably doing the right thing.
[1]
http://martinfowler.com/articles/mocksArentStubs.html