12

I have some code as shown below. I am getting a too few args error when I run it. I am not calling setup_class explicitly, so not sure how to pass any parameter to it. I tried decorating the method with @classmethod, but still see the same error.

The error that I am seeing is this - E TypeError: setup_class() takes exactly 2 arguments (1 given)

One point to note - If I do not pass any parameter to the class, and pass only cls, then I am not seeing the error.

Any help is greatly appreciated.

I did review these questions question #1 and question #2prior to posting. I did not understand the solutions posted to these questions, or how they would work.

class A_Helper:
    def __init__(self, fixture):
        print "In class A_Helper"

    def some_method_in_a_helper(self):
        print "foo"

class Test_class:
    def setup_class(cls, fixture):
        print "!!! In setup class !!!"
        cls.a_helper = A_Helper(fixture)

    def test_some_method(self):
        self.a_helper.some_method_in_a_helper()
        assert 0 == 0
Community
  • 1
  • 1
Muthu Palanisamy
  • 765
  • 2
  • 9
  • 17
  • @metatoaster I should not have to instantiate `Test_class`. I am expecting `A_Helper` to be instantiated using the `arg` that I supply. And then using that object (`a_helper`), I am hoping to invoke the method in `A_Helper`. Am I conceptually missing something? Same code works, without having to instantiate anything, as long as I do not provide an arg to the `setup_class`. – Muthu Palanisamy Feb 02 '15 at 23:22
  • As pointed out by @metatoaster it can't be done. But wouldn't it be simplier to define `a_helper` fixture (with `scope='class'`) and pass it to `test_some_method`? Generally `setup_class` handling is added to py.test only to make it compatible with classical unit-style testing. I advice not to mix these two things (i.e. classical style with py.test fixture style). – freakish Feb 03 '15 at 15:37

2 Answers2

16

You get this error because you are trying to mix two independent testing styles that py.test supports: the classical unit testing and pytest's fixtures.

What I suggest is not to mix them and instead simply define a class scoped fixture like this:

import pytest

class A_Helper:
    def __init__(self, fixture):
        print "In class A_Helper"

    def some_method_in_a_helper(self):
        print "foo"

@pytest.fixture(scope='class')
def a_helper(fixture):
    return A_Helper(fixture)

class Test_class:
    def test_some_method(self, a_helper):
        a_helper.some_method_in_a_helper()
        assert 0 == 0
freakish
  • 54,167
  • 9
  • 132
  • 169
  • Hi, I wish to use your approach but in addition of using the fixture inside the test function, pass it also to prolog function like `setup_class` or `setup_method`. Perhaps you can extend your example to add this functionality ? Thanks ! – Zohar81 Jul 02 '19 at 08:08
  • This means that referenced fixture `fixture` should also be scoped as `class`, which is a nightmare. – VisioN Mar 17 '22 at 14:01
7

Since you are using this with pytest, it will only call setup_class with one argument and one argument only, doesn't look like you can change this without changing how pytest calls this.

You should just follow the documentation and define the setup_class function as specified and then set up your class inside that method with your custom arguments that you need inside that function, which would look something like

class Test_class:
    @classmethod
    def setup_class(cls):
        print "!!! In setup class !!!"
        arg = '' # your parameter here
        cls.a_helper = A_Helper(arg)

    def test_some_method(self):
        self.a_helper.some_method_in_a_helper()
        assert 0 == 0
jxramos
  • 7,356
  • 6
  • 57
  • 105
metatoaster
  • 17,419
  • 5
  • 55
  • 66
  • I edited the question, and replaced `arg` with `fixture`. My intent is - **from** the test method, I want to pass one or more fixtures **to** a helper method, and do some action with the `fixture` in the helper method. If passing a second arg is not possible, then I am not sure how I would pass a fixture, even in the body of the method. – Muthu Palanisamy Feb 03 '15 at 15:43
  • One comment in the documentation is pretty interesting, specifically under the _Remarks_ section at the end: _Now the xunit-style functions are integrated with the fixture mechanism and obey the proper scope rules of fixtures involved in the call._ I wonder if this broke that "mixing" technique that @freakish mentioned in the other answer which may have previously worked when the scope rules weren't obeyed. – jxramos Feb 21 '20 at 23:44