La dérivation d'une classe de cas de test en jette deux erreurs
J'ai quelques base de l'installation/démontage de code que je veux réutiliser dans tout un tas de tests unitaires. J'ai donc eu la brillante idée de la création de certaines classes dérivées pour éviter la répétition du code dans chaque classe de test.
En agissant de la sorte, j'ai reçu deux étranges erreurs. Un, je ne peux pas résoudre. Voici la insolubles:
AttributeError: 'TestDesktopRootController' object has no attribute '_testMethodName'
Voici ma classe de base:
import unittest
import twill
import cherrypy
from cherrypy._cpwsgi import CPWSGIApp
class BaseControllerTest(unittest.TestCase):
def __init__(self):
self.controller = None
def setUp(self):
app = cherrypy.Application(self.controller)
wsgi = CPWSGIApp(app)
twill.add_wsgi_intercept('localhost', 8080, lambda : wsgi)
def tearDown(self):
twill.remove_wsgi_intercept('localhost', 8080)
Et voici ma classe dérivée:
import twill
from base_controller_test import BaseControllerTest
class TestMyController(BaseControllerTest):
def __init__(self, args):
self.controller = MyController()
BaseControllerTest.__init__(self)
def test_root(self):
script = "find 'Contacts'"
twill.execute_string(script, initial_url='http://localhost:8080/')
L'autre étrange erreur est:
TypeError: __init__() takes exactly 1 argument (2 given)
La "solution" à qui a été d'ajouter le mot "args" à mon __init__
fonction dans la classe dérivée. Est-il possible de l'éviter?
Rappelez-vous, j'ai deux erreurs dans celui-ci.
- Pourquoi êtes-vous primordial
__init__()
? Généralement, nous l'emportersetUp
.
Vous devez vous connecter pour publier un commentaire.
C'est parce que vous êtes primordial
__init__()
de manière incorrecte. Presque certainement, vous ne voulez pas remplacer__init__()
à tous; vous devriez faire tout ensetUp()
. J'ai été en utilisantunittest
pour >10 ans et je ne pense pas que j'ai jamais remplacé__init__()
.Toutefois, si vous avez vraiment besoin de remplacer
__init__()
, n'oubliez pas que vous n'avez pas de contrôle où votre constructeur est appelé -- le cadre des appels pour vous. Donc, vous devez fournir une signature que l'on peut appeler. À partir du code source (unittest/case.py
), que la signature est:La manière la plus sûre à faire est d'accepter les arguments et juste pass 'em up de la classe de base. Ici, c'est un travail de mise en œuvre:
__init__()
. Ce qui me manque ici?__init__()
, ce n'est pas une classe attr -- c'est une instance attr. Lorsque vous définissez quelque chose à portée de classe, en dehors de toutes les méthodes, puis c'est une classe attr.TestCase.__init__()
parce qu'il est tout simplement pas nécessaire. Pour chaque test,unittest
crée une nouvelle instance de la classe de test (qui invoque__init__()
), les appelssetUp()
, appelle latest*()
méthode en cours d'exécution, puis appelletearDown()
.setUp()
est le fonctionnaire désigné point d'extension, et à chaque fois__init__()
est appelé, donc estsetUp()
.setUp
. Alors maintenant, c'est une question de unittest de conventions contre les Pythons, je suppose. Merci aussi pour la terminologie de correction.Dans
BaseController
's__init__
vous devez appelerunittest.TestCase
's__init__
comme vous l'avez fait dansTestMyController
.L'appel à la construction d'un cas de test à partir de la structure peut être en passant un argument. La meilleure façon de gérer cela pour dériver des classes est: