web-dev-qa-db-fra.com

Comment tester avec Python est unitest d'un avertissement?

J'ai une fonction suivante dans Python et je tiens à tester avec un impair que si la fonction obtient 0 en tant qu'argument, il jette un avertissement. J'ai déjà essayé des assertraises, mais puisque je ne lève pas le AVERTISSEMENT, ça ne fonctionne pas.

def isZero(i):
    if i != 0:
        print "OK"
    else:
        warning = Warning("the input is 0!") 
        print warning
    return i
57
Tomas Novotny

Vous pouvez utiliser le catch_warnings Gestionnaire de contexte. Cela vous permet essentiellement de vous moquer du gestionnaire d'avertissements afin de pouvoir vérifier les détails de l'avertissement. Voir le Documents officiels pour une explication plus complète et un exemple de code de test.

import warnings

def fxn():
    warnings.warn("deprecated", DeprecationWarning)

with warnings.catch_warnings(record=True) as w:
    # Cause all warnings to always be triggered.
    warnings.simplefilter("always")
    # Trigger a warning.
    fxn()
    # Verify some things
    assert len(w) == 1
    assert issubclass(w[-1].category, DeprecationWarning)
    assert "deprecated" in str(w[-1].message)
48
ire_and_curses

En commençant par Python 3.2, vous pouvez simplement utiliser assertWarns() méthode.

with self.assertWarns(Warning):
    do_something()
45
Melebius

Un problème avec l'approche warnings.catch_warnings est que les avertissements produits dans différents tests peuvent interagir de manière étrange à travers l'état mondial conservé dans les attributs __warningregistry__.

Pour résoudre ce problème, nous devrions effacer l'attribut __warningregistry__ de chaque module avant chaque test qui vérifie les avertissements.

class MyTest(unittest.TestCase):

  def setUp(self):
    # The __warningregistry__'s need to be in a pristine state for tests
    # to work properly.
    for v in sys.modules.values():
      if getattr(v, '__warningregistry__', None):
        v.__warningregistry__ = {}

  def test_something(self):
    with warnings.catch_warnings(record=True) as w:
      warnings.simplefilter("always", MySpecialWarning)
      ...
      self.assertEqual(len(w), 1)
      self.assertIsInstance(w[0].message, MySpecialWarning)

C'est ainsi que Python 3's assertWarns() méthode est mise en œuvre .

0
ostrokach