[[oktatas:programozás:python|< Python]] ====== TDD ====== * **Szerző:** Sallai András * Copyright (c) 2020, Sallai András * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC BY-SA 4.0]] * Web: https://szit.hu ===== A TDD ===== A **TDD** a **Test-Driven Development** rövidítése. Magyarul **teszt vezérelt fejlesztés**. - TDD esetén a teszt fejlesztésével kezdem. De csak annyit fejlesztek rajta, hogy éppen ne teljesüljön. Első körben, annyi is elég, hogy egy nem létező osztályra hivatkozunk. - Ezek után minimálisan, annyit fejlesztünk az ipari kódon (hasznos kód), ami teljesíti a tesztet, de nem többet. Futtatjuk a tesztet. Ha teljesül mehetünk tovább. - Megnézzük mit lehet az ipari kódban, és a teszt kódban újratervezni (refactor). Ha találunk valamit, lekódoljuk, majd futtatjuk a tesztet. Ha teljesült, mehetünk vissza az első lépéshez, vagyis fejlesztjük a tesztet. ===== Példa ===== ==== Iteráció 01 ==== === Teszt fejlesztése === Írjunk egy tesztet amely betölti a Haromszog osztályt, amikor az még nem is létezik: import haromszog haromszog.Haromszog() Futtassuk a tesztet. A teszt elszáll, mivel nem létezik a triangle fájl. === Ipari kód fejlesztése === Most annyi kódot írjunk, ami teljesíti a tesztet. class Haromszog(): pass Futtassuk a tesztet. A teszt teljesül. === Újraépítés === Lehet jobb lenne angol elnevezésekkel. from triangle import Triangle class Triangle(): pass ==== Iteráció 02 ==== === Teszt fejlesztése === Most fejlesszük a tesztet, addig, amíg meghívja a Triangle osztályban a calcArea() függvényt. from triangle import Triangle def testCalcAreaExist(): Triangle.calcArea() testCalcAreaExist() Most futtassuk a tesztet. A teszt elbukik, mivel még nem létezik a Triangle osztályban calcArea() függvény. === Ipari kód fejlesztése === Most fejlesszünk annyit a Triagnle osztályon, hogy teljesüljön a teszt. class Triangle(): def calcArea(): pass Futtassuk a tesztet. A teszt most teljesül. === Újraépítés === A teszt számára is készíthetünk osztályt: from triangle import Triangle import unittest class TestTriangle(unittest.TestCase): def testCalcAreaExist(self): Triangle.calcArea() if __name__ == "__main__": unittest.main() A if __name__ == "__main__": sor kötelező a a TestCase osztály indításához. ==== Iteráció 03 ==== === Teszt fejlesztése === Fejlesszük a tesztet. A calcArea() függvényhívásnál adjunk át egy alapot, legyen ez most 30. class TestTriangle(unittest.TestCase): def testCalcAreaExist(self): Triangle.calcArea(30) if __name__ == "__main__": unittest.main() Teszteljünk. A teszt elbukik, mivel a calcArea() függvény nem fogad semmilyen paramétert. === Ipari kód fejlesztése === Fejlesszük a calcArea() függvényt addig, hogy elfogadja a base paramétert. class Triangle(): def calcArea(base): pass Futtassuk a tesztet. A teszt teljesül. === Újraépítés === class TestTriangle(unittest.TestCase): def testCalcAreaOneParameter(self): Triangle.calcArea(30) if __name__ == "__main__": unittest.main() ==== Iteráció 04 ==== === Teszt fejlesztése === Fejlesszük a tesztet. Adjuk át a magasság értéket is a calcArea() függvénynek. Futtassuk a tesztet. A teszt elbukik, mert csak egy paramétert fogad a függvény. class TestTriangle(unittest.TestCase): def testCalcAreaOneParameter(self): Triangle.calcArea(30, 35) if __name__ == "__main__": unittest.main() Futtassuk a tesztet. A teszt elbukik. === Ipari kód fejlesztése === Fejlesszük a calcArea() függvényt, amíg teljesíti a tesztet. class Triangle(): def calcArea(b, h): pass Futtassuk a tesztet. A teszt teljesül. === Újraépítés === class TestTriangle(unittest.TestCase): def testCalcAreaTwoParameter(self): Triangle.calcArea(30, 35) if __name__ == "__main__": unittest.main() class Triangle(): def calcArea(base, height): pass ==== Iteráció 05 ==== === Teszt fejlesztése === Fejlesszük a tesztet. A calcArea() függvénytől elvárjuk, hogy adja vissza az alapból és magasságból kiszámolt 525.0 értéket. Vizsgáljuk meg, hogy a megfelelő értéket kaptuk-e. from triangle import Triangle import unittest class TestTriangle(unittest.TestCase): def testCalcAreaTwoParameter(self): area = Triangle.calcArea(30, 35) self.assertEqual(area, 525.0, 'Az elvárt érték 525.0') if __name__ == "__main__": unittest.main() Futtassuk a tesztet. A teszt elbukik. === Az ipari kód fejlesztése === Fejlesszük a függvényt addig, hogy visszaadja a 525.0 értéket. class Triangle(): def calcArea(base, height): return 525.0 Futtassuk a tesztet. Teljesült. === Újraépítés === class TestTriangle(unittest.TestCase): def testCalcAreaNormalParameter(self): area = Triangle.calcArea(30, 35) self.assertEqual(area, 525.0, 'Az elvárt érték 525.0') if __name__ == "__main__": unittest.main() ==== Iteráció 06 ==== === Teszt fejlesztése === Fejlesszük a tesztet. A calcArea() függvénynek más bemenő paraméterek mellett is helyes értéket kell visszaadnia. Legyenek a bemenő paraméterek most 52 és 48. Ekkor 1248-t kell kapnunk. Ezt egy újabb függvényben írjuk meg a teszten belül. from triangle import Triangle import unittest class TestTriangle(unittest.TestCase): def testCalcAreaNormalParameter(self): area = Triangle.calcArea(30, 35) self.assertEqual(area, 525.0, 'Az elvárt érték 525.0') def testCalcAreaNormalParameter2(self): area = Triangle.calcArea(52, 48) self.assertEqual(area, 1248.0, 'Az elvárt érték 1248.0') if __name__ == "__main__": unittest.main() Futtassuk a tesztet. Az első teszt teljesül, de a második elbukik. === Az ipari kód fejlesztése === Fejlesszük tovább az ipari kódot, amíg teljesül mindkét teszt. class Triangle(): def calcArea(base, height): area = base*height/2 return area Futtassuk a tesztet. A teszt teljesül. === Újraépítés === class Triangle(): def calcArea(base, height): return base*height/2 ==== Iteráció 07 ==== === Teszt fejlesztése === Fejlesszük a tesztet. A programunk negatív szám esetén adjon vissza -1-t. from triangle import Triangle import unittest class TestTriangle(unittest.TestCase): def testCalcAreaNormalParameter(self): area = Triangle.calcArea(30, 35) self.assertEqual(area, 525.0, 'Az elvárt érték 525.0') def testCalcAreaNormalParameter2(self): area = Triangle.calcArea(52, 48) self.assertEqual(area, 1248.0, 'Az elvárt érték 1248.0') def testCalcAreaNegative(self): area = Triangle.calcArea(-5, 48) self.assertEqual(area, -1, 'Az elvárt érték -1') Futtassuk a tesztet. A teszt elbukik. === Az ipari kód fejlesztése === Fejlesszük az ipari kódot, amíg teljesül teszt. class Triangle(): def calcArea(base, height): if base < 0: return -1 else: return base*height/2 === Újraépítés === class Triangle(): def calcArea(base, height): if base < 0 or height < 0: return -1 else: return base*height/2