返回介绍

A.8 第19章:处理 OSCON 日程表的脚本和测试

发布于 2024-02-05 21:59:46 字数 5834 浏览 0 评论 0 收藏 0

示例 A-12 是 schedule1.py 模块(示例 19-9)的测试脚本,使用 py.test 库和测试运行程序实现。

示例 A-12 test_schedule1.py

import shelve
import pytest

import schedule1 as schedule


@pytest.yield_fixture
def db():
  with shelve.open(schedule.DB_NAME) as the_db:
    if schedule.CONFERENCE not in the_db:
      schedule.load_db(the_db)
    yield the_db


def test_record_class():
  rec = schedule.Record(spam=99, eggs=12)
  assert rec.spam == 99
  assert rec.eggs == 12


def test_conference_record(db):
  assert schedule.CONFERENCE in db


def test_speaker_record(db):
  speaker = db['speaker.3471']
  assert speaker.name == 'Anna Martelli Ravenscroft'


def test_event_record(db):
  event = db['event.33950']
  assert event.name == 'There *Will* Be Bugs'


def test_event_venue(db):
  event = db['event.33950']
  assert event.venue_serial == 1449

19.1.5 节分四部分列出了 schedule2.py 脚本里的代码,示例 A-13 是完整的代码清单。

示例 A-13 schedule2.py

"""
schedule2.py: 遍历OSCON的日程数据

  >>> import shelve
  >>> db = shelve.open(DB_NAME)
  >>> if CONFERENCE not in db: load_db(db)

# BEGIN SCHEDULE2_DEMO

  >>> DbRecord.set_db(db)
  >>> event = DbRecord.fetch('event.33950')
  >>> event
  <Event 'There *Will* Be Bugs'>
  >>> event.venue
  <DbRecord serial='venue.1449'>
  >>> event.venue.name
  'Portland 251'
  >>> for spkr in event.speakers:
  ...   print('{0.serial}: {0.name}'.format(spkr))
  ...
  speaker.3471: Anna Martelli Ravenscroft
  speaker.5199: Alex Martelli

# END SCHEDULE2_DEMO

  >>> db.close()

"""

# BEGIN SCHEDULE2_RECORD
import warnings
import inspect

import osconfeed

DB_NAME = 'data/schedule2_db'
CONFERENCE = 'conference.115'


class Record:
  def __init__(self, **kwargs):
    self.__dict__.update(kwargs)

  def __eq__(self, other):
    if isinstance(other, Record):
      return self.__dict__ == other.__dict__
    else:
      return NotImplemented
# END SCHEDULE2_RECORD


# BEGIN SCHEDULE2_DBRECORD
class MissingDatabaseError(RuntimeError):
  """Raised when a database is required but was not set."""


class DbRecord(Record):

  __db = None

  @staticmethod
  def set_db(db):
    DbRecord.__db = db

  @staticmethod
  def get_db():
    return DbRecord.__db

  @classmethod
  def fetch(cls, ident):
    db = cls.get_db()
    try:
      return db[ident]
    except TypeError:
      if db is None:
        msg = "database not set; call '{}.set_db(my_db)'"
        raise MissingDatabaseError(msg.format(cls.__name__))
      else:
        raise

  def __repr__(self):
    if hasattr(self, 'serial'):
      cls_name = self.__class__.__name__
      return '<{} serial={!r}>'.format(cls_name, self.serial)
    else:
      return super().__repr__()
# END SCHEDULE2_DBRECORD


# BEGIN SCHEDULE2_EVENT
class Event(DbRecord):

  @property
  def venue(self):
    key = 'venue.{}'.format(self.venue_serial)
    return self.__class__.fetch(key)

  @property
  def speakers(self):
    if not hasattr(self, '_speaker_objs'):
      spkr_serials = self.__dict__['speakers']
      fetch = self.__class__.fetch
      self._speaker_objs = [fetch('speaker.{}'.format(key))
                  for key in spkr_serials]
    return self._speaker_objs

  def __repr__(self):
    if hasattr(self, 'name'):
      cls_name = self.__class__.__name__
      return '<{} {!r}>'.format(cls_name, self.name)
    else:
      return super().__repr__()
# END SCHEDULE2_EVENT


# BEGIN SCHEDULE2_LOAD
def load_db(db):
  raw_data = osconfeed.load()
  warnings.warn('loading ' + DB_NAME)
  for collection, rec_list in raw_data['Schedule'].items():
    record_type = collection[:-1]
    cls_name = record_type.capitalize()
    cls = globals().get(cls_name, DbRecord)
    if inspect.isclass(cls) and issubclass(cls, DbRecord):
      factory = cls
    else:
      factory = DbRecord
    for record in rec_list:
      key = '{}.{}'.format(record_type, record['serial'])
      record['serial'] = key
      db[key] = factory(**record)
# END SCHEDULE2_LOAD

示例 A-14 使用 py.test 测试示例 A-13。

示例 A-14 test_schedule2.py

import shelve
import pytest

import schedule2 as schedule


@pytest.yield_fixture
def db():
  with shelve.open(schedule.DB_NAME) as the_db:
    if schedule.CONFERENCE not in the_db:
      schedule.load_db(the_db)
    yield the_db


def test_record_attr_access():
  rec = schedule.Record(spam=99, eggs=12)
  assert rec.spam == 99
  assert rec.eggs == 12


def test_record_repr():
  rec = schedule.DbRecord(spam=99, eggs=12)
  assert 'DbRecord object at 0x' in repr(rec)
  rec2 = schedule.DbRecord(serial=13)
  assert repr(rec2) == "<DbRecord serial=13>"


def test_conference_record(db):
  assert schedule.CONFERENCE in db


def test_speaker_record(db):
  speaker = db['speaker.3471']
  assert speaker.name == 'Anna Martelli Ravenscroft'


def test_missing_db_exception():
  with pytest.raises(schedule.MissingDatabaseError):
    schedule.DbRecord.fetch('venue.1585')


def test_dbrecord(db):
  schedule.DbRecord.set_db(db)
  venue = schedule.DbRecord.fetch('venue.1585')
  assert venue.name == 'Exhibit Hall B'


def test_event_record(db):
  event = db['event.33950']
  assert repr(event) == "<Event 'There *Will* Be Bugs'>"


def test_event_venue(db):
  schedule.Event.set_db(db)
  event = db['event.33950']
  assert event.venue_serial == 1449
  assert event.venue == db['venue.1449']
  assert event.venue.name == 'Portland 251'


def test_event_speakers(db):
  schedule.Event.set_db(db)
  event = db['event.33950']
  assert len(event.speakers) == 2
  anna_and_alex = [db['speaker.3471'], db['speaker.5199']]
  assert event.speakers == anna_and_alex


def test_event_no_speakers(db):
  schedule.Event.set_db(db)
  event = db['event.36848']
  assert len(event.speakers) == 0

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文