Модульное тестирование — ошибка типа: объект ‘dict’ не вызывается

#unit-testing #flask-sqlalchemy

#модульное тестирование #flask-sqlalchemy

Вопрос:

Я новичок в базах данных в целом, поэтому извините, если этот вопрос слишком простой.

Я пытаюсь протестировать Playlist модель, которая имеет отношение к Track модели.

 class Track(db.Model):
    """
    Model for storing track information
    """
    id = db.Column(db.Integer, primary_key=True)
    artist = db.Column(db.String(140))
    title = db.Column(db.String(140))
    created = db.Column(db.DateTime, default=func.now())
    track_id = db.Column(db.String(140))
    tempo = db.Column(db.Float)      
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))

    def __init__(self, title, artist, uri):
        self.title = title
        self.artist = artist
        self.uri = uri

    @property
    def serialize(self):
       """Return object data in easily serializeable format"""
       return {
           'id' : self.id,
           'title': self.title,
           'artist': self.artist,
           'track_id': self.track_id,
            'tempo':self.tempo
       } 
  

и тогда у меня есть эта вторичная таблица:

 tracks = db.Table('tracks',
    db.Column('track_id', db.Integer, db.ForeignKey('track.id')),
    db.Column('playlist_id', db.Integer, db.ForeignKey('playlist.id')))
  

здесь Playlist модель:

 class Playlist(db.Model):
    """
    Model for storing playlist information belonging to a specific user
    """
    __tablename__ = 'playlist'

    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(50))
    created = db.Column(db.DateTime, default=func.now())    
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))

    tracks = db.relationship('Track', 
                            secondary=tracks,
                            backref=db.backref('playlists', 
                            lazy='dynamic'))

    def __init__(self, title):
        self.title = title

    @property
    def serialize(self):
       """Return object data in easily serializeable format"""
       return {
           'id' : self.id,
           'created' : self.created,
           'title': self.title,
           'tracks': [ item.serialize for item in self.tracks]
       }
  

и теперь я пытаюсь протестировать Playlist , вот так:

test_playlist_model.py

 import unittest
# third party libs
from sqlalchemy.exc import IntegrityError
# application modules
from project.api.models.base import db
from project.api.models.all import Playlist, tracks
from project.tests.base import BaseTestCase
from project.tests.utils import add_playlist


class TestPlaylistModel(BaseTestCase):

    def test_add_track(self):

        track = add_track(title='Karma Police',
                          artist='Radiohead',
                          uri='spofity:test')

        self.assertEqual(track.title, 'Karma Police')
        self.assertEqual(track.artist, 'Radiohead')
        self.assertEqual(track.uri, 'spofity:test')


    def test_add_playlist(self):

        track = add_track(title='Karma Police',
                          artist='Radiohead',
                          uri='spofity:test')

        playlist = add_playlist(title='Alternative')
        self.assertEqual(playlist.title, 'Alternative')
        self.assertTrue(playlist.id)
        self.assertEqual(playlist.tracks, track.serialize())

if __name__ == '__main__':
    unittest.main()
  

utils.py

 from project.api.models.base import db
from project.api.models.all import Playlist

def add_playlist(title):
    playlist = Playlist(
        title=title)
    db.session.add(playlist)
    db.session.commit()
    return playlist

def add_track(title, artist, uri):
    track = Track(
                title=title,
                artist=artist,
                uri=uri
            )
    db.session.add(track)
    db.session.commit()
    return track
  

но я получаю:

 ======================================================================
ERROR: test_add_playlist (test_playlist_model.TestPlaylistModel)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/src/app/project/tests/test_playlist_model.py", line 34, in test_add_playlist
    self.assertEqual(playlist.tracks, track.serialize())
TypeError: 'dict' object is not callable
  

чего мне не хватает?

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

1. На первый взгляд, в тесте похоже, что вы создали новый список воспроизведения только с заголовком и без отношения к каким-либо дорожкам. Поэтому, конечно, он не сможет подтвердить фактические значения трека (полиция кармы и т.д.) . Кроме того, функция add_playlist() В utils. py уже добавляет список воспроизведения в db.session и фиксирует, поэтому модульный тест, вероятно, не должен дублировать эти шаги?

2. Я видел, что вы назвали свою вторичную таблицу «дорожки». Это может привести к конфликту с автоматическим именем таблицы, присвоенным вашей модели дорожки. Я рекомендую вам переименовать эту таблицу в «playlist_tracks» вместо этого (<первый основной>_<вторые основные> — это своего рода соглашение для имен вторичных таблиц).

Ответ №1:

Ваш метод Track.serialize на самом деле является свойством, что означает, что он возвращает словарь при обращении к нему, как если бы это был атрибут.

Вам следует либо убрать скобки после track.serialize (и рассмотреть возможность переименования свойства в track.serialized , чтобы избежать путаницы), либо удалить @property декоратор.


 class Playlist(db.Model):
    ...

    def serialize(self):
        ...


class Track(db.Model):
    ...

    def serialize(self):
        ...
  

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

1. спасибо, но остается одна проблема: self.assertEqual(playlist.tracks, track.serialize()) AssertionError: [] != {'id': 1, 'title': 'Karma Police', 'artis[466 chars]None} . должен ли я отредактировать свой вопрос или создать другой, чтобы решить эту проблему?

2. Я предполагаю, что все еще есть ошибка, относящаяся к вторичной таблице, не рассмотренной в тесте.

3. Вы должны рассматривать этот результат как новую проблему, поэтому вы должны хотя бы попытаться решить ее, прежде чем отправлять новый вопрос.

4. Я думаю, что комментарий пользователя @peekay имеет отношение к делу, возможно, вам не хватает playlist.tracks.append(track) в вашем тесте.