De Test-Driven-Development-workflow
Stuur het ontwerp met de red-green-refactorcyclus.
De Test-Driven-Development-workflow is een gratis PHP Academy-les op CoddyKit. Dit is les 1 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject PHP Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus PHP Academy bevat in totaal 4 lessen.
TDD is een ontwerphulpmiddel
Testgestuurde ontwikkeling wordt vaak gepresenteerd als een testtechniek, maar de echte waarde ervan is ontwerpdruk. Door eerst de test te schrijven, moet je de openbare interface, de afhankelijkheden en het contract van een object definiëren voordat je implementatie schrijft. De tests zijn een bijproduct; een beter ontwerp is het product.
Rood, groen, refactoren
De cyclus bestaat uit drie strikte fasen:
- Rood — schrijf een falende test voor het volgende kleine gedrag. De test moet om de juiste reden falen.
- Groen — schrijf de minimale code waarmee de test slaagt, ook als die lelijk is.
- Refactoren — ruim implementatie en tests op terwijl alles groen blijft.
Discipline is belangrijk: sla Rood nooit over, want dan test je misschien niets, en bouw tijdens Groen nooit meer dan nodig.
Rood: schrijf eerst de falende test
We bouwen een PriceCalculator die een procentuele korting toepast. Begin met een test voor gedrag dat nog niet bestaat. Als je de test uitvoert, moet die falen omdat de klasse niet is gedefinieerd — dat is een geldige Rood-fase.
<?php
use PHPUnit\Framework\TestCase;
final class PriceCalculatorTest extends TestCase
{
public function test_applies_a_percentage_discount(): void
{
$calc = new PriceCalculator();
// 100 with 10% off -> 90.0
self::assertSame(90.0, $calc->withDiscount(100.0, 10));
}
}
Groen: minimale code om te slagen
Schrijf nu de kleinst mogelijke implementatie waarmee de tests slagen. Voeg nog geen afrondingsregels, validatie of valutaverwerking toe — er is nog geen falende test die daarom vraagt.
<?php
final class PriceCalculator
{
public function withDiscount(float $amount, float $percent): float
{
return $amount - ($amount * $percent / 100);
}
}
$calc = new PriceCalculator();
var_dump($calc->withDiscount(100.0, 10)); // float(90)
Triangulatie dwingt generaliteit af
Met één test kun je volstaan door iets hard te coderen. Triangulatie — een tweede, ander voorbeeld toevoegen — dwingt de implementatie om algemeen toepasbaar te worden. Voeg een geval toe dat de triviale oplossing niet kan namaken, zodat de echte formule naar voren komt.
<?php
use PHPUnit\Framework\TestCase;
final class PriceCalculatorTest extends TestCase
{
public function test_zero_percent_is_unchanged(): void
{
self::assertSame(50.0, (new PriceCalculator())->withDiscount(50.0, 0));
}
public function test_full_discount_is_free(): void
{
self::assertSame(0.0, (new PriceCalculator())->withDiscount(50.0, 100));
}
}
Randgevallen als specificaties afdwingen
Bij TDD is een nieuwe vereiste een nieuwe falende test. Stel dat negatieve kortingen ongeldig zijn. Schrijf eerst de test die een uitzondering verwacht; die faalt omdat er nog niets een uitzondering opwerpt. De test legt het contract vast.
<?php
use PHPUnit\Framework\TestCase;
final class PriceCalculatorValidationTest extends TestCase
{
public function test_rejects_negative_discount(): void
{
$this->expectException(\InvalidArgumentException::class);
(new PriceCalculator())->withDiscount(100.0, -5);
}
}
Opnieuw groen, daarna refactoren
Voeg de controle toe zodat de nieuwe test slaagt en refactor daarna met vertrouwen — de bestaande tests vangen regressies op. Merk op dat we afronding ook pas hebben geïntroduceerd toen een test of een bekende vereiste dat rechtvaardigde.
<?php
final class PriceCalculator
{
public function withDiscount(float $amount, float $percent): float
{
if ($percent < 0 || $percent > 100) {
throw new \InvalidArgumentException('percent must be 0..100');
}
return round($amount - ($amount * $percent / 100), 2);
}
}
var_dump((new PriceCalculator())->withDiscount(19.99, 15)); // float(16.99)
Dataproviders bundelen voorbeelden
Zodra gedrag stabiel is, bundel je veel voorbeeldparen in één geparametriseerde test met een dataprovider. Zo blijft de lus tussen Rood en Groen snel en blijft de bedoeling leesbaar in een tabel.
<?php
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\DataProvider;
final class DiscountTableTest extends TestCase
{
#[DataProvider('cases')]
public function test_discounts(float $amount, float $pct, float $expected): void
{
self::assertSame($expected, (new PriceCalculator())->withDiscount($amount, $pct));
}
public static function cases(): array
{
return [
'no discount' => [100.0, 0, 100.0],
'ten percent' => [100.0, 10, 90.0],
'free' => [100.0, 100, 0.0],
];
}
}
Houd de lus snel
TDD werkt alleen als de terugkoppellus seconden duurt, geen minuten. Praktische middelen:
- Voer één bestand uit of gebruik een filter:
phpunit --filter test_full_discount_is_free. - Gebruik
--testdoxom tests als gedragsspecificatie te lezen. - Houd unittests vrij van I/O — geen database, netwerk of bestandssysteem in de binnenste lus.
vendor/bin/phpunit --testdox --filter PriceCalculatorRefactor ook je tests
De refactorfase geldt voor de testsuite, niet alleen voor productiecode. Verwijder duplicatie met hulpfuncties en setUp(), geef tests namen op basis van gedrag en verwijder tests die niets betekenisvols meer controleren. Tests zijn code die je voor altijd onderhoudt — behandel ze met dezelfde zorg.
<?php
use PHPUnit\Framework\TestCase;
final class PriceCalculatorTest extends TestCase
{
private PriceCalculator $calc;
protected function setUp(): void
{
$this->calc = new PriceCalculator(); // shared setup, no duplication
}
public function test_ten_percent(): void
{
self::assertSame(90.0, $this->calc->withDiscount(100.0, 10));
}
}
TDD vormt afhankelijkheden
Omdat je de test eerst schrijft, vallen omslachtige afhankelijkheden meteen op. Als je een klasse in een test moeilijk kunt instantiëren, is dat ontwerpfeedback: injecteer samenwerkende objecten in plaats van ze binnenin met new te maken. De kortingscalculator hieronder wordt testbaar door het afrondingsbeleid te accepteren in plaats van dit hard te coderen — TDD heeft dat aansluitpunt naar voren gebracht.
<?php
interface RoundingPolicy { public function round(float $v): float; }
final class PriceCalculator
{
public function __construct(private RoundingPolicy $rounding) {}
public function withDiscount(float $amount, float $percent): float
{
return $this->rounding->round($amount - ($amount * $percent / 100));
}
}
// Tests inject a deterministic RoundingPolicy; no hidden global behavior.
Snelle controle
Wat is het doel van de stap Rood?
Samenvatting
Je hebt TDD als ontwerpdiscipline beoefend:
- Rood-Groen-Refactoren: falende test, minimale code en daarna opruimen terwijl alles groen blijft.
- Triangulatie dwingt generaliteit af; nieuwe vereisten verschijnen als nieuwe falende tests.
- Dataproviders bundelen stabiele gevallen;
--filter/--testdoxhouden de lus snel. - Refactor ook je tests — het is code die lang meegaat.
Volgende: flexibele testdubbels met Mockery.
Leer PHP met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 49
- Lessen
- 195
Veelgestelde vragen
Is de les “De Test-Driven-Development-workflow” gratis?
Ja — de volledige tekst van “De Test-Driven-Development-workflow” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus PHP Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus PHP Academy bevat in totaal 4 lessen.
Wat leer ik in “De Test-Driven-Development-workflow”?
Stuur het ontwerp met de red-green-refactorcyclus. Je oefent met PHP Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met PHP Academy te beginnen?
Ervaring vooraf is niet nodig. PHP Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 1 van 4.
Hoe lang duurt de les “De Test-Driven-Development-workflow”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over PHP Academy?
Ja. Elke les over PHP Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- De Test-Driven-Development-workflow
- Mocking en stubbing met Mockery
- Integratie- en functioneel testen
- Mutation testing met Infection