5 votes

Le décorateur fonctionne pour les fonctions mais pas pour les classes

J'ai besoin d'un peu d'aide pour corriger un décorateur pour unittest. Je ne suis pas sûr de savoir comment répondre aux exigences du test unitaire. L'idée de ce décorateur est de marquer le test comme expectedFailure SI True est passé. Dans le cas contraire, il permet au test de s'exécuter simplement. Ce décorateur fonctionne pour les fonctions de test, mais pas pour les définitions de classes.

import unittest

def expectedFailureIf(expFailure):
    if expFailure: 
        return unittest.expectedFailure
    return lambda func: func

@expectedFailureIf(GetCurrentOS() == kPlatMac)  # Fails on Class
class someClass(unittest.TestCase):
    #@expectedFailureIf(GetCurrentOS() == kPlatMac) # Works on Function
    def test_sometestA(self):
        assert True

    def test_sometestB(self):
        assert False

L'erreur que j'obtiens est que test_sometest() prend exactement 1 argument. La suppression du décorateur permet au test de s'exécuter. Déplacer le décorateur au sommet de la fonction permet au test de s'exécuter.

L'histoire... Une de mes plateformes fonctionne bien et l'autre non. Je veux permettre à une plateforme d'exécuter tous les tests tandis que l'autre plateforme sera marquée comme des échecs attendus. Bien sûr, je ne veux pas utiliser skip ou skip if. Puisque cela ne permettra pas à la plateforme valide de fonctionner. Les marquer comme des échecs attendus ne fonctionnera pas non plus puisque l'une des plateformes renverra un succès inattendu. Avec le expectedFailureIf() en place, chaque plateforme rapportera correctement et une fois que les choses seront corrigées, ces tests rapporteront un succès inattendu. Ce qui m'avertira lorsque les choses seront corrigées. Pour moi, cela semble être un meilleur résultat.

3voto

wim Points 35274

Sous Python 3, votre code fonctionne correctement. Le code la mise en œuvre de unittest.expectedFailure est meilleur, et il fonctionne correctement lorsqu'il décore des classes ou des fonctions.

Sur Python 2, la fonction unittest.expectedFailure n'est conçu que pour fonctionner sur des fonctions .

Voici un remplacement qui fonctionne avec Python 2.

import inspect
import types
import unittest

def expectedFailureIf(condition):
    if callable(condition):
        condition = condition()
    if not condition:
        # return identity function for no-op
        return lambda x: x
    def patch(func_or_class):
        if isinstance(func_or_class, types.FunctionType):
            return unittest.expectedFailure(func_or_class)
        for name, member in inspect.getmembers(func_or_class):
            if name.startswith('test') and isinstance(member, types.MethodType):
                setattr(func_or_class, name, unittest.expectedFailure(member))
        return func_or_class
    return patch

@expectedFailureIf(True)
class MyTest(unittest.TestCase):

    def test_that_passes(self):
        assert 2 + 2 == 4

    def test_that_fails(self):
        assert 2 + 2 == 5

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

Résultat :

test_that_fails (__main__.MyTest) ... expected failure
test_that_passes (__main__.MyTest) ... unexpected success

----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK (expected failures=1, unexpected successes=1)

Attention !

Le fait qu'un succès inattendu n'entraîne pas l'échec du test est un bogue dans Python ! Il a été corrigé en janvier 2014 (Python 3.4), mais cette correction n'a pas été fusionnée dans la branche 2.7 pour des raisons de compatibilité ascendante (voir les commentaires sur la page numéro20165 ). Il s'agit donc maintenant d'un Python 2 "caractéristique" malheureusement.

Si cela vous gêne, envisagez de passer à un modèle plus performant. version récente de Python et/ou en utilisant un meilleur gestionnaire de tests .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X