Unit testing op de Google App Engine (Python versie)

Een eerste reflex die je als rechtgeaarde moderne ontwikkelaar hebt als je aan een nieuw platform begint is die van het inrichten van een testgedreven omgeving. Ik ben de laatste maanden vol goede moed begonnen met me te verdiepen in de Google App Engine en dan wel in de taal waarvoor dit platform bedoeld is: Python.

Na verscheidene avondjes zoeken en experimenteren heb ik diverse alternatieven gevonden. Zo is er nose-gae, een app engine variant van het Python nose unit testing framework. Vreemd genoeg kreeg ik het niet lekker aan de praat. Na wat andere frameworkjes te hebben geprobeerd (en veel uren te hebben gespendeerd) ben ik eens gaan nadenken wat ik eigenlijk wil. Samengevat is dat:

– Makkelijk tests kunnen runnen
– Zonder enige vorm van configuratie of wat dan ook tests kunnen toevoegen
– Tests op een voor mij makkelijke plek kunnen neerzetten

En hoewel ik er zwaar op tegen ben heb ik een eigen ‘frameworkje’ (zo mag je 15 regels code eigenlijk niet noemen maar á la) geschreven.

class Test(webapp.RequestHandler):
    def get(self):
        testsrun=0
        testsfailed=0
        self.response.out.write("")        
        files=os.listdir(".")
        #iterate through files
        for fil in files:
            if fil.endswith(".py"):
                m = __import__(fil.replace(".py",""))
                for f in dir(m):
                    #methods starting with test_ will be executed
                    if f.startswith("test_") and callable(getattr(m,f)):
                        self.response.out.write("""""")
                        try:
                            testsrun+=1
                            #Execute the method
                            getattr(m,f)()
                            #No exception: successfully executed
                            self.response.out.write("""""")
                        except:
                            #Exception occurred: print traceback
                            testsfailed+=1
                            self.response.out.write("""")

        self.response.out.write("
"""+fil+"-"+f+""" SUCCESS
 FAIL
---
""""" + traceback.format_exc()+"
---
") self.response.out.write("

Executed " + str(testsrun) + " tests. " + str(testsrun-testsfailed) + " succeeded, " + str(testsfailed) + " failed.

")

Dit reflectieve stukje code itereert door alle .py files in in de directory, en zoekt alle methodes (ongeacht in welke class die zich bevindt) die met test_ beginnen. Vervolgens worden deze methodes aangeroepen en bepaald of de test slaagt of faalt. Een klein beetje grafische suiker is toegevoegd met wat plaatjes.

Een volledig lege app engine applicatie die dit frameworkje bevat (dus slechts deze class en de benodigde plaatjes) kan je hier downloaden.