J'utilise Selenium pour les tests de bout en bout et je ne sais pas comment utiliser setup_class
et teardown_class
méthodes.
J'ai besoin de configurer le navigateur dans setup_class
méthode, puis effectuez une série de tests définis en tant que méthodes de classe et quittez finalement le navigateur dans teardown_clas
s méthode.
Mais logiquement, cela semble une mauvaise solution, car mes tests ne fonctionneront pas avec la classe, mais avec l’objet. Je passe self
param dans chaque méthode de test pour pouvoir accéder aux variables des objets:
class TestClass:
def setup_class(cls):
pass
def test_buttons(self, data):
# self.$attribute can be used, but not cls.$attribute?
pass
def test_buttons2(self, data):
# self.$attribute can be used, but not cls.$attribute?
pass
def teardown_class(cls):
pass
Et il semble même ne pas être correct de créer une instance de navigateur pour class. Elle devrait être créée pour chaque objet séparément, non?
Donc, je dois utiliser __init__
et __del__
méthodes au lieu de setup_class
et teardown_class
?
Selon finalisation du montage/exécution du code de démontage , l'utilisation de addfinalizer
est "historique".
En tant que note historique, un autre moyen d'écrire du code de démontage consiste à accepter un objet de requête dans votre fonction fixture et à appeler son request.addfinalizer une ou plusieurs fois:
La meilleure pratique actuelle pour l’installation et le démontage consiste à utiliser yield
import pytest
@pytest.fixture()
def resource():
print("setup")
yield "resource"
print("teardown")
class TestResource(object):
def test_that_depends_on_resource(self, resource):
print("testing {}".format(resource))
En cours d'exécution, il en résulte
$ py.test --capture=no pytest_yield.py
=== test session starts ===
platform darwin -- Python 2.7.10, pytest-3.0.2, py-1.4.31, pluggy-0.3.1
collected 1 items
pytest_yield.py setup
testing resource
.teardown
=== 1 passed in 0.01 seconds ===
Lorsque vous écrivez "tests définis comme méthodes de classe", voulez-vous dire vraiment méthodes de classe (méthodes qui reçoivent sa classe en tant que premier paramètre) ou juste des méthodes régulières (méthodes qui reçoivent une instance en tant que premier paramètre)?
Étant donné que votre exemple utilise self
pour les méthodes de test, je suppose que c'est la dernière, il vous suffit donc d'utiliser setup_method
au lieu:
class Test:
def setup_method(self, test_method):
# configure self.attribute
def teardown_method(self, test_method):
# tear down self.attribute
def test_buttons(self):
# use self.attribute for test
L'instance de la méthode de test est transmise à setup_method
et teardown_method
, mais peut être ignoré si votre code d'installation/de démontage n'a pas besoin de connaître le contexte de test. Plus d'informations peuvent être trouvées ici .
Je vous recommande également de vous familiariser avec fixtures de py.test, car ils constituent un concept plus puissant.
Comme @Bruno l'a suggéré, l'utilisation de luminaires pytest est une autre solution accessible pour les deux classes de test ou même pour de simples fonctions de test. Voici un exemple de test des fonctions python2.7 :
import pytest
@pytest.fixture(scope='function')
def some_resource(request):
stuff_i_setup = ["I setup"]
def some_teardown():
stuff_i_setup[0] += " ... but now I'm torn down..."
print stuff_i_setup[0]
request.addfinalizer(some_teardown)
return stuff_i_setup[0]
def test_1_that_needs_resource(some_resource):
print some_resource + "... and now I'm testing things..."
Donc, courir test_1...
produit:
I setup... and now I'm testing things...
I setup ... but now I'm torn down...
Remarquerez que stuff_i_setup
est référencé dans la fixture, permettant à cet objet d’être setup
et torn down
pour le test avec lequel il interagit. Vous pouvez imaginer que cela pourrait être utile pour un objet persistant, tel qu'une base de données hypothétique ou une connexion, qui doit être effacé avant chaque test afin de les maintenir isolés.
Cela pourrait aider http://docs.pytest.org/fr/latest/xunit_setup.html
Dans ma suite de tests, je regroupe mes cas de test en classes. Pour la configuration et le démontage dont j'ai besoin pour tous les tests élémentaires de cette classe, j'utilise les méthodes de classe setup_class(cls)
et teardown_class(cls)
.
Et pour la configuration et le démontage dont j'ai besoin pour chaque cas de test, j'utilise les fonctions setup_method(method)
et teardown_method(methods)
Exemple:
lh = <got log handler from logger module>
class TestClass:
@classmethod
def setup_class(cls):
lh.info("starting class: {} execution".format(cls.__name__))
@classmethod
def teardown_class(cls):
lh.info("starting class: {} execution".format(cls.__name__))
def setup_method(self, method):
lh.info("starting execution of tc: {}".format(method.__name__))
def teardown_method(self, method):
lh.info("starting execution of tc: {}".format(method.__name__))
def test_tc1(self):
<tc_content>
assert
def test_tc2(self):
<tc_content>
assert
Maintenant, lorsque je lance mes tests, au début de l'exécution de TestClass, il enregistre les détails de son exécution, de sa fin d'exécution et de la même chose pour les méthodes.
Vous pouvez ajouter d'autres étapes de configuration et de démontage que vous pourriez avoir aux emplacements respectifs.
J'espère que ça aide!
Votre code devrait fonctionner exactement comme vous le souhaiteriez si vous ajoutez @classmethod
décorateurs.
@classmethod
def setup_class(cls):
"Runs once per class"
@classmethod
def teardown_class(cls):
"Runs at end of class"
Voir http://pythontesting.net/framework/pytest/pytest-xunit-style-fixtures/