Ad

Python Multiple Inheritance Only Working For One Parent's Method But Calling Method From Both Parents

- 1 answer

I have a Python/OOP question.
You are all familiar with diamond problem in C++ right? This is something similar.
I have the following classes

class BaseAuth(TestCase):

    def setUp(self):
        # create dummy user and client, removing code of that for simplicity.
        self.user.save()
        self.client.save()

    def _get_authenticated_api_client(self):
        pass

class TokenAuthTests(BaseAuth):

    def _get_authenticated_api_client(self):
        super()._get_authenticated_api_client()
        print("I AM IN TOKEN AUTH")
        api_client = APIClient()
        # do stuff with api_client
        return api_client

class BasicAuthTests(BaseAuth):

    def _get_authenticated_api_client(self):
        super()._get_authenticated_api_client()
        print("I AM IN BASIC AUTH")
        api_client = APIClient()
        # do stuff with api client
        return api_client

class ClientTestCase(BasicAuthTests, TokenAuthTests):

    def test_get_login_response(self):
        api_client = self._get_authenticated_api_client()
        # login test code

    def test_get_clients(self):
        api_client = self._get_authenticated_api_client()
        # get client test code

    def test_get_client_by_id(self):
        api_client = self._get_authenticated_api_client()
        # get client by id test code

    def test_update_client_by_id(self):
        api_client = self._get_authenticated_api_client()
        # update client test code

    def test_add_client(self):
        api_client = self._get_authenticated_api_client()
        # add client test code

    def test_delete_client_by_id(self):
        api_client = self._get_authenticated_api_client()
        # delete client test code

Now, when I run the code, I can see that this is printed out:

I AM IN TOKEN AUTH
I AM IN BASIC AUTH
.I AM IN TOKEN AUTH
I AM IN BASIC AUTH
.I AM IN TOKEN AUTH
I AM IN BASIC AUTH
.I AM IN TOKEN AUTH
I AM IN BASIC AUTH
.I AM IN TOKEN AUTH
I AM IN BASIC AUTH
.I AM IN TOKEN AUTH
I AM IN BASIC AUTH

But if I see functionality wise, the tests run for only BasicAuthTests. How do I know this?

1. The number of test runs is 6, when it should be 12, 6 with each parent class.

2. If I change the _get_authenticated_api_client() function in BasicAuthTests to wrong return type, the code crashes but if I change it in TokenAuthTests nothing happens, which means, the TokenAuthTests is not doing anything, but its print statement in working which means function is called.

This is so confusing, can somebody please help?
My ultimate goal here is to run these 6 tests for each of the parent class's returned api_client.

HERE IS MUST MENTION THAT, THE CODE RUNS FINE. AND THE TEST WORK ALRIGHT IF I RUN THEM SEPARATELY. I AM TRYING TO SIMPLIFY THE CODE AND REMOVE ALL THE REPETITION, THAT'S WHY I AM KIND TO TRYING TO MERGE THEM INTO ONE FILE.

Ad

Answer

So I solved this problem by using a different approach.

What we can do is, we can declare all the tests in a parent class and declare the function _get_authenticated_api_client in child classes.

But how can we use a child class's function in parent class?

When parent class inherits TestCase and will be the first class from which tests will be run and it will crash because it won't have _get_authenticated_api_client function.

To avoid this what we do is we wrap the parent class in another class, this way that class will not be treated as a class but as an object of parent class.

But when we inherit our child classes from that wrapped parent TestCase inherited class, it will be treated like class and it's tests will be run but at that point the _get_authenticated_api_client function will be declared in child. Here's the code

class WrapperTestClass:

    class ClientTestCase(TestCase):

        # all the tests and setup function

class TokenAuthTests(WrapperTestClass.ClientTestCase):

    def get_authenticated_api_client(self):
        # function that returns api_client

class BasicAuthTests(WrapperTestClass.ClientTestCase):

    def get_authenticated_api_client(self):
        # function that returns api_client
Ad
source: stackoverflow.com
Ad