factory_boy README 和訳
# 必要に迫られたので訳したよ。更新が久しぶりすぎて、はてダの使いかた忘れてる…
factory_boy は thoughtbot の factory_girl をベースにした fixture replacement です。 factory_girl のように、わかりやすい定義構文、 複数のビルドストラテジ(インスタンスの保存、非保存、属性辞書、スタブオブジェクト)の対応、 ファクトリの継承を含め、同一クラスに対する複数ファクトリの対応などがあります。 Django に対応していますが、他の ORM の対応も簡単に追加することができます。
クレジット
この README はできるだけ factory_girl の README に対応させています。 文章や例は比較しやすいように同じ内容にしています。 factory_girl を使っている Ruby ユーザーなら、すぐに Python の factory_boy を使えるでしょう。
factory_boy は Mark Sandstrom によって書かれました。
Joe Ferris と factory_girl を作ってくれた thoughtbot に感謝します。
ダウンロード
Github: http://github.com/dnerdy/factory_boy/tree/master
easy_install:
easy_install factory_boy
ソース:
# ソースをダウンロードして実行 python setup.py install
ファクトリの定義
ファクトリは、オブジェクトをインスタンス化するのに使う属性のまとまりを宣言したものです。 ファクトリ名はデフォルトではオブジェクトのクラスを推測するのに使われますが、 明示的に指定することも可能です:
import factory from models import User # これは User クラスを推測します class UserFactory(factory.Factory): first_name = 'John' last_name = 'Doe' admin = False # これは(Admin クラスを推測しますが) User クラスを使います class AdminFactory(factory.Factory): FACTORY_FOR = User first_name = 'Admin' last_name = 'User' admin = True
ファクトリの使用
factory_boy はいくつかの異なったビルドストラテジに対応しています: build, create, attributes そして stub です:
# save されていない User インスタンスを返します user = UserFactory.build() # save された User インスタンスを返します user = UserFactory.create() # User インスンタンスの生成に使える属性の辞書を返します attributes = UserFactory.attributes() # 全ての属性がスタブ化されたオブジェクトを返します(?) stub = UserFactory.stub()
ファクトリクラスをデフォルトのビルドストラテジのショートカットとして使うことができます:
# UserFactory.create() と同じ
user = UserFactory()
デフォルトのストラテジを上書きすることも可能です:
UserFactory.default_strategy = factory.BUILD_STRATEGY user = UserFactory()
全ファクトリに対するデフォルトストラテジを上書きすることもできます:
# デフォルトのビルドストラテジが定義されていない全ファクトリのデフォルトストラテジを設定
factory.Factory.default_strategy = factory.BUILD_STRATEGY
どのストラテジが使われていても、 キーワード引数を渡すことで既に定義済の属性を上書きすることが可能です:
# User インスタンスを生成して first_name を上書きする user = UserFactory.build(first_name='Joe') user.first_name # => 'Joe'
遅延評価属性
ほとんどのファクトリ属性は、ファクトリを定義する際に評価される 静的な値を使ってファクトリに追加することができますが、 いくつかの属性(関連や動的に生成されるべき属性など)は インスタンスが生成される度に値が設定される必要があります。 そのような "lazy" な属性は、次のように追加することができます:
class UserFactory(factory.Factory): first_name = 'Joe' last_name = 'Blow' email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower()) UserFactory().email # => 'joe.blow@example.com'
LazyAttribute に渡された関数には、その宣言までにファクトリに定義された属性が与えられます。
ラムダ式では具合が悪い場合は lazy_attribute デコレータで関数を装飾することができます:
# Stub ファクトリは特定のクラスとのひもづきを持たない class SumFactory(factory.StubFactory): lhs = 1 rhs = 1 @lazy_attribute def sum(a): result = a.lhs + a.rhs # などのなんらかの計算 return result
関連
LazyAttribute を使うことで、ひもづいたオブジェクトインスタンスを生成することもできます:
from models import Post class PostFactory(factory.Factory): author = factory.LazyAttribute(lambda a: UserFactory())
ひもづいたオブジェクトでは、常にデフォルトストラテジが使われます:
# User と Post をビルドして保存する post = PostFactory() post.id == None # => False post.author.id == None # => False # User をビルドして保存してから Post をビルドするが保存はしない post = PostFactory.build() post.id == None # => True post.author.id == None # => False
継承
継承を使えば、何度も共通の属性の宣言をしなくても、簡単に同じクラスのファクトリを複数作ることができます:
class PostFactory(factory.Factory): title = 'A title' class ApprovedPost(PostFactory): approved = True approver = factory.LazyAttribute(lambda a: UserFactory())
シーケンス
特定のフォーマット(Eメールアドレスなど)のユニークな値はシーケンスを使って生成できます。 シーケンスは Sequence で定義するか sequence デコレータを使います:
class UserFactory(factory.Factory): email = factory.Sequence(lambda n: 'person{0}@example.com'.format(n)) UserFactory().email # => 'person0@example.com' UserFactory().email # => 'person1@example.com'
シーケンスは遅延属性と組み合わせて使うこともできます:
class UserFactory(factory.Factory): name = 'Mark' email = factory.LazyAttributeSequence(lambda a, n: '{0}+{1}@example.com'.format(a.name, n).lower()) UserFactory().email # => mark+0@example.com