TDD AI:n kanssa — ensimmäinen projekti
Tässä oppitunnissa yhdistämme kaikki moduulin taidot: projektisäännöt, skillit, promptauksen ja speksit. Rakennamme ensimmäisen projektin käyttäen Test-Driven Development -prosessia yhdessä AI:n kanssa.
TDD: Red → Green → Refactor
TDD (Test-Driven Development)
TDD on kehitysprosessi, jossa testit kirjoitetaan ENNEN toteutusta. Sykli on: Red (kirjoita failaava testi) → Green (kirjoita minimikoodi, joka passaa) → Refactor (paranna koodia testien suojassa). AI:n kanssa TDD on erityisen tehokas, koska testit toimivat automaattisena verifointina AI:n tuottamalle koodille.
Miksi TDD + AI?
AI tuottaa koodia nopeasti, mutta miten tiedät, onko se oikeaa koodia? TDD ratkaisee tämän:
| Vaihe | Ilman TDD | TDD:n kanssa |
|---|---|---|
| AI generoi koodin | "Näyttää hyvältä?" | Testit kertovat onko oikein |
| Muutos rikkoo jotain | Huomaat tuotannossa | Testit failaavat heti |
| Refaktorointi | Pelottaa | Testit suojaavat |
| Regressiot | Yleisiä | Harvinaisia |
TDD-sykli AI:n kanssa
Vaihe 1: RED — Kirjoita testi ensin
// lib/validation/__tests__/email.test.ts
import { describe, it, expect } from 'vitest'
import { validateEmail } from '../email'
describe('validateEmail', () => {
it('should accept valid email', () => {
expect(validateEmail('user@example.com')).toEqual({
valid: true,
email: 'user@example.com',
})
})
it('should reject email without @', () => {
expect(validateEmail('invalid')).toEqual({
valid: false,
error: 'Virheellinen sähköpostiosoite',
})
})
it('should reject empty string', () => {
expect(validateEmail('')).toEqual({
valid: false,
error: 'Sähköposti on pakollinen',
})
})
it('should trim whitespace', () => {
expect(validateEmail(' user@example.com ')).toEqual({
valid: true,
email: 'user@example.com',
})
})
})Testit failaavat, koska validateEmail-funktiota ei ole vielä olemassa. Tämä on Red-vaihe.
Vaihe 2: GREEN — Anna AI:n toteuttaa
Anna AI:lle testin ja pyydä toteutusta:
Toteuta validateEmail-funktio, joka läpäisee
kaikki nämä testit.
Noudata sääntöjä:
- TypeScript strict mode
- Palauta tyypitetty Result-objekti
- Ei ulkoisia kirjastojaAI tuottaa toteutuksen:
// lib/validation/email.ts
type ValidationResult =
| { valid: true; email: string }
| { valid: false; error: string }
export function validateEmail(input: string): ValidationResult {
const trimmed = input.trim()
if (!trimmed) {
return { valid: false, error: 'Sähköposti on pakollinen' }
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (!emailRegex.test(trimmed)) {
return { valid: false, error: 'Virheellinen sähköpostiosoite' }
}
return { valid: true, email: trimmed }
}Aja testit — kaikki vihreällä. Tämä on Green-vaihe.
Vaihe 3: REFACTOR — Paranna koodia
Testien suojassa voit pyytää AI:ta refaktoroimaan:
Refaktoroi tämä funktio:
- Erota validointisäännöt omiksi funktioiksi
- Lisää JSDoc-dokumentaatio
- Varmista että regex on turvallinen (ei ReDoS)Pro tip
TDD:ssä testit ovat turvaverkko. Kun testit ovat olemassa, voit pyytää AI:ta tekemään rohkeita refaktorointeja — testit kertovat heti jos jokin meni rikki.
Käytännön projekti: Todo-API
Rakennetaan yksinkertainen Todo-API TDD:llä ja AI:n avulla.
Speksi
# Feature: Todo API
## AC1: Luonti
Given tyhjä todo-lista
When POST /api/todos { title: "Osta maitoa" }
Then palautaa 201 + todo-objektin id:llä
## AC2: Listaus
Given 2 todoa tietokannassa
When GET /api/todos
Then palautaa listan kahdella todolla
## AC3: Valmistuminen
Given olemassa oleva todo
When PATCH /api/todos/:id { completed: true }
Then todo merkitään valmiiksi
## AC4: Validointi
Given tyhjä title
When POST /api/todos { title: "" }
Then palautaa 400 + virheilmoitusTDD-prosessi
- Kirjoita testit AC1:lle →
__tests__/api/todos.test.ts - Anna AI:n toteuttaa →
app/api/todos/route.ts - Aja testit → Kaikki vihreällä?
- Toista AC2–AC4 → Jatka samaa sykliä
- Refaktoroi → Pyydä AI:ta parantamaan koodia
Testin ja toteutuksen suhde
AC1 (testi) → POST handler (koodi) → ✅ Pass
AC2 (testi) → GET handler (koodi) → ✅ Pass
AC3 (testi) → PATCH handler (koodi) → ✅ Pass
AC4 (testi) → Validointi (koodi) → ✅ Pass
AI:n rooli TDD:ssä
| TDD-vaihe | Ihmisen rooli | AI:n rooli |
|---|---|---|
| Red | Kirjoittaa testin (tai tarkistaa) | Voi ehdottaa testejä |
| Green | Tarkistaa toteutuksen | Generoi toteutuksen |
| Refactor | Päättää refaktoroinnin suunnan | Toteuttaa refaktoroinnin |
Kaksi tapaa, joilla AI rikkoo TDD:n huomaamattasi
Yllä oleva taulukko kuvaa sitä, miten homma menee kun se menee oikein. Käytännössä malli rikkoo sykliä kahdella tavalla, ja kumpikin näyttää onnistumiselta:
1. Malli kirjoittaa testin ja toteutuksen samalla vastauksella. Silloin testi on kirjoitettu koodin mukaan, ei speksin mukaan — ja se menee läpi ensimmäisellä ajolla. Punaista vaihetta ei koskaan ollut, joten testi ei todista mitään; se vain kuvailee sitä, mitä koodi sattuu tekemään.
Miten huomaat: testi menee läpi heti, etkä ole nähnyt sen epäonnistuvan. Mitä teet: pyydä testi erikseen, aja se, ja katso että se on punainen ennen kuin pyydät riviäkään toteutusta.
2. Malli “korjaa” testin, kun toteutus ei mene läpi. Pyydät korjaamaan epäonnistuvan testin, ja malli muuttaa odotusarvon vastaamaan koodia. Testit ovat taas vihreitä, ja hyväksymiskriteeri on hiljaa kadonnut.
Miten huomaat: vertaa testin odotusarvoa speksiin, älä koodiin. Mitä teet: sano se ääneen promptissa — “speksi on lähde; jos testi on väärässä, korjaa ensin speksi ja sano se minulle”. Jos testi oikeasti on väärin, se on speksivirhe, ja se pitää korjata speksissä ensin.
Pro tip
Molemmat virheet tulevat samasta syystä: mallille “kaikki vihreänä” on onnistumisen merkki, ja se optimoi sitä kohti. Sinulle vihreä on merkitykselli vain, jos olet nähnyt saman testin punaisena. Punainen vaihe ei ole byrokratiaa — se on ainoa hetki, jolloin testi todistaa olevansa testi.
AI-TDD-periaate
TDD:ssä ihminen omistaa speksin ja hyväksymiskriteerit, AI omistaa toteutuksen. Testit ovat sopimus näiden välillä — ne varmistavat, että AI:n tuottama koodi tekee sen mitä ihminen halusi.
Mikä on TDD:n tärkein hyöty AI-avusteisessa kehityksessä?
TDD-harjoitus: Rakennetaan laskuri
Toteuta yksinkertainen laskurimoduuli TDD:llä: 1) Kirjoita testit ensin (add, subtract, multiply, divide + virhetilanne nollalla jako), 2) Anna AI:n toteuttaa funktiot, 3) Aja testit, 4) Refaktoroi. Bonus: lisää testit edge caseille (erittäin suuret luvut, desimaalit).
Moduulin yhteenveto
Olet nyt oppinut Greenfield-moduulin kaikki perustaidot:
- Työkalut & säännöt — AI-koodaustyökalut ja AGENTS.md
- Skills — Kyvykkyyksien dokumentointi ja löydettävyys
- Promptaus — Konteksti → Tehtävä → Rajoitteet
- Speksit — Given-When-Then hyväksymiskriteerit
- TDD — Red → Green → Refactor AI:n kanssa
Session 1 project → portfolio
Your own small greenfield app
By the end of Session 1, you have a small greenfield app you built AI-assisted using a TDD cycle (Red → Green → Refactor). Anything goes — a weather CLI, todo app, bookmark API — small but working.
What to capture
Repo URL, short description of what you built, the AI tools you used (Cursor / Claude Code / Copilot), and one screenshot or roughly 30 seconds of demo video. Tags are added automatically.
Seuraavassa moduulissa siirrymme Brownfield-kehitykseen: miten turvallisesti muokata olemassa olevaa koodikantaa AI:n avulla.