2017-01-16 3 views
3

Um den Kesselplattencode zu reduzieren, kam ich auf die Idee, in der Klasse Tester Testfälle für alle parameterlosen Methoden zu generieren.Wie automatisch Testfälle für parameterlose Methoden generieren?

Auf py.test einsetzen, erkennt nur die statisch geschrieben Testfälle (Test_a, test_b), aber nicht die dynamisch erstellt Testfälle setattr(Tester,'test_' + name, member)

Vielleicht mit py.test bereits die Klasse Tester inspiziert für Methoden mit 'test_ *' bevor setUpClass aufgerufen wird? Irgendwelche Hinweise wie man das laufen lässt?

import inspect 
import unittest 


class Testee: 
    def a(self): 
     print('a') 

    def b(self): 
     print('b')  

    #... 

    #... 
    def z(self): 
     print('z') 

class Tester(unittest.TestCase): 

    @classmethod 
    def setUpClass(cls): 
     testee = Testee() 
     for name, member in inspect.getmembers(object=testee, predicate=inspect.ismethod or inspect.iscoroutine): 
      if len(inspect.signature(member).parameters): 
       print(str(inspect.signature(member).parameters)) 
       setattr(Tester,'test_' + name, member) 
      if inspect.isfunction(member) or inspect.ismethod(member): 
       setattr(Tester,'test_' + name, member) 
      elif inspect.iscoroutinefunction(member): 
       setattr(Tester,'test_' + name, functools.partialmethod(TestInstrument.run_coro, member)) 
      else: 
       print(member) 
     return super().setUpClass() 

    def test_a(self): 
     Tester.testee.a() 

    def test_b(self): 
     Tester.testee.b() 

============================= Testsitzung beginnt ========= ==================== Plattform win32 - Python 3.5.1, Pytest-2.9.2, py-1.4.31, Pluggy-0.3.1 - c: \ program Dateien \ python35 \ python.exe cachedir: .cache rootdir: C: \ Tests, inifile: gesammelt 2 Artikel

sandbox.py::Tester::test_a PASSED sandbox.py::Tester::test_b PASSED

========================== 2 in 0,03 Sekunden vergangen ============== =============

EDIT: Wenn ich den Code in setupClass auf den globalen Bereich bewegen (außerhalb der Klasse), dann py.test erkennt und führt die automatisch generierten Testfälle.

+0

Können Sie bitte posten, wo Sie die Testklasse instanziieren? Bitte verwenden Sie auch 'cls' anstelle von' Tester' in Ihrem Setattr. –

+0

@Vinzenzzzochi py.test macht die Instantiierung für mich. – goldcode

Antwort

0

Um auf meine "EDIT" zu erarbeiten, wäre eine Option so. Ich bin unzufrieden mit der Lösung, weil die globale Codeausführung offen für Nebeneffekte und andere kleine Fehler sein könnte. irgendwelche Vorschläge, wie man dies in Klasse Tester Bereich bekommen?

import inspect 
import unittest 
import functools 
def auto_generate_test_cases(Tester, Testee): 
    def run(self, fn): 
     fn(Tester._testee) 
    for name, member in inspect.getmembers(
     object=Testee, predicate=inspect.isfunction or inspect.iscoroutine): 
     if len(inspect.signature(member).parameters) == 1:    
      setattr(Tester,'test_' + name, functools.partialmethod(run, member)) 

class Testee: 
    def __init__(self): 
     self._a = 'a' 
    def a(self): 
     print(self._a) 
    def ab(self, a, b): 
     print('a') 
    def b(self): 
     print('b')  
    def h(self): 
     print('h')  
    async def q(self): 
     print('async q') 
    #... 

    #... 
    def z(self): 
     print('z') 

class Tester(unittest.TestCase): 
    _testee = Testee() 
auto_generate_test_cases(Tester, Testee) 

py.test. Ausgabe:

C:\tests>py.test sandbox.py --verbose 
============================= test session starts ============================= 
platform win32 -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- c:\program files\python35\python.exe 
cachedir: .cache 
rootdir: C:\\tests, inifile: 
collected 5 items 

sandbox.py::Tester::test_a PASSED 
sandbox.py::Tester::test_b PASSED 
sandbox.py::Tester::test_h PASSED 
sandbox.py::Tester::test_q PASSED 
sandbox.py::Tester::test_z PASSED 

========================== 5 passed in 0.07 seconds =========================== 
Verwandte Themen