web-dev-qa-db-fra.com

Arguments de passage en Python

En python, comment passer d'un argument de la ligne de commande à une fonction unittest. Voici le code jusqu'à présent… Je sais que c'est faux.

class TestingClass(unittest.TestCase):

    def testEmails(self):
        assertEqual(email_from_argument, "[email protected]")


if __== "__main__":
    unittest.main(argv=[sys.argv[1]])
    email_from_argument = sys.argv[1] 
49
Christopher H

Pour étendre le commentaire ci-dessus à propos des tests unitaires. Les tests unitaires doivent être autonomes en ce sens qu’ils n’ont aucune dépendance en dehors de leurs exigences de configuration et de démontage, comme dans votre cas, la configuration d’un courrier électronique. Cela garantit que chaque test a des effets secondaires et des réactions très spécifiques au test. Passer un paramètre annule cette propriété des tests unitaires et les rend donc invalides dans un sens. L'utilisation d'une configuration de test serait le moyen le plus simple et le plus approprié, car encore une fois, un test unitaire ne devrait jamais s'appuyer sur des informations extérieures pour effectuer le test. C'est pour les tests d'intégration.

17
sean

Donc, les médecins ici qui disent "Vous dites que ça fait mal? Alors ne faites pas ça!" ont probablement raison. Mais si vous voulez vraiment, voici une façon de passer des arguments à un test unittest:

import sys
import unittest

class MyTest(unittest.TestCase):
    USERNAME = "jemima"
    PASSWORD = "password"

    def test_logins_or_something(self):
        print 'username', self.USERNAME
        print 'password', self.PASSWORD


if __== "__main__":
    if len(sys.argv) > 1:
        MyTest.USERNAME = sys.argv.pop()
        MyTest.PASSWORD = sys.argv.pop()
    unittest.main()

cela vous permettra de courir avec:

python mytests.py ausername apassword

Vous avez besoin du argv.pops pour que vos paramètres de ligne de commande ne plaisent pas avec le propre unittest ...

[mise à jour] L'autre chose que vous voudrez peut-être examiner concerne l'utilisation de variables d'environnement:

import os
import unittest

class MyTest(unittest.TestCase):
    USERNAME = "jemima"
    PASSWORD = "password"

    def test_logins_or_something(self):
        print 'username', self.USERNAME
        print 'password', self.PASSWORD


if __== "__main__":
    MyTest.USERNAME = os.environ.get('TEST_USERNAME', MyTest.USERNAME)            
    MyTest.PASSWORD = os.environ.get('TEST_PASSWORD', MyTest.PASSWORD)
    unittest.main()

Cela vous permettra de courir avec:

TEST_USERNAME=ausername TEST_PASSWORD=apassword python mytests.py

et cela a l'avantage de ne pas jouer avec l'analyse des arguments de unittest. inconvénient est que cela ne fonctionnera pas tout à fait comme ça sous Windows ...

89
hwjp

Une autre méthode pour ceux qui veulent vraiment le faire malgré les remarques correctes qu'il ne faut pas faire

import unittest

class MyTest(unittest.TestCase):

    def __init__(self, testName, extraArg):
        super(MyTest, self).__init__(testName)  # calling the super class init varies for different python versions.  This works for 2.7
        self.myExtraArg = extraArg

    def test_something(self):
        print self.myExtraArg

# call your test
suite = unittest.TestSuite()
suite.addTest(MyTest('test_something', extraArg))
unittest.TextTestRunner(verbosity=2).run(suite)
18
steffens21

Si vous souhaitez utiliser l'approche de steffens21 avec unittest.TestLoader, vous pouvez modifier le chargeur de test d'origine (voir unittest.py):

import unittest
from unittest import suite

class TestLoaderWithKwargs(unittest.TestLoader):
    """A test loader which allows to parse keyword arguments to the
       test case class."""
    def loadTestsFromTestCase(self, testCaseClass, **kwargs):
        """Return a suite of all tests cases contained in 
           testCaseClass."""
        if issubclass(testCaseClass, suite.TestSuite):
            raise TypeError("Test cases should not be derived from "\
                            "TestSuite. Maybe you meant to derive from"\ 
                            " TestCase?")
        testCaseNames = self.getTestCaseNames(testCaseClass)
        if not testCaseNames and hasattr(testCaseClass, 'runTest'):
            testCaseNames = ['runTest']

        # Modification here: parse keyword arguments to testCaseClass.
        test_cases = []
        for test_case_name in testCaseNames:
            test_cases.append(testCaseClass(test_case_name, **kwargs))
        loaded_suite = self.suiteClass(test_cases)

        return loaded_suite 

# call your test
loader = TestLoaderWithKwargs()
suite = loader.loadTestsFromTestCase(MyTest, extraArg=extraArg)
unittest.TextTestRunner(verbosity=2).run(suite)
3
sfinkens

J'ai le même problème. Ma solution consiste à supprimer les arguments de sys.argv après avoir manipulé les arguments d'analyse syntaxique à l'aide d'argparse

sys.argv = sys.argv[:1]  

Si vous avez besoin, vous pouvez filtrer les arguments unittest de main.parseArgs ()

0
Denis Solovjev

Test unitaire est conçu pour tester les fonctionnalités de base (fonctions de bas niveau de l'application) afin de vous assurer que vos blocs de construction application fonctionnent correctement. Il n’existe probablement pas de définition officielle de ce que cela signifie exactement, mais vous devriez envisager d’autres types de test pour la fonctionnalité plus grande - voir Test d’intégration . Le cadre de test unitaire peut ne pas être idéal à cet effet.

0
pepr

Même si les gourous du test disent que nous ne devrions pas le faire: je le fais. Dans certains contextes, il est judicieux de disposer de paramètres permettant de conduire le test dans la bonne direction, par exemple:

  • laquelle des douze cartes USB identiques devrais-je utiliser pour ce test maintenant?
  • quel serveur dois-je utiliser pour ce test maintenant?
  • quel XXX devrais-je utiliser?

Pour moi, l'utilisation de la variable d'environnement est assez bonne pour ce problème car vous n'avez pas à écrire de code dédié pour transmettre vos paramètres; il est supporté par Python. C'est propre et simple.

Bien sûr, je ne préconise pas des tests entièrement paramétrables. Mais nous devons être pragmatiques et, comme je l'ai dit, dans certains contextes, vous avez besoin d'un paramètre ou deux. Nous ne devrions pas y renoncer :)

import os
import unittest


class MyTest(unittest.TestCase):
    def setUp(self):
        self.var1 = os.environ["VAR1"]
        self.var2 = os.environ["VAR2"]

    def test_01(self):
        print("var1: {}, var2: {}".format(self.var1, self.var2))

Puis depuis la ligne de commande (testé sur Linux)

$ export VAR1=1
$ export VAR2=2
$ python -m unittest MyTest
var1: 1, var2: 2
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
0
Federico