2

I really couldn't find a solution for :

PytestCollectionWarning: cannot collect test class 'TestBlaBla' because it has a init constructor

Here is my testing module and it needs to take the arguments outside of this file because at the end of the day I'm gonna call all test modules in a single file and run them all over different names and there is a bunch of names. I have to init them but when I run pytest it always ignores these classes. Idk how to handle without initializing them. If there is any suggestions I would be glad to hear.

tests/test_bla_bla.py
class TestBlaBla():
    def __init__(self, **kwargs):
     
        self.name1 = kwargs.get("name1")
        self.name2 = kwargs.get("name2")

    @pytest.fixture(scope='session')
    def load_data_here(self): 
        return load_data(self.name1) # a function comes from a utils file. it only stands for load data and it needs take a name for path
..
"continue with test_ functions that use output of load_data_here"

tests/main.py
class TestingAll:
    def __init__(self, *args, **kwargs):
        self.name1 = kwargs.get("name1")
        self.name2 = kwargs.get("name2")
        self._process()
        
    def _process(self):
        TestBlaBla(name1 = self.name1, name2= self.name2)
        TestBlaBla2(name1 = self.name1, name2= self.name2)

        
        
if __name__ == "__main__":
    Test = TestingAll(name1 = "name1", name2= "name2")
Hazel
  • 21
  • 1
  • 3

1 Answers1

-1

Python test modules cannot have init methods as python test instantiates the class itself and there is not any way (IMHO?) to extend the instantiation and add arguments.

Yes, it is a natural idea to want to make your tests flexible by passing in command-line arguments. But you can't :-P. So you need to find another way of doing this.

Note also the if name == 'main': can work if you call the test file with python and add some code to explicitly call a py test runner. Note you do not just call your test class. A python test runner needs to be instantiated itself and run tests in a particular way.

e.g. we can have this which will allow python to instantiate and run tests in a TestingAll class (as long as it doesn't have an init method).

This uses the unittest.TextTestRunner

Note there are all sorts of python test runners, also runners like nose2 or like py.test which use a different test library.

if __name__ == '__main__':
    unittest.main()
    suite = unittest.TestLoader().loadTestsFromTestCase(TestingAll)
    unittest.TextTestRunner(verbosity=3).run(suite)

You could maybe have an ArgsProcess class to process command line args. Then iterate and set a global var with each value to be used and call the test runner each time.

But it depends on how your tests will be used.

The answers on this question already mentioned in comments explain and link to documentation for this warning:

py.test skips test class if constructor is defined

The answer on this question shows how an init method is replaced by using fixture:

Pytest collection warning due to __init__ constructor

Maybe something like this would work for you.

gaoithe
  • 4,218
  • 3
  • 30
  • 38