Érdekes

Python Egység Vizsgálati Keret

Az eredeti dokumentum http://pyunit.sourceforge.net/pyunit.html

Áttekintés

Python unit testing framework, szinkronizált ‘PyUnit’ egyezmény, egy Python nyelvű változata JUnit, okos cookie-k Kent Beck es Erich Gamma. JUnit viszont egy Java verzió Kent Smalltalk vizsgálati keret. Minden a de facto standard egység vizsgálati keretet a megfelelő nyelvet.

Ez a dokumentum ismerteti a Python-specifikus szempontok a tervezés, mind a használat PyUnit; a háttér-információk az alapvető design a keret az olvasó említett Kent eredeti papír, az “Egyszerű Smalltalk Tesztelés: A Minták“.

PyUnit formák egy része a Python Standard Könyvtár, mint a Python verzió 2.1.

A következő információkat feltételezi, hogy a tudás, a Python nyelvet annyira egyszerű, hogy még nekem is sikerült megtanulni, annyira addiktív, hogy nem tudom abbahagyni.

Rendszer követelmények

PyUnit úgy tervezték, hogy bármilyen szabványos Python verzió 1.5.2 magasabb.

PyUnit tesztelték a szerző által a Linux (Redhat 6.0, 6.1, Debian Potato) a Python 1.5.2, 2.0 es 2.1. Az is ismert, hogy a munka más Python platformok, beleértve a Windows, mind a Mac. Ha bármely platform, vagy a Python változat kérdések, mert baj van, kérem tudassa velem.

A részletekért használata PyUnit a JPython, Jython, kérjük, lásd a “Segítségével PyUnit a JPython, Jython“.

Használata PyUnit írok saját tesztet

Telepítés

Az osztályok kellett írni tesztek találhatók a ‘unittest’ a modul. Ez a modul része a szabványos Python könyvtár Python 2.1 majd később. Ha egy régebbi Python verzió, meg kell, hogy szerezze be a modult a külön PyUnit engedély.

Hogy képes legyen használni a modul a saját kód, egyszerűen biztosítására, hogy a könyvtár, amely a fájl ‘unittest.py’ ez a Python keresési ösvényt. Ezt megteheti azáltal, hogy a ‘$PYTHONPATH’ környezeti változó, vagy azáltal, hogy a fájlt egy könyvtárba a jelenlegi Python keresési utat, mint például a /usr/lib/python1.5/site-csomagok a Redhat Linux gépek.

Ne feledje, hogy meg kell tennem, mielőtt futni a példák, hogy vannak ellátva PyUnit hacsak másolás ‘unittest.py’ a példák könyvtár.

Bevezetés TestCases

Alapvető építőkövei az egység-vizsgálat ‘test cases’ — egyetlen forgatókönyv, hogy kell beállítani, ellenőrizni helyességét. A PyUnit, teszt esetet képviseli a TestCase osztály a unittest modul. Hogy a saját vizsgálati esetek kell írni alosztályok a TestCase.

Egy példány a TestCase osztály egy objektum, ami teljesen fut egy egységes vizsgálati módszer, együtt opcionális beállítás, tiszt kódot.

A vizsgálat kódja TestCase például teljesen önálló, például, hogy lehet futtatni vagy önmagában, vagy tetszőleges kombinációja számos más vizsgált esetekben.

Ami egy egyszerű próba

A legegyszerűbb teszt esetben alosztály egyszerűen felülírják a runTest módszer annak érdekében, hogy végre konkrét vizsgálati kód:

        import unittest

        class DefaultWidgetSizeTestCase(unittest.TestCase):
            def runTest(self):
                widget = Widget("The widget")
                assert widget.size() == (50,50), 'incorrect default size'

Megjegyzés annak érdekében, hogy a teszt valamit, használjuk a beépített ‘assert’ állítását a Python. Ha az állítás nem sikerül, ha a vizsgált esetben fut, egy AssertionError fogja emelni, a vizsgálati keret meghatározza a vizsgálati helyzet, mint a “failure”. Más kivételek, amelyek nem merülnek fel, a kifejezett ‘érvényesíteni’ ellenőrzés által azonosított a vizsgálati keret, mint a ‘errors’. (Lásd még a “Többet a vizsgálati feltételek“.)

A módja annak, hogy egy tesztet az esetben lesz leírt később. Most, vegye figyelembe, hogy építeni egy példát egy ilyen teszt az esetben hívjuk a kivitelező nélkül érvek:

        testCase = DefaultWidgetSizeTestCase()

Újra segítségével beállított kód: létrehozása ‘fixtures’

Most, ilyen teszt lehet számos, a set-ig lehet ismétlődő. A fenti eset, miszerint a ‘Widget’ minden 100 Widget vizsgált esetben alosztályok azt jelentené, hogy csúnya párhuzamos.

Szerencsére tudunk tényező ilyen set-up kód végrehajtása horog módszer az úgynevezett beállítás, amely a tesztelési keretrendszer automatikusan hív bennünket, amikor a tesztet:

      import unittest

        class SimpleWidgetTestCase(unittest.TestCase):
            def setUp(self):
                self.widget = Widget("The widget")

        class DefaultWidgetSizeTestCase(SimpleWidgetTestCase):
            def runTest(self):
                assert self.widget.size() == (50,50), 'incorrect default size'

        class WidgetResizeTestCase(SimpleWidgetTestCase):
            def runTest(self):
                self.widget.resize(100,150)
                assert self.widget.size() == (100,150), \
                       'wrong size after resize'

Ha a setUp módszer felvet egy kivétel, míg a teszt fut, a keret megfontolja, hogy a vizsgált szenvedett egy hiba, illetve a runTest módszer nem fog megvalósulni.

Hasonlóképpen tudunk biztosítani egy  tearDown módszer, hogy tidies után a runTest módszer már fut:

        import unittest

        class SimpleWidgetTestCase(unittest.TestCase):
            def setUp(self):
                self.widget = Widget("The widget")
            def tearDown(self):
                self.widget.dispose()
                self.widget = None

Ha a setUp sikeres, a tearDown módszer futni fog, függetlenül attól, hogy runTest sikerült.

Egy ilyen környezetben dolgozik a vizsgálati kód nevezzük lámpatest.

TestCase osztályok több vizsgálati módszerek

Gyakran előfordul, hogy sok kis teszt fogja használni az azonos lámpatest. Ebben az esetben mi lenne a vége subclassing SimpleWidgetTestCase a sok kicsi-módszer osztályok, mint a DefaultWidgetSizeTestCase. Ez időigényes, elég elkeserítő, hasonlóképpen, mint a JUnit, PyUnit biztosít egy egyszerűbb mechanizmus:

       import unittest

        class WidgetTestCase(unittest.TestCase):
            def setUp(self):
                self.widget = Widget("The widget")
            def tearDown(self):
                self.widget.dispose()
                self.widget = None
            def testDefaultSize(self):
                assert self.widget.size() == (50,50), 'incorrect default size'
            def testResize(self):
                self.widget.resize(100,150)
                assert self.widget.size() == (100,150), \
                       'wrong size after resize'

Itt még nem nyújtott runTest módszer, de van helyette, feltéve, két különböző vizsgálati módszerek. Osztály esetekben, most minden a vizsgálati módszerek, egyéni self.widget létre, megsemmisült, külön-külön minden egyes esetben. Ha létre egy példányát meg kell határozni a vizsgálati módszer az, hogy fuss. Mi ez a átadásával a módszer neve a konstruktor:

        defaultSizeTestCase = WidgetTestCase("testDefaultSize")
        resizeTestCase = WidgetTestCase("testResize")

Összesítése teszt a teszt lakosztályok

Teszt esetben esetekben csoportosítják a funkciók teszt. PyUnit biztosít egy mechanizmust: a ‘test suite’, képviseli az osztály TestSuite a unittest modul:

        widgetTestSuite = unittest.TestSuite()
        widgetTestSuite.addTest(WidgetTestCase("testDefaultSize"))
        widgetTestSuite.addTest(WidgetTestCase("testResize"))

A könnyebb tesztelni, mint később látni fogjuk, ez egy jó ötlet, hogy biztosítani, hogy az egyes vizsgálati modul ‘lehívható’ tárgy, ami visszatér egy előre beépített teszt csomag:

       def suite():
           suite = unittest.TestSuite()
           suite.addTest(WidgetTestCase("testDefaultSize"))
           suite.addTest(WidgetTestCase("testResize"))
           return suite

vagy is:

       class WidgetTestSuite(unittest.TestSuite):
           def __init__(self):
               unittest.TestSuite.__init__(self,map(WidgetTestCase,
                                                     ("testDefaultSize",
                                                      "testResize")))

(ez utóbbi kétségkívül nem a gyenge szívű)

Mivel ez egy közös minta, hogy hozzon létre egy TestCase alosztály a sok hasonló nevű teszt funkciók, van egy kényelmi funkció, hívott makeSuite feltéve, hogy a unittest modul, amely felépíti a test suite, amely magában foglalja mind a vizsgált esetekben a vizsgált esetben osztály:-

       suite = unittest.makeSuite(WidgetTestCase,'test')

Megjegyzés: ha használja a makeSuite funkció, a sorrend, amelyben a különböző vizsgált esetben a test suite a sorrend határozza meg a válogatás a teszt funkció nevek használata a cmp beépített funkció.

Fészkelő teszt lakosztályok

Gyakran kívánatos, hogy a csoport suites a vizsgált esetek együtt, oly módon, hogy a vizsgálatok az egész rendszer egyszerre. Ez könnyű, mivel TestSuites lehet adni, hogy a TestSuite ahogy TestCases lehet adni, hogy a TestSuite:-

       suite1 = module1.TheTestSuite()
       suite2 = module2.TheTestSuite()
       alltests = unittest.TestSuite((suite1, suite2))

Egy példa fészkelő teszt suites található a fájl ‘alltests.py’ a ‘examples’ alkönyvtár a telepítőcsomag.

Hol a hely vizsgálati kód

Helyezze a meghatározások a teszt, teszt lakosztályok az azonos modulok, mint a kódot ezek vizsgálat (pl. ‘widget.py’), de számos előnnyel jár, hogy a forgalomba a teszt kód egy külön modul, mint a ‘widgettests.py’ a továbbiakban:

  • A teszt modul lehet futtatni önálló parancssorból
  • A teszt kód könnyebben lehet elválasztani szállított kód
  • Kevesebb a kísértés, hogy a változás teszt kód, hogy illeszkedjen a kód vizsgálatok ok nélkül
  • Teszt kód módosítani sokkal ritkábban, mint a kód vizsgálatok
  • Tesztelt kód lehet refactored könnyebben
  • Vizsgálatok modulok, C-ben írt kell külön modulokat, mindegy, akkor miért nem következetes?
  • Ha a vizsgálati stratégia változik, nem kell változtatni a forráskód

Futó vizsgálatok interaktívan

Persze, a lényeg az írás ezeket a vizsgálatokat olyan, hogy tudjuk futtatni őket, ha a szoftver működik. A teszt keretrendszert használ ‘TestRunner’ osztályok, hogy olyan környezetet, amelyben a vizsgálatokat lehet végezni. A leggyakoribb TestRunner az TextTestRunner, amely a vizsgálatok, illetve a jelentést az eredmények szöveges formában:

      runner = unittest.TextTestRunner()
      runner.run(widgetTestSuite)

Alapértelmezés szerint TextTestRunner kiírja a kimeneti sys.stderr, de ezt meg lehet változtatni átadásával egy másik fájl mint tárgy a kivitelező.

Használata TextTestRunner így ideális módja annak, hogy a teszteket interaktív belül a Python értelmező ülésén.

Folyik a vizsgálat a parancssorból

Unittest modul tartalmaz egy olyan funkció, hívott fő, amelyet fel lehet használni, hogy könnyen be egy teszt modul a szkript a vizsgálatot tartalmaz. A fő funkciót használja, a unittest.TestLoader osztály automatikusan megtalálja, terhelési teszt belül a jelenlegi modul.

Ezért, ha a neve a vizsgálati módszerek használata a test* egyezmény a korábban bemutatott, a következő kódot alján a teszt modul:

        if __name__ == "__main__":
            unittest.main()

Aztán, amikor végre a teszt modul a parancssorból, a vizsgálatok az abban foglalt fog futni. Futtassa a modul ‘-h’ opció, annak érdekében, hogy a rendelkezésre álló lehetőségeket.

Futni önkényes vizsgálatok parancssorból, akkor futtassa a unittest modul, mint egy forgatókönyv, így ez a neve egy próbát, vagy test suite:

     % python unittest.py widgettests.WidgetTestSuite

vagy

        % python unittest.py widgettests.makeWidgetTestSuite

Te is meghatározhat bizonyos vizsgálatok a parancssori. Hogy fut a TestCase alosztály ‘ListTestCase’ a modul ‘listtests’ (lásd a ‘examples’ alkönyvtár, a terjesztési csomag) akkor végre a parancsot:

        % python unittest.py listtests.ListTestCase.testAppend

hol ‘testAppend’ a neve a vizsgálati módszer az, hogy a vizsgált esetben például. Létrehozni, majd futtassa ListTestCase esetekben a ‘test*” módszerek abban az osztályban, lehet futtatni:

      % python unittest.py listtests.ListTestCase

GUI teszt futó

Van egy grafikus front-end, hogy tudod használni, annak érdekében, hogy a vizsgálatokat. Meg van írva, Tkinter használatával, a windowing toolkit szállított Python a legtöbb platformon. Ez hasonlít a JUnit GUI.

GUI használni teszt futó, egyszerűen futtassa:

      % python unittestgui.py

vagy

        % python unittestgui.py widgettests.WidgetTestSuite

Megjegyzendő, hogy itt ismét a beírt név a tesztet futtatni kell a teljesen minősített név, egy tárgy, amely visszatér a TestCase vagy TestSuite például. Nem szabad a nevét egy előre létrehozott teszt, hiszen minden vizsgálatot újra el kell készíteni minden egyes alkalommal, amikor fut.

A használata a GUI teszt futó inkább, mint a szöveg teszt futó ró az idő, rezsi miatt azok a frissítések ablak; a rendszer, vesz egy extra hét másodperc per ezer tesztet. A kilométeróra változhat.

A vizsgálatok dokumentálása

Általában, ha egy vizsgálatot, annak neve megjelenik a TestRunner. Ez a név származik a neve a vizsgált esetben az osztály, a neve a vizsgálati módszer, hogy a fokon már szeretnénk futtatni.

Azonban, ha a kínálat a doki egy vizsgálati módszert, az első sorban, hogy doc-karakterlánc jelenik meg, ha a vizsgálatot. Ez biztosítja, hogy egy egyszerű mechanizmus, amely dokumentálja a tesztet:

       class WidgetTestCase(unittest.TestCase):
            def testDefaultSize(self):
                """Check that widgets are created with correct default size"""
                assert self.widget.size() == (50,50), 'incorrect default size'

Többet vizsgálati feltételek

Én használatát javasolta Piton beépített állítás ellenőrző mechanizmust feltételek a vizsgált esetekben inkább, mint a ‘haza-főzött’ egyenértékű; érvényesíteni az egyszerű, tömör, ismerős.

Ne feledje azonban, hogy ha a tesztek futtatása a Python optimalizálás opciót bekapcsolva (generáló ‘.pyo’ bytecode fájlok), a érvényesíteni kimutatások kimarad, ami a vizsgált esetben teljesen haszontalan.

Azok számára, akik hajlamosak a munka Python optimalizálás opció engedélyezve van, én is egy módszer assert_ a TestCase osztály. Ez funkcionálisan egyenértékű a érvényesíteni beépített, nem lesz optimális el, de ez kevésbé kényelmes eredménye kevesebb hasznos hiba üzenetek:

        def runTest(self):
            self.assert_(self.widget.size() == (100,100), "size is wrong")

Jó intézkedés azt is, feltéve, TestCase a failIf es failUnless módszerek:

    def runTest(self):
            self.failIf(self.widget.size() <> (100,100))

A vizsgált esetben a módszer is a hívás sikertelen, annak érdekében, hogy sikerül azonnal:

        def runTest(self):
            ...
            if not hasattr(something, "blah"):
                self.fail("blah missing")
                # or just 'self.fail()'

Az egyenlőség tesztelése

A leggyakoribb típus az az állítás, hogy egy állítás, egyenlőség két érték között, vagy tárgyakat. Ha az állítás nem sikerül, a fejlesztő általában látni akarja, mi a helytelen értéket valójában volt.

TestCase van egy pár módszerek, az úgynevezett assertEqual, assertNotEqual erre a célra (alias failUnlessEqual, failIfEqual azoknak akik kedvelik):

       def testSomething(self):
            self.widget.resize(100,100)
            self.assertEqual(self.widget.size, (100,100))

Vizsgálat kivételek

Gyakran egy tesztet, akkor szeretné, hogy ellenőrizze, hogy kivétel fel egy bizonyos meghatározott körülmények között. Ha a várható kivételt nem dobták el, a teszt sikertelen. Ez egyszerű:

        def runTest(self):
            try:
                self.widget.resize(-1,-1)
            except ValueError:
                pass
            else:
                fail("expected a ValueError")

Általában, a forrás, a várható kivétel lehívható tárgy; ezért TestCase egy assertRaises módszer. Az első két érv, hogy a módszer a várható kivétel, mivel úgy tűnik, egy “kivéve” záradék, valamint a lehívható tárgy. A fennmaradó érvek azok, hogy át kellene, hogy a lehívható tárgy:

        def runTest(self):
            self.assertRaises(ValueError, self.widget.resize, -1, -1)

Újra régi használt teszt kód PyUnit

Egyes felhasználók számára, hogy meglévő vizsgálati kód, amit szeretnének futtatni a PyUnit, átalakítás nélkül minden régi teszt funkció, hogy egy TestCase alosztály.

Ez az oka annak, PyUnit nyújt FunctionTestCase osztály. Ez az alosztály a TestCase lehet csomagolni egy meglévő teszt funkció. Set-up tépd le funkciók is választható lesz csomagolva.

Adott a következő teszt funkció:

        def testSomething():
            something = makeSomething()
            assert something.name is not None
            ...

egy létrehozhat egy ezzel egyenértékű vizsgálat esetében például a következőképpen:

        testcase = unittest.FunctionTestCase(testSomething)

Ha vannak további set-up tépd le módszereket kell hívni részeként a vizsgált esetben ez a művelet is lehet, feltéve, hogy:

        testcase = unittest.FunctionTestCase(testSomething,
                                             setUp=makeSomethingDB,
                                             tearDown=deleteSomethingDB)

Használata PyUnit a JPython, Jython

Bár PyUnit volt írva elsősorban a ‘C’ Python, lehetséges, hogy írni PyUnit vizsgálatok segítségével Jython a Java, vagy Jython szoftver. Ez lehet előnyösebb, hogy megpróbálok írni JUnit teszteket Jython. PyUnit is működik megfelelően Jython elődei, JPython 1.0 es 1.1.

Persze, a Java nem rendelkezik TK GUI felület, így PyUnit ez a Tkinter-alapú GUI nem fog működni a Jython. A csak szöveges felület jól működik, azonban.

Ehhez egyszerűen másolja a szabványos C Python könyvtár modul fájlok ‘traceback.py’, ‘linecache.py’, ‘stat.py’ valamint ‘getopt.py’, egy hely, ahonnan lehet által behozott JPython. Ezeket a fájlokat, minden megoszlása C Piton. (Ezek az iránymutatások alapján a standard könyvtár a C Python 1.5.x, lehet, hogy nem megfelelő az egyéb Python változat.)

Most írjuk meg a PyUnit vizsgálatok pontosan úgy, mint a C, Python.

Ellenjavallat

Állítások

Lásd a kikötéssel lásd “További információ a vizsgálati feltételek” felett.

Memória használat

Amikor a kivételek során felmerült, hogy a futás egy test suite, az ebből eredő traceback tárgyak kerülnek, így a kudarc részletek formázható nyomtatott végén a teszt. Eltekintve az egyszerűség, az előnye ennek az, hogy a jövőbeli verziója a GUI TestRunner lehetővé post mortem vizsgálat a helyi, mind globális változó értékek, amelyek tárolják az traceback.

Egy lehetséges mellékhatás az, hogy amikor fut a teszt suites nagyon magas bukási arány, a memória használat ezeket a mentett traceback tárgyak gondot okozhat. Persze, ha olyan sok vizsgálatok hiányában ez a memória a feje fölött a legkisebb gondja.

Felhasználási feltételek

Szabadon használhatja, mellyel újraelosztása ez a szoftver alatt ugyanaz a liberális feltételek, hogy Piton. Csak annyit kérek, hogy a név, e-mail címe, valamint a projekt URL őrizni a forráskód, valamint a kísérő dokumentációt, a hitel, mint az eredeti szerző.

Az írásra ezt a szoftvert, hogy egy kis hozzájárulás a javítása, szoftver minőség a világon; nem alku, hogy pénz. (Ez nem azt jelenti, hogy a támogatás lenne kellemetlen.)

Jövőbeli tervek

Az egyik legfontosabb terve a jövőre nézve, hogy integrálja a TK GUI es IDLE IDE. Önkéntesek szívesen!

Más, mint, hogy nincs nagy tervek, hogy kiterjeszti a funkcionalitást a modul. Én megtartottam PyUnit olyan egyszerű, amennyire csak lehetséges (de nem egyszerűbb, remélhetőleg!) mert úgy gondolom, hogy helper modulok ilyen közös vizsgálati feladatok, mint a log fájl összehasonlítás jobb írta tesztet írók, mint egyedül.

A frissítések, valamint a közösségi

Hírek, frissítések, valamint elérhető a projekt honlapján.

Észrevételeket, javaslatokat, valamint a hibajelentéseket szívesen; egyszerűen e-mailben, vagy még jobb, csatlakozz a nagyon alacsony hangerő levelezési lista, tegye meg észrevételeit. Van egy meglepően nagy számú ember már használja PyUnit, mind bölcsesség megosztani.

Köszönetnyilvánítás

Nagyon köszönöm, hogy Guido, a tanítványok, a Python nyelv. A tribute, írtam a következő haiku (vagy ‘pyku’ ha lesz):

Guido van Rossum
‘Esetlen Holland’ szült
Gyönyörű Python

Én hálásan elismerjük a munkáját Kent Beck es Erich Gamma, a munka JUnit, amely lehetővé tette, hogy a design PyUnit egy nem-agy.

Köszönöm azt is, hogy Tim Voght; fedeztem fel, miután nem hajtotta végre PyUnit, hogy ő is végre egy ‘pyunit’ a modul részeként a ‘PyWiki’ WikiWikiWeb klón. Ő kegyesen megadta az engedélyt, hogy nyújtsák be a verzió, hogy a közösség nagy.

Nagyon köszönöm azoknak, akik írtak nekem javaslatokat, kérdéseket. Próbáltam hozzá megfelelő kredit a változások fájlt a letöltési csomagban.

Külön köszönet, hogy Jérôme Marant, aki csomagolt PyUnit a Debian.

Kapcsolódó információk

Körülbelül szerző

Steve Purcell csak egy programozó a szíve, önállóan dolgozik írás, alkalmazása, illetve az oktatási Open Source szoftver.

Nemrég járt el, mint Műszaki Igazgató egy Web/WAP start fel, de legtöbbször építész, kódolás nagy Java rendszerek, miközben counterproductively sürgetve a Java képzett kollégák, hogy Pyton helyett.

Vissza a főoldalra

Leave a Reply