Aman Raheja
Aman Raheja

Reputation: 615

unit test case for super() in python

I have a class as:

"""A"""

from clay import config
from datetime import timedelta
from <path> import B

EXECUTION_TIMEOUT = timedelta(minutes=30)

class A(B):
    """Crawler task for A"""

    def __init__(self, *args, **kwargs):
        """Initialization."""
        super(A, self).__init__(execution_timeout=EXECUTION_TIMEOUT, *args, **kwargs)

I have a test file as :

"""Test class for A"""
from datetime import timedelta, datetime
from doubles import allow
from mock import patch, MagicMock
from unittest import TestCase
import mock

from <path> import A


class JobInfoHandler:
    """Mock job info."""

    def __init__(self):
        """Init Method."""
        self.crawlerConfig = None
        pass


class TestA(TestCase):
    """Test class for A."""

    def setUp(self):
        """Create instance of class to test."""
        job_info_ob = JobInfoHandler()
        self.obj_a = A(owner='arahej', task_id='12',
                                              schedule_interval=timedelta(minutes=60), job_info=job_info_ob)

When I run my test coverage command. The below line is not covered :

super(A, self).__init__(execution_timeout=EXECUTION_TIMEOUT, *args, **kwargs)

Can anyone help me with how to cover super here. I tried to mock or patch, but it didn't worked.

Upvotes: 0

Views: 1284

Answers (2)

Niel Godfrey P. Ponciano
Niel Godfrey P. Ponciano

Reputation: 10709

The setUp() method is only called when you write a test method as documented:

setUp()

Method called to prepare the test fixture. This is called immediately before calling the test method;...

class TestA(TestCase):
    """Test class for A."""

    def setUp(self):
        """Create instance of class to test."""
        print("Setting up testcase")
        job_info_ob = JobInfoHandler()
        self.obj_a = A(owner='arahej', task_id='12',
                                              schedule_interval=timedelta(minutes=60), job_info=job_info_ob)

Here, you haven't defined any test method, thus setUp() would never be called, thus A would never be initialized which in turn would never call the initialization of parent B via super().__init__().

$ coverage run -m unittest discover

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK
$ coverage html

enter image description here

Adding a test method would now run setUp() which would initialize A.__init__() which in turn runs B.__init__() via super().

class TestA(TestCase):
    def setUp(self):
        ...

    def test_first(self):
        print("1st test method called")
        assert True
$ coverage run -m unittest discover
Setting up testcase
1st test method called
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
$ coverage html

enter image description here

Also, you mentioned about mocks/patches. You maybe misunderstanding what mocks/patches are for, because if you mock/patch the call to super().__init__() with a stub implementation, then it would not call the actual implementation and instead call the mocked/patched/stubbed version, which means it wouldn't solve your problem because the coverage to your actual implementation would still be missing as you replaced the actual call with a patched one. In other words, you're just making your problem worse by patching :)

Upvotes: 2

KodornaRocks
KodornaRocks

Reputation: 405

Try patching super:

from mock import patch


class B(object):

    def foo(self):
        print('foo from B')


class A(B):

    def foo(self):
        self.called_foo = True
        super(A, self).foo()


class TestA(object):

    @patch('%s.super' % __name__, create=True)
    def test_foo(self, super_func):
        A = A()
        A.foo()
        assert A.called_foo
        assert super_func.called

Upvotes: 1

Related Questions