Элемент списка (объект) не подлежит подписке - PullRequest
0 голосов
/ 20 июня 2020

Я хочу создать модульный тест для функции, которая сортирует список объектов в соответствии с некоторыми атрибутами объекта. Вот пример кода:

class Foo:
    """Custom data type Foo."""

    def __init__(self,
                 a: str,
                 b: int,
                 c: int,
                 d: int,
                 e: int,
                 f: int):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.e = e
        self.f = f
        self.g = c * d * e
        self.h = c * d

Это часть функции модульного тестирования, которая выдает ошибку:

from random import randint
...
class Test(TestCase):

def test_item_sort_foo(self):
    random_list = [Foo(str(randint(0, 1000)),
                        randint(0, 100),
                        randint(0, 100),
                        randint(0, 100),
                        randint(0, 100),
                        randint(0, 100))
                   for x in range(100)]
...

Сообщение об ошибке:

TypeError: 'Foo' object is not subscriptable. 

Несмотря на то, что прочитал этот вопрос , я не могу понять, почему Python заботится о том, что Foo имеет подписку, поскольку random_list уже есть. Я пытаюсь создать список случайных Foo элементов аналогично ответу здесь . Я озадачен, потому что у меня уже есть (рабочий) класс

from dataclasses import dataclass
from typing import List


@dataclass
class Bar:
    """Bar custom data type."""
    i: str
    j: List[Foo]

И я могу ввести, например,

f = Foo(...)
b = Bar("baz", [])
b.j.append(f)

Итак, вот мои вопросы:

  • Должны ли быть элементы объектов с индексируемыми индексами тоже? Почему?
  • Как лучше всего сгенерировать случайные данные с указанными выше свойствами для тестирования?
  • Как применить этот принцип в моем случае?

РЕДАКТИРОВАТЬ: это полная функция модульного тестирования:

def test_item_sort_foo(self):
        random_list = [Foo(str(randint(0, 1000)),
                            randint(0, 100),
                            randint(0, 100),
                            randint(0, 100),
                            randint(0, 100),
                            randint(0, 100))
                       for x in range(100)]
        sorted_list = item_sort_foos(random_list)
        assert eq(sorted_list, sorted(random_list,
                                      key=itemgetter(4, 7),
                                      reverse=True))

А вот код функции, которая реализует logi c:

def item_sort_foos(foos: List[Foo]) -> List[Foo]
    return sorted(foos,
                  key=attrgetter("e", "h"),
                  reverse=True)

EDIT2: Полная трассировка :

Error
Traceback (most recent call last):
  File "/opt/anaconda3/lib/python3.7/unittest/case.py", line 59, in testPartExecutor
    yield
  File "/opt/anaconda3/lib/python3.7/unittest/case.py", line 628, in run
    testMethod()
  File ".../src/project/tests/test_orderings.py", line 89, in test_item_sort_foos
    reverse=True))
TypeError: 'Foo' object is not subscriptable

Если вам нужна дополнительная информация, спрашивайте в комментариях.

1 Ответ

2 голосов
/ 20 июня 2020

random_list - это список Foo объектов. Когда вы используете ключ сортировки key=itemgetter(4, 7), вы пытаетесь проиндексировать сам объект foo. Это то же самое, что

foo = Foo(...)
sort_key = foo[4], foo[7]

Вероятно, вы захотите использовать key=attrgetter("e", "h") как в тестируемой функции item_sort_foos.

Но это тестовый код. item_sort_foos - это очень маленькая функция, и если все, что вы делаете, это прикладываете все усилия к своему модульному тесту, вы мало что тестируете. Вместо этого вы должны передать некоторые стандартные списки, о которых вы уже знаете, каким должен быть результат. Сравните их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...