Python多重继承只对一个父方法有效,但从两个父方法调用方法

2024-10-02 06:22:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我有个Python/OOP问题
你们都熟悉C++中的钻石问题,对吧?这是相似的。
我有以下课程

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

现在,当我运行代码时,我可以看到这是打印出来的:

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

但是如果从功能角度来看,测试只运行BasicAuthTests。我怎么知道的?

1.测试运行的次数是6,而每个父类的测试运行次数应该是126

2.如果我将BasicAuthTests中的_get_authenticated_api_client()函数更改为错误的return类型,代码会崩溃,但是如果我在TokenAuthTests中更改它,什么都不会发生,这意味着TokenAuthTests没有做任何事情,而是它的print语句正在工作,这意味着调用了函数。

这太令人困惑了,有人能帮忙吗?
我的最终目标是为每个父类返回的api_client运行这6个测试

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.


Tags: intestselfclienttokenauthapiget
2条回答

你被我们的MRO困住了。 虽然Python支持Diamond Inheritance,但是当涉及到变量赋值时,您将陷入困境

多亏了Diamond Inheritance,我们现在都_get_authenticated_api_client将被调用。当谈到赋值时,_get_authenticated_api_client返回的内容取决于传递类的顺序

在您的例子中,只有6个测试运行,因为您只有一个类,有6个测试函数

您打算使用不同的auth方法运行完全相同的测试。 一个简单的方法是:

class ClientMixinCase: #Do not Inherit from "TestCase"
    #... Declare you tests here

class ClientWithTokenAuthTestCase(ClientMixinCase,TokenAuthTests):
    pass

class ClientWithBasicAuthTestCase(ClientMixinCase,BasicAuthTests):
    pass

所以我用另一种方法解决了这个问题。

我们可以做的是,我们可以声明父类中的所有测试,并在子类中声明函数_get_authenticated_api_client

但如何在父类中使用子类的函数呢

当父类继承TestCase并且将是运行测试的第一个类时,它将崩溃,因为它没有_get_authenticated_api_client函数。

为了避免这种情况,我们要做的是将父类包装到另一个类中,这样该类就不会被视为类,而是被视为父类的对象。

但是,当我们从包装的父继承类TestCase继承的类继承子类时,它将被视为类,它的测试将运行,但此时_get_authenticated_api_client函数将在child中声明。 这是密码

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

相关问题 更多 >

    热门问题