2010-02-10 2 views
12

je décoratrice @login_testuser appliqué contre la méthode test_1:application décorateurs de python méthodes dans une classe

class TestCase(object): 
    @login_testuser 
    def test_1(self): 
     print "test_1()" 

Est-il possible que je peux appliquer @login_testuser sur toutes les méthodes de la classe préfixé par « test_ »?

En d'autres termes, le décorateur s'appliquerait à test_1, test_2 méthodes ci-dessous, mais pas sur setUp.

class TestCase(object): 
    def setUp(self): 
     pass 

    def test_1(self): 
     print "test_1()" 

    def test_2(self): 
     print "test_2()" 

Répondre

18

En Python 2.6, un class decorator est définitivement la solution. Par exemple, voici une assez général pour ce genre de tâches:

import inspect 

def decallmethods(decorator, prefix='test_'): 
    def dectheclass(cls): 
    for name, m in inspect.getmembers(cls, inspect.ismethod): 
     if name.startswith(prefix): 
     setattr(cls, name, decorator(m)) 
    return cls 
    return dectheclass 

et maintenant, juste

@decallmethods(login_testuser) 
class TestCase(object): 
    def setUp(self): 
     pass 

    def test_1(self): 
     print "test_1()" 

    def test_2(self): 
     print "test_2()" 

vous obtiendrez ce que vous désirez. En Python 2.5 ou pire, la syntaxe @decallmethods ne fonctionne pas pour la décoration de la classe, mais sinon exactement le même code, vous pouvez le remplacer par la déclaration suivante à droite après la fin de la déclaration class TestCase:

TestCase = decallmethods(login_testuser)(TestCase) 
3

Sûr. Itérer tous les attributs de la classe. Cochez chacun d'eux comme étant une méthode et si le nom commence par "test_". Remplacez-le par la fonction de retour de votre décorateur

Quelque chose comme:

from inspect import ismethod, getmembers 
for name, obj in getmembers(TestCase, ismethod): 
    if name.startswith("test_"): 
     setattr(TestCase, name, login_testuser(obj)) 
+3

I mettrait même cela dans un décorateur de classe. – Wim

0

Oui, vous pouvez boucler sur dir/__dict__ ou une métaclasse de la classe qui le fait, identifier si les attributs commencent par " tester". Cependant, cela créera un code explicite moins direct que l'écriture explicite du décorateur.

3

Etes-vous sûr que vous ne feriez pas mieux de mettre le code de login_testuser dans setUp à la place? C'est ce à quoi sert setUp: il est exécuté avant chaque méthode de test.

+0

Merci pour la suggestion, mais je souhaite appliquer le décorateur uniquement aux méthodes avec un préfixe particulier, et setUp s'appliquera à toutes les méthodes. –

+2

Peut-être séparer ces méthodes dans leur propre classe alors? L'inspection magique et l'augmentation des méthodes sonne comme un mal de tête mystérieux. –

Questions connexes