Sobes.tech
Middle

Kuidas testid ja TDD-metodoloogia mõjutavad koodi organiseerimist?

sobes.tech AI

Vastus AI-lt

Testid ja TDD avaldavad olulist mõju koodi organiseerimisele:

  1. Dekonstruktsioon ja moodulid: Testide kirjutamine enne või protsessi ajal soodustab väikeste, kergesti testitavate funktsioonide ja komponentide loomist, mis parandab moodulit ja vähendab sõltuvust.

  2. Puhtus ja arusaadavus: Testid toimivad kui elav dokumentatsioon ja näited koodi kasutamisest. Halvasti kujundatud, keeruline (spagetikood) on raske testida. See julgustab kirjutama puhtamat ja arusaadavamat koodi.

  3. API täiustamine: Testide kirjutamise protsess sunnib kasutama loodavate moodulite API-d väljaspool. See aitab varakult tuvastada ebamugavaid või ebaühtlasi API osi ning parandada neid enne laialdast kasutuselevõttu.

  4. Refaktoreerimise tugi: Kogupikk testide komplekt annab kindlustunde refaktoreerimisel. Testid kiiresti avastavad regressioone, võimaldades turvaliselt muuta koodi sisemist struktuuri, mitte mõjutades selle välist käitumist.

  5. Kiire vigade avastamine: Testid võimaldavad avastada vigu varases arenguetapis, mis oluliselt vähendab nende parandamise kulusid võrreldes tootmises avastamisega.

Näide, kuidas organiseerida koodi, mis on inspireeritud TDD-st (Golang):

package calculator // Funktsioonide pakett

import "errors" // Sõltuvused

// Add liidab kaks täisarvu.
func Add(a, b int) int {
	return a + b // Lihtne loogika
}

// Divide jagab num den-iga. Tagastab vea, kui den on 0.
func Divide(num, den int) (int, error) {
	if den == 0 {
		// Selgelt käsitletud äärejuhtumid, kergesti testitavad
		return 0, errors.New("jagamine nulliga on lubamatu")
	}
	return num / den, nil
}

Vastavad testid:

package calculator // Testid samas paketis, kuid eraldi failis (_test.go)

import (
	"testing"
)

// TestAdd kontrollib funktsiooni Add.
func TestAdd(t *testing.T) {
	// Testjuhtumid erinevate sisendandmetega
	testCases := []struct {
		name   string
		a, b   int
		expected int
	}{
		{"Positiivsed numbrid", 1, 2, 3},
		{"Negatiivsed numbrid", -1, -2, -3},
		{"Segased numbrid", -1, 2, 1},
		{"Null ja positiivne", 0, 5, 5},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) { // Kasutades t.Run testide struktureerimiseks
			result := Add(tc.a, tc.b) // Kutsuge testitav funktsioon
			if result != tc.expected {
				// Täpne veateade
				t.Errorf("Add(%d, %d): Oodatud %d, saadud %d", tc.a, tc.b, tc.expected, result)
			}
		})
	}
}

// TestDivide kontrollib funktsiooni Divide.
func TestDivide(t *testing.T) {
	testCases := []struct {
		name        string
		num, den    int
		expected int
		expectError bool
	}{
		{"Positiivne jagamine", 10, 2, 5, false},
		{"Negatiivne tulemus", 10, -2, -5, false},
		{"Jagamine ühega", 7, 1, 7, false},
		{"Jagamine nulliga", 5, 0, 0, true}, // Juhtum vea jaoks
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			result, err := Divide(tc.num, tc.den)

			if tc.expectError {
				if err == nil {
					// Kontrollige, kas oodatakse viga
					t.Errorf("Divide(%d, %d): Oodatud viga, aga seda ei olnud", tc.num, tc.den)
				}
			} else {
				if err != nil {
					// Kontrollige, kas viga puudub, kui seda ei oodata
					t.Errorf("Divide(%d, %d): Saadud ootamatu viga: %v", tc.num, tc.den, err)
				}
				if result != tc.expected {
					// Kontrollige tulemust edukal täitmisel
					t.Errorf("Divide(%d, %d): Oodatud %d, saadud %d", tc.num, tc.den, tc.expected, result)
				}
			}
		})
	}
}