webentwicklung-frage-antwort-db.com.de

Python ist das einzige Argument, das die Argumente übertrifft

Wie würde ich in Python ein Argument von der Kommandozeile an eine einzige Funktion übergeben? Hier ist der Code soweit… ich weiß, dass es falsch ist.

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

Mit dem obigen Kommentar zu Komponententests erweitern. Unit-Tests sollten für sich alleine stehen, da sie keine Abhängigkeiten außerhalb ihrer Setup- und Abbau-Anforderungen haben, wie z. B. bei der Einrichtung einer E-Mail. Dies stellt sicher, dass jeder Test sehr spezifische Nebenwirkungen und Reaktionen auf den Test hat. Durch die Übergabe eines Parameters wird diese Eigenschaft von Komponententests vereitelt und somit unwirksam. Die Verwendung einer Testkonfiguration wäre der einfachste und auch zweckmäßigere, da wiederum ein Komponententest niemals auf externe Informationen angewiesen sein sollte, um den Test durchzuführen. Das ist für Integrationstests.

17
sean

Die Ärzte hier, die sagen: "Sie sagen, dass es weh tut? Dann machen Sie das nicht!" sind wohl richtig. Wenn Sie es aber wirklich wollen, können Sie die Argumente auf eine einzige Prüfung übergeben:

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()

das wird Sie mit laufen lassen:

python mytests.py ausername apassword

Sie benötigen den argv.pops, damit Ihre Befehlszeilenparameter nicht mit den eigenen Einstellungen von unittest verwirren.

[Update] Die andere Sache, die Sie untersuchen möchten, ist die Verwendung von Umgebungsvariablen:

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()

Das lässt Sie mit laufen:

TEST_USERNAME=ausername TEST_PASSWORD=apassword python mytests.py

und es hat den Vorteil, dass Sie sich nicht mit dem eigenen Argumentieren von unittest herumschlagen. Nachteil ist, dass es unter Windows nicht ganz so funktioniert ...

89
hwjp

Eine weitere Methode für diejenigen, die dies wirklich tun möchten, trotz der richtigen Anmerkungen, die Sie nicht beachten sollten:

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

Wenn Sie den Ansatz von steffens21 mit unittest.TestLoader verwenden möchten, können Sie den ursprünglichen Testloader ändern (siehe 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

Habe ein gleiches Problem. Meine Lösung ist, nachdem Sie mit der Analyse von Argumenten mit argparse oder auf andere Art und Weise umgegangen sind, entfernen Sie Argumente aus sys.argv

sys.argv = sys.argv[:1]  

Wenn Sie möchten, können Sie die einzigen Argumente aus main.parseArgs () filtern.

0
Denis Solovjev

Unit Testing dient zum Testen der sehr grundlegenden Funktionalität (der untersten Funktionen der Anwendung), um sicherzustellen, dass Ihre Anwendungsbausteine ​​ ordnungsgemäß funktionieren. Es gibt wahrscheinlich keine formale Definition dessen, was genau dies bedeutet, aber Sie sollten andere Arten von Tests für die größere Funktionalität - siehe Integrationstest in Betracht ziehen. Das Unit-Test-Framework ist für diesen Zweck möglicherweise nicht ideal.

0
pepr

Auch wenn die Testgurus sagen, dass wir es nicht tun sollten: ich tue. In manchen Zusammenhängen ist es sehr sinnvoll, Parameter zu haben, die den Test in die richtige Richtung lenken, zum Beispiel:

  • welche der vielen identischen USB-Karten sollte ich jetzt für diesen Test verwenden?
  • welchen Server sollte ich jetzt für diesen Test verwenden?
  • welche XXX soll ich verwenden?

Für mich ist die Verwendung der Umgebungsvariablen für diesen Zweck gut genug, da Sie keinen dedizierten Code schreiben müssen, um Ihre Parameter zu übergeben. Es wird von Python unterstützt. Es ist sauber und einfach.

Natürlich plädiere ich nicht für vollständig parametrierbare Tests. Aber wir müssen pragmatisch sein und, wie gesagt, in manchen Zusammenhängen braucht man ein oder zwei Parameter. Wir sollten es nicht übel nehmen :)

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))

Dann von der Kommandozeile (getestet unter Linux)

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

OK
0
Federico