Felhasználói eszközök

Eszközök a webhelyen


oktatas:programozas:tdd

< Programozás

TDD

A TDD

A TDD a Test-driven development rövidítése, magyarul teszt-vezérelt fejlesztés. Egy szoftverfejlesztési folyamat, amely nagyon rövid fejlesztési ciklusok ismétléséből áll. Kent Beck amerikai mérnök alkotta meg, vagy újra felfedezte.

Tulajdonképpen a kód egy részét, ami jellemzően egy függvény, eljárás vagy metódus, teszteljük, újra és újra. A vizsgált részt egy egységként vagy angolul unitként szokás emlegetni. Így egységteszt vagy unit tesztnek is hívják.

Két kódot fejlesztünk párhuzamosan:

  • teszt kód
  • ipari kód

A fejlesztést a teszt megírásával kezdjük, akkor amikor még nem is áll rendelkezésre az ipari kód.

A mai integrált fejlesztői környezetek támogatják a tesztek írását. Így könnyedén használhatjuk a teszt-vezérelt fejlesztésre.

A TDD folyamata

A tesztelést Java objektum orientált kódokkal tekintjük meg.

Három osztályt készítünk.

  • főosztályt
  • teszt osztályt
  • hasznos kódot tartalmazó osztály

A TDD lépései

  1. fejlesztjük a tesztet
    1. csak annyit fejlesztünk rajta, hogy az ne teljesüljön
    2. futtatjuk a tesztet
  2. fejlesztjük az ipari kódot
    1. csak annyit fejlesztünk, hogy teljesüljön a teszt
    2. futtatjuk a tesztet
  3. újratervezünk, ha szükséges
    1. tesztelünk
    2. folytatjuk elölről az első ponttól

Az Eclipse

Készítsünk egy projektet. A példa kedvéért legyen a neve sikidom.

  • File → New → Project…
  • Java → Java Project
  • legyen a neve: sikidom

Készítsünk egy csomagot:

  • File → New → Package
  • legyen a neve: sikidom

Elkészítjük a tesztet:

  • File → New → JUnit Test Case

Ha nincs a menüben a JUnit Test Case, akkor válasszuk a következőt:

  • File → New → Other…
  • JUnit → JUnit Test Case
  • legyen a neve: HaromszogTest

Eredmény

HaromszogTest.java
package sikidom;
 
import static org.junit.jupiter.api.Assertions.*;
 
import org.junit.jupiter.api.Test;
 
class HaromszogTest {
 
	@Test
	void test() {
		fail("Not yet implemented");
	}
 
}

A teszt fejlesztése

HaromszogTest.java
package sikidom;
 
import static org.junit.jupiter.api.Assertions.*;
 
import org.junit.jupiter.api.Test;
 
class HaromszogTest {
 
	@Test
	void test() {
		Haromszog haromszog = new Haromszog();
	}
 
}

A teszt futtatása

  • Run → Run

A teszt hibával ér végett, mivel nem létezik a Haromszog osztály.

Az ipari kód fejlesztése

Elkészítjük a Haromszog osztályt, de nem fejlesztjük tovább.

  • File → New → Class
  • legyen a neve: Haromszog
Haromszog.java
package sikidom;
 
public class Haromszog {
 
}

Futtatjuk a tesztet

  • Run → Run
  • A teszt teljesült.
  • Következik a teszt továbbfejlesztése.

Teszt fejlesztése

Hívjuk meg a szamolKerulet() metódust, ami még nem létezik. Egyelőre paraméterekre sincs szüksége.

HaormszogTest.java
package sikidom;
 
import static org.junit.jupiter.api.Assertions.*;
 
import org.junit.jupiter.api.Test;
 
class HaromszogTest {
 
	@Test
	void test() {
		Haromszog haromszog = new Haromszog();
		haromszog.szamolKerulet();
	}
 
}

Futtassuk a tesztet. A teszt nem teljesül.

Ipari kód fejlesztése

Annyit fejlesszünk a kódon, hogy teljesítse a tesztet.

Haromszog.java
package sikidom;
 
public class Haromszog {
	public void szamolKerulet() {
 
	}
}

Teszt fejlesztése

HaromszogTest.java
package sikidom;
 
import static org.junit.jupiter.api.Assertions.*;
 
import org.junit.jupiter.api.Test;
 
class HaromszogTest {
 
	@Test
	void test() {
		Haromszog haromszog = new Haromszog();
		double ker = haromszog.szamolKerulet();
 
	}
 
}

Ipari kód fejlesztése

Haromszog.java
package sikidom;
 
public class Haromszog {
	public double szamolKerulet() {
		return 0;
	}
}

Teszt fejlesztése

Jó lenne, ha a metódus fogadna paramétereket.

HaromszogTest.java
package sikidom;
 
import static org.junit.jupiter.api.Assertions.*;
 
import org.junit.jupiter.api.Test;
 
class HaromszogTest {
 
	@Test
	void test() {
		Haromszog haromszog = new Haromszog();
		double ker = haromszog.szamolKerulet(30, 35, 40);
 
	}
 
}

Ipari kód fejlesztése

Haromszog.java
package sikidom;
 
public class Haromszog {
	public double szamolKerulet(double a, double b, double c) {
		return 0;
	}
}

Teszt fejlesztése

HaromszogTest.java
package sikidom;
 
import static org.junit.jupiter.api.Assertions.*;
 
import org.junit.jupiter.api.Test;
 
class HaromszogTest {
 
	@Test
	void test() {
		Haromszog haromszog = new Haromszog();
		double ker = haromszog.szamolKerulet(30, 35, 40);
		assertEquals(105, haromszog.szamolKerulet(30, 35, 40));
	}
 
}

A teszt sikertelen. Hiba ugyan nincs, de a teszt sikertelen, mivel nem 105 az eredményt, 30, 35 és 40 bemenő paraméterek esetén.

Ipari kód fejlesztése

A kódot egyszerű javítani, írjuk oda, hogy 105-tel térjen vissza.

Haromszog.java
package sikidom;
 
public class Haromszog {
	public double szamolKerulet(double a, double b, double c) {
		return 105;
	}
}

A teszt lefut.

Teszt fejlesztése

HaromszogTest.java
package sikidom;
 
import static org.junit.jupiter.api.Assertions.*;
 
import org.junit.jupiter.api.Test;
 
class HaromszogTest {
 
	@Test
	void test() {
		Haromszog haromszog = new Haromszog();
		double ker = haromszog.szamolKerulet(30, 35, 40);
		assertEquals(105, haromszog.szamolKerulet(30, 35, 40));
		assertEquals(75, haromszog.szamolKerulet(20, 25, 30));
	}
 
}

A teszt újra sikertelen. A hiba csak 30, 35 és 40 bemenő paraméterek esetén működik.

Ipari kód fejlesztése

A kódot egyszerű javítani, írjuk oda, hogy 105-tel térjen vissza.

Haromszog.java
package sikidom;
 
public class Haromszog {
	public double szamolKerulet(double a, double b, double c) {
		return a + b + c;
	}
}

A teszt lefut.

Ezek után jöhet a tesztelés szélsőértékekre.

Újratervezés

HaromszogTest.java
package sikidom;
 
import static org.junit.jupiter.api.Assertions.*;
 
import org.junit.jupiter.api.Test;
 
class HaromszogTest {
 
	@Test
	void szamolKeruletTest() {
		Haromszog haromszog = new Haromszog();
		assertEquals(105, haromszog.szamolKerulet(30, 35, 40));
		assertEquals(75, haromszog.szamolKerulet(20, 25, 30));
	}
 
}

Kitöröltük a felesleges sort, mivel mindenképpen meghívjuk szamolKerulet() metódust. Mivel a test() metódus csak a szamolKerulet() metódust teszteli, ezért átnevezzük szamolKeruletTest() névre.

Netbeans

Ipari kód osztálya

Netbeans alatt létre kell hoznunk a tesztelendő osztályt:

Haromszog.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package hu.szit.sikidom;
 
/**
 *
 * @author andras
 */
public class Haromszog {
 
}

Tesztkód

A jobb egér gombbal kattintunk a Prejects fülön a projekt nevén.

  • New → Other…
  • Az előugró ablakban:
    • Categories: Unit Tests
    • File Types: JUnit Test
    • Next >
  • Az újabb ablakban:
    • Class Name: HaromszogTest
    • Package: hu.szit.sikidom
    • Generated Code:
      • [ ] Test Initializer
      • [ ] Test Finalizer
      • [ ] Test Class Initializer
      • [ ] Test Class Finalizer
    • Generated Comments:
      • [ ] Source Code Hints
    • Finish gomb

Eredmény

HaromszogTest.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package hu.szit.sikidom;
 
import org.junit.Test;
import static org.junit.Assert.*;
 
/**
 *
 * @author andras
 */
public class HaromszogTest {
 
    public HaromszogTest() {
    }
 
}

Első teszt írása

HaromszogTest.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
 
import org.junit.Test;
import static org.junit.Assert.*;
 
/**
 *
 * @author andras
 */
public class HaromszogTest {
 
    public HaromszogTest() {
    }
 
    @Test
    public void test() {
        Haromszog har = new Haromszog();
        har.szamitKerulet();
    }
 
}

Futtassuk a tesztet:

  • Run → Test Project (sikidom)

Ipari kód fejlesztése

Írjunk annyi kódot, ami miatt a teszt nem fut hibára.

Haromszog.java
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package hu.szit.sikidom;
 
/**
 *
 * @author andras
 */
public class Haromszog {
    public void szamitKerulet() {
 
    }    
}

A teszt most már nem fut hibára.

Tervezzük újra

Jelen esetben semmi különöset nem csinálok, csak kiszedem a megjegyzéseket.

Haromszog.java
package hu.szit.sikidom;
 
public class Haromszog {
    public void szamitKerulet() {
 
    }    
}
HaromszogTest.java
package hu.szit.sikidom;
 
import org.junit.Test;
import static org.junit.Assert.*;
 
public class HaromszogTest {
 
    public HaromszogTest() {
    }
    @Test
    public void haromszogKeruletTest() {
        Haromszog har = new Haromszog();
        har.szamitKerulet();
    }
 
}

A teszt fejlesztése

Jó lenne, ha adna vissza értéket szamitKerulet() metódus.

    @Test
    public void haromszogKeruletTest() {
        Haromszog har = new Haromszog();
        double ker = har.szamitKerulet();
    }

Futtassuk a tesztet.

Ipari kód fejlesztése

Éppen csak annyira fejlesztjük, hogy teljesítse a tesztet.

public class Haromszog {
    public double szamitKerulet() {
        return 0;
    }
}

Mentsünk és futtassuk a tesztet.

Újratervezés

Most nincs mit.

Teszt fejlesztése

Jó lenne, ha metódus fogadna bemenő paramétereket.

    @Test
    public void haromszogKeruletTest() {
        Haromszog har = new Haromszog();
        double ker = har.szamitKerulet(30, 35, 40);
    }

Ipari kód fejlesztése

Haromszog.java
package hu.szit.sikidom;
 
public class Haromszog {
    public double szamitKerulet(double a, double b, double c) {
        return 0;
    }
}

Újratervezés

Haromszog.java
package hu.szit.sikidom;
 
public class Haromszog {
    public double szamitKerulet(double aOldal, double bOldal, double cOldal) {
        return 0;
    }
}

A teszt fejlesztése

HaromszogTest.java
package hu.szit.sikidom;
 
import org.junit.Test;
import static org.junit.Assert.*;
 
public class HaromszogTest {
 
    public HaromszogTest() {
    }
    @Test
    public void haromszogKeruletTest() {
        Haromszog har = new Haromszog();
        double ker = har.szamitKerulet(30, 35, 40);
        assertEquals(105, har.szamitKerulet(30, 35, 40), 0);
    }
 
}

Ipari kód fejlesztése

Ha 0 helyett 105-el térünk vissza, a teszt már teljesül:

Haromszog.java
package hu.szit.sikidom;
 
public class Haromszog {
    public double szamitKerulet(double aOldal, double bOldal, double cOldal) {
        return 105;
    }
}

Újratervezés

Az alábbi sort töröljük, mivel helyettesíti az assertEquals()-t tartalmoaz sor:

double ker = har.szamitKerulet(30, 35, 40);
HaromszogTest.java
package hu.szit.sikidom;
 
import org.junit.Test;
import static org.junit.Assert.*;
 
public class HaromszogTest {
 
    public HaromszogTest() {
    }
    @Test
    public void haromszogKeruletTest() {
        Haromszog har = new Haromszog();
        assertEquals(105, har.szamitKerulet(30, 35, 40), 0);
    }
 
}

A teszt fejlesztése

HaromszogTest.java
package hu.szit.sikidom;
 
import org.junit.Test;
import static org.junit.Assert.*;
 
public class HaromszogTest {
 
    public HaromszogTest() {
    }
    @Test
    public void haromszogKeruletTest() {
        Haromszog har = new Haromszog();
        assertEquals(105, har.szamitKerulet(30, 35, 40), 0);
        assertEquals(75, har.szamitKerulet(20, 25, 30), 0);
    }
 
}

Ipari kód fejlesztése

Haromszog.java
package hu.szit.sikidom;
 
public class Haromszog {
    public double szamitKerulet(double aOldal, double bOldal, double cOldal) {
        return aOldal+bOldal+cOldal;
    }
}

Újratervezése

Most nem teszünk semmit.

Teszt fejlesztése

HaromszogTest.java
package hu.szit.sikidom;
 
import org.junit.Test;
import static org.junit.Assert.*;
 
public class HaromszogTest {
 
    public HaromszogTest() {
    }
    @Test
    public void haromszogKeruletTest() {
        Haromszog har = new Haromszog();
        assertEquals(105, har.szamitKerulet(30, 35, 40), 0);
        assertEquals(75, har.szamitKerulet(20, 25, 30), 0);
    }
 
    @Test(expected = IllegalArgumentException.class)
    public void haromszogKeruletException() {
        Haromszog har = new Haromszog();
        har.szamitKerulet(0, 25, 30);
    }
}

JUnit5 már lehetővé teszi:

        assertThrows(IllegalArgumentException.class, 
                har.szamitKerulet(0, 25, 30));

Ipari kód fejlesztése

Haromszog.java
package hu.szit.sikidom;
 
public class Haromszog {
    public double szamitKerulet(double aOldal, double bOldal, double cOldal) {
        if(aOldal <= 0) {
            throw new IllegalArgumentException("Nem megfelelő paraméter");
        }
        return aOldal+bOldal+cOldal;
    }
}
oktatas/programozas/tdd.txt · Utolsó módosítás: 2024/01/07 15:09 szerkesztette: admin