модульный тестовый пример для super() в python

#python #unit-testing #python-unittest

Вопрос:

У меня есть класс, как:

 """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)

 

У меня есть тестовый файл в виде :

 """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)

 

Когда я запускаю свою команду тестового покрытия. Приведенная ниже строка не покрыта :

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

Может ли кто-нибудь помочь мне с тем, как освещать super здесь. Я пытался издеваться или исправлять, но это не сработало.

Комментарии:

1. Это следствие A того, что класс не создается, что происходит из-за того, что не определены тесты, которые на самом деле требуют создания экземпляра A (на самом деле, вообще никаких тестов).

Ответ №1:

setUp() Метод вызывается только тогда, когда вы пишете метод тестирования, как описано в документации:

setUp()

Метод, вызванный для подготовки испытательного приспособления. Это вызывается непосредственно перед вызовом метода тестирования;…

 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)
 

Здесь вы не определили никакого метода тестирования, поэтому setUp() он никогда не будет вызван, поэтому A он никогда не будет инициализирован, что, в свою очередь, никогда не вызовет инициализацию родительского B элемента via super().__init__() .

 $ coverage run -m unittest discover

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

OK
$ coverage html
 

введите описание изображения здесь

Теперь будет запущен метод добавления теста setUp() A.__init__() , который инициализирует, что, в свою очередь, выполняется B.__init__() через 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
 

введите описание изображения здесь

Кроме того, вы упомянули о насмешках/исправлениях. Вы, может быть, непонимание того, что издевается над/патчи, потому что если вы дразните/патч вызов super().__init__() с заглушкой реализации, то она бы не назвал фактическую реализацию и вместо того, чтобы вызвать глумились/латать/уменьшенные версии, что означает, что оно не решит вашу проблему, потому что охват вашей фактической реализации не будет хватать, как вы заменили фактический звонок с пропатчен один. Другими словами, вы просто усугубляете свою проблему, исправляя 🙂

Комментарии:

1. @Нил. Лучшее объяснение. Большое Вам спасибо

Ответ №2:

Попробуйте исправить супер:

 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