Testiohjatun kehityksen työnkulku
Ohjatkaa suunnittelua red-green-refactor-syklillä.
Testiohjatun kehityksen työnkulku on ilmainen PHP Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu PHP Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. PHP Academy-kurssilla on yhteensä 4 oppituntia.
TDD on suunnittelutyökalu
Testivetoinen kehitys esitellään usein testaustekniikkana, mutta sen todellinen arvo on suunnittelupaine. Kun kirjoitat testin ensin, joudut määrittelemään olion julkisen rajapinnan, riippuvuudet ja sopimuksen ennen minkään toteutuksen kirjoittamista. Testit ovat sivutuote; parempi suunnittelu on varsinainen tuote.
Red, Green, Refactor
Työkierto koostuu kolmesta tiukasta vaiheesta:
- Red — kirjoita seuraavaa pientä toimintoa varten testi, joka epäonnistuu. Sen on epäonnistuttava oikeasta syystä.
- Green — kirjoita vähimmäismäärä koodia testin läpäisemiseksi, vaikka toteutus olisi ruma.
- Refactor — siisti toteutusta ja testejä pysyen vihreässä tilassa.
Kurinalaisuus on tärkeää: älä koskaan ohita Red-vaihetta (saatat testata tyhjää), äläkä rakenna Green-vaiheessa liikaa.
Red: kirjoita epäonnistuva testi ensin
Rakennamme PriceCalculator-luokan, joka soveltaa prosenttialennusta. Aloita testaamalla toimintoa, jota ei vielä ole olemassa. Testin suorittamisen pitäisi epäonnistua, koska luokkaa ei ole määritelty — tämä on kelvollinen Red-vaihe.
<?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));
}
}
Green: vähimmäistoteutus, joka läpäisee testin
Kirjoita nyt pienin mahdollinen toteutus, joka muuttaa tilanteen vihreäksi. Älä lisää vielä pyöristyssääntöjä, kelpoisuuden tarkistusta tai valuuttakäsittelyä — mikään epäonnistuva testi ei vielä vaadi niitä.
<?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)
Yleisyyden ajaminen trianguloinnilla
Yksi testi voidaan läpäistä kovakoodatulla ratkaisulla. Triangulointi — toisen, erilaisen esimerkin lisääminen — pakottaa toteutuksen yleistämään. Lisää tapaus, jota suoraviivainen ratkaisu ei voi jäljitellä, jolloin todellinen kaava on pakko toteuttaa.
<?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));
}
}
Reunaehdot määrittelyiksi
TDD:ssä uusi vaatimus tarkoittaa uutta epäonnistuvaa testiä. Oletetaan, että negatiiviset alennukset eivät ole sallittuja. Kirjoita ensin testi, joka odottaa poikkeusta; se epäonnistuu, koska mikään ei vielä heitä poikkeusta. Testi dokumentoi sopimuksen.
<?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);
}
}
Jälleen Green, sitten Refactor
Lisää tarkistus uuden testin läpäisemiseksi ja refaktoroi sitten luottavaisin mielin — olemassa olevat testit havaitsevat taantumat. Huomaa, että otimme pyöristyksen käyttöön vasta, kun testi (tai tunnettu vaatimus) perusteli sen.
<?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)
Data providerit tiivistävät esimerkit
Kun toiminta on vakiintunut, yhdistä useat esimerkkiparit yhdeksi parametrisoiduksi testiksi, joka käyttää data provideria. Näin Red/Green-työkierto pysyy nopeana ja tarkoitus näkyy taulukkona.
<?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],
];
}
}
Pidä työkierto nopeana
TDD toimii vain, jos palautekierto kestää sekunteja eikä minuutteja. Käytännön keinoja:
- Suorita yksi tiedosto tai suodata testit:
phpunit --filter test_full_discount_is_free. - Käytä
--testdox-valitsinta lukeaksesi testit toiminnan määrittelynä. - Pidä yksikkötestit vapaina I/O-toiminnoista — sisäisessä työskentelykierrossa ei tietokantaa, verkkoa tai tiedostojärjestelmää.
vendor/bin/phpunit --testdox --filter PriceCalculatorRefaktoroi myös testit
Refactor-vaihe koskee testikokoelmaa, ei vain tuotantokoodia. Poista toistoa apufunktioilla ja setUp()-metodilla, nimeä testit toiminnan mukaan ja poista testit, jotka eivät enää varmista mitään merkityksellistä. Testit ovat koodia, jota ylläpidät ikuisesti — käsittele niitä yhtä huolellisesti.
<?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 muovaa riippuvuuksia
Koska kirjoitat testin ensin, hankalat riippuvuudet tulevat heti näkyviin. Jos luokkaa on vaikea alustaa testissä, se on suunnittelupalautetta: injektoi yhteistyökumppanit sen sijaan, että loisitte ne suoraan new-operaattorilla. Alla olevasta alennuslaskurista tulee testattava, kun sen pyöristyspolitiikka annetaan sille eikä kovakoodata — TDD toi tämän rajapinnan esiin.
<?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.
Pikatarkistus
Mikä on Red-vaiheen tarkoitus?
Kertaus
Harjoittelit TDD:tä suunnittelukurin avulla:
- Red-Green-Refactor: epäonnistuva testi, vähimmäistoteutus ja sen jälkeen siistiminen testien pysyessä vihreinä.
- Triangulointi pakottaa yleiseen ratkaisuun; uudet vaatimukset tulevat uusina epäonnistuvina testeinä.
- Data providerit tiivistävät vakiintuneet tapaukset;
--filter/--testdoxpitävät työkierron nopeana. - Refaktoroi myös testisi — ne ovat pitkäikäistä koodia.
Seuraavaksi: joustavat testidoublet Mockerylla.
Opi PHP tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 49
- Oppitunnit
- 195
Usein kysytyt kysymykset
Onko oppitunti ”Testiohjatun kehityksen työnkulku” ilmainen?
Kyllä – oppitunnin ”Testiohjatun kehityksen työnkulku” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko PHP Academy-kurssin, päivitä CoddyKit PROhon. PHP Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Testiohjatun kehityksen työnkulku”?
Ohjatkaa suunnittelua red-green-refactor-syklillä. Harjoittelet PHP Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni PHP Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin PHP Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.
Kuinka kauan ”Testiohjatun kehityksen työnkulku”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä PHP Academy-oppitunnilla?
Kyllä. Jokainen PHP Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Testiohjatun kehityksen työnkulku
- Mockaus ja stubit Mockerylla
- Integraatio- ja toiminnallinen testaus
- Mutaatiotestaus Infectionilla