2010-02-10 11 views
12

ho decoratore @login_testuser applicato contro il metodo TEST_1:Applicando decoratori pitone a metodi in una classe

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

C'è un modo per applicare @login_testuser su ogni metodo della classe con il prefisso "test_"?

In altre parole, il decoratore si applicherebbe a TEST_1, test_2 metodi indicati, ma non su setUp.

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

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

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

risposta

18

In Python 2.6, un class decorator è decisamente la soluzione. Per esempio, ecco uno abbastanza generale per questo tipo di attività:

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 

e ora, appena

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

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

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

si ottiene ciò che si desidera. In Python 2.5 o, peggio, la sintassi @decallmethods non funziona per la decorazione di classe, ma con altrimenti esattamente lo stesso codice è possibile sostituirlo con la seguente dichiarazione giusta dopo alla fine dell'istruzione class TestCase:

TestCase = decallmethods(login_testuser)(TestCase) 
3

Sicuro. Iterate tutti gli attributi della classe. Verifica che ognuno sia un metodo e se il nome inizia con "test_". Poi sostituirlo con la funzione restituita dal decoratore

Qualcosa di simile:

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

I lo metterebbe anche in un decoratore di classe. – Wim

0

Sì, è possibile ciclare su della classe dir/__dict__ o di avere un metaclasse che fa così, identificando se gli attributi iniziano con " test". Tuttavia, questo creerà un codice meno diretto ed esplicito rispetto alla scrittura esplicita del decoratore.

3

Sei sicuro che non staresti meglio inserendo invece il codice login_testuser in setUp? Ecco a cosa serve SetUp: viene eseguito prima di ogni metodo di prova.

+0

Grazie per il suggerimento, ma desidero applicare il decoratore solo a metodi con un prefisso particolare, e setUp si applicherà a tutti i metodi. –

+2

Forse segregate questi metodi nella loro classe allora? L'ispezione magica e l'aumento dei metodi suona come un misterioso mal di testa di manutenzione. –

Problemi correlati