Vraag Hoe sla ik een volledige Python Unittest-module over tijdens runtime?


Ik zou graag zien dat mijn Python Unittest-module de testrunner vertelt om het geheel over te slaan in bepaalde situaties (zoals het niet kunnen importeren van een module of het lokaliseren van een kritieke bron).

ik kan gebruiken @unittest.skipIf(...) om een ​​Unittest.TestCase-klasse over te slaan, maar hoe sla ik de hele module? Het toepassen van skips op elke klasse is niet voldoende omdat de klassendefinities zelf uitzonderingen zouden kunnen veroorzaken als een module niet kan importeren.


21
2017-09-19 01:54


oorsprong


antwoorden:


Na hier naar de andere antwoorden te hebben gekeken, is dit het beste antwoord dat ik heb bedacht. Het is lelijk, het hele testsuite in de uitzonderingsafhandeling inbedden, maar het lijkt te doen wat je wilt. Specifiek overslaan van de tests wanneer de invoer niet werkt.

Ervan uitgaande dat je het hebt over het gebruik van nosetests -x voor het uitvoeren van de tests, zou het moeten doorgaan met de tests die overslaan, in ieder geval leek het toen ik het probeerde.

import unittest
try:
    import PyQt4
    # the rest of the imports


    # actual tests go here.
    class TestDataEntryMixin(unittest.TestCase):
        def test_somefeature(self):
            # ....

except ImportError, e:
    if e.message.find('PyQt4') >= 0:
        class TestMissingDependency(unittest.TestCase):

            @unittest.skip('Missing dependency - ' + e.message)
            def test_fail():
                pass
    else:
        raise

if __name__ == '__main__':
    unittest.main()

Als het importeren mislukt, wordt de testrun vervangen door een enkele test die gewoon wordt overgeslagen. Ik heb ook geprobeerd ervoor te zorgen dat het onbedoeld geen uitzonderingen inslikt. Deze oplossing heeft veel te danken aan alle andere antwoorden en opmerkingen op de vraag.

Als u het in de uitgebreide modus uitvoert, ziet u dit wanneer het overgeslagen wordt,

test_fail (test_openihm_gui_interface_mixins.TestMissingDependency) ... skipped 'Missing dependency - No module named PyQt4'

6
2017-09-20 10:12



Als je kijkt naar de definitie van unittest.skipIf en unittest.skip, je kunt zien dat de sleutel het doet raise unittest.SkipTest(reason) wanneer de test wordt uitgevoerd. Als je in orde bent met het laten verschijnen een overgeslagen test in plaats van meerdere in de testrunner, je kunt gewoon raisen unittest.SkipTest jezelf bij het importeren:

import unittest
try:
    # do thing
except SomeException:
    raise unittest.SkipTest("Such-and-such failed. Skipping all tests in foo.py")

Lopen met nosetests -v geeft:

Failure: SkipTest (Such-and-such failed. Skipping all tests in foo.py) ... SKIP:
Such-and-such failed. Skipping all tests in foo.py

----------------------------------------------------------------------
Ran 1 test in 0.002s

OK (SKIP=1)

14
2017-09-19 04:22



Ik ontdekte dat het gebruik van skipTest in setUp goed werkte. Als u een module wilt importeren, gebruikt u een try-blok om b.v. module_failed = Waar, en in setUP call skipTest als het is ingesteld. Dit rapporteert het juiste aantal test skips met slechts een korte try-block nodig:

import unittest

try:
    import my_module
    module_failed = False
except ImportError:
    module_failed = True

class MyTests(unittest.TestCase):
    def setUp(self):
        if module_failed:
            self.skipTest('module not tested')

    def test_something(self):
            #...

9
2018-05-08 08:42



De oplossing voorgesteld door otus werkt en is naar mijn mening gemakkelijker dan de geaccepteerde oplossing. Maar er is minstens één nadeel. Als je een vraag stelt my_module in een binnenhuisarchitect om een ​​enkele test over te slaan, zoals

@unittest.skipIf(my_module.support_foo, 'foo not supported')
def test_foo(self):
...

je krijgt een NameError: name 'my_module' is not defined. De oplossing is de skip binnen de functiedefinitie:

def test_foo(self):
    if not my_module.support_foo:
        self.skipTest('foo not supported')

3
2017-09-10 14:43



Probeer een gebruik te definiëren load_tests functie in uw module:

import unittest
try:
    (testcases)
except ImportError as e:
    def load_tests(*args, **kwargs):
        print("Failed to load tests: skipping")
        return unittest.TestSuite() # no tests

2
2017-09-19 04:25



Het kan zijn vuil om alle unittest.TestCase subklasse definities in a try...except blokkeren, maar het zou werken:

import unittest
try:
    import eggs
    class Spam(unittest.TestCase):
        pass
    class Ham(unittest.TestCase):
        pass
    # ...
except ImportError:
    # print 'could not import eggs'
    pass

Geen van de subklassen zou worden gedefinieerd als de eggs import mislukt en al die klassen (Spam, Ham, etc. ) wordt overgeslagen. Zou niet worden weerspiegeld in de output (goed of slecht, afhankelijk van wat je wilt).


2
2017-09-19 04:00



Voor python 2.7+ (of met behulp van unittest2 backport):

...

import unittest

def setUpModule():
    try:
        import something
    except ImportError as err:
        raise unittest.SkipTest(str(err))

class Tests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        try:
            import something
        except ImportError as err:
            raise unittest.SkipTest(str(err))
...

1
2018-06-17 19:21



Combinatie van de genoemde antwoorden en gebruik dit antwoord:

import unittest
def module_exists(module_name):
    try:
        __import__(module_name)
    except ImportError:
        return False
    else:
        return True

class TestClass(unittest.TestCase):

    @unittest.skipUnless(module_exists("moduleA"), 'ModuleA not installed')
    def test_something(self):
        # test something with moduleA

0
2018-02-25 15:29