くろねこ日記

ソフトウェアに関する技術メモが多いです.

テストデータ作成に便利なFactoryBoyをつかってみた

はじめに

FactoryBoyというテストデータ作成ライブラリがあります.

もともとはRuby on RailsプラグインであるFactory Girlからインスパイア(パク(ry)されてつくられたようです. http://factoryboy.readthedocs.org/en/latest/

インストールは簡単で

pip install factory_boy

だけです.

僕は,普段はadminページを開いて手動でデータを追加してたりと面倒なことをしていたのですが,FactoryBoyを使うことで,そのような手間を大幅に削減できました.

FactoryBoyをつかってみる

FactoryBoyをつかうために最低限のDjango環境を用意してあげましょう.今回も使用例を簡単なブログにしておきます.

djangoプロジェクトの立ち上げ

factoryboy_sampleというプロジェクトをつくって移動しましょう.

django-admin startproject factoryboy_sample
cd factoryboy_sample

アプリを作りましょう.ここではmainとしておきます.

python manage.py startapp main

今回使うmainというappをfactoryboy_sample/settings.pyのINSTALLED_APPSの中に追記書きましょう

・・・
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'main',
)
・・・

modelの設定

次のようなモデル設計とします.(このあたりは前回の記事を流用…)

  • BlogModel
    • 日付(date: DateTimeField)
    • タイトル(title: CharField)
    • 内容(message: TextField)

このモデルを実際に反映していきます. main/models.pyを開き,次のように編集してください.

from django.db import models


class BlogModel(models.Model):
    date = models.DateTimeField()
    title = models.CharField(max_length=256)
    message = models.TextField()

これでmodelの環境は整いました. Datetimeの初期値は無くても良いですが,一応default値として現在時刻を入れておきました

FactoryBoy

今回の本題を書いていきます.

main/factory.pyというファイルをつくりましょう.

touch main/factory.py

このファイルの中に次のようなコードを書いてください.

from factory import DjangoModelFactory, lazy_attribute
from main.models import BlogModel
from factory.fuzzy import FuzzyText
import random
import datetime


class BlogModelFactory(DjangoModelFactory):
    class Meta:
        model = BlogModel
    date = datetime.datetime.now()
    title = lazy_attribute(lambda o: random.choice(['ham', 'spam', 'egg']))
    message = FuzzyText()

解説するとModelFormのような使い方で定義ができます. class Metaの中にあるmodel変数に使うModelを指定します. あとはModelに指定されている,各値をどのような内容にするか設定するというものです.

異なるテストデータを入力するための便利な機能として,FuzzyとLazyがあります.Fuzzyは勝手にテキストを生成してくれるなど,自動でテストデータを生成するときに便利です. lazyはrandomで出した結果を反映させたいときに使います.詳しいことはわからないのですが,lazy_attributeを使わずにrandom.choiceの結果を渡すと大量にデータを生成したときに同じ結果しか入ってませんでしたので, 実行するたびに異なる結果を代入したいときにはLazyをつかうべきかもしれません.

確かめる

今回は確かめる手段としてdjangoのshellをつかってみます.

まずはその前にmakemigrationsとmigrateを実行しましょう.

python manage.py makemigrations
python manage.py migrate
python manage.py shell

次のような内容を打つことでデータを自動で1件生成してくれるはずです.

from main.factoryboy import BlogModelFactory
BlogModelFactory()

次のようにcreate_batchメソッドに件数を打つとその件数分入ります(ここでは10件).

from main.factoryboy import BlogModelFactory
BlogModelFactory.create_batch(10)

では本当に中身があるか見てみましょう.おそらく1件+10件表示されるはずです.

from main.models import BlogModel
for x in BlogModel.objects.all():
    print('date={0}, title={1}, message={2}'.format(x.date, x.title, x.message))

titleについては予め決めた範囲から値をランダムに取り出してますし,messageについては出鱈目な文字列が入っていると思います.

date=2015-01-24 18:00:46.741512+00:00, title=egg, message=gTwpefYyxfIJ
date=2015-01-24 18:00:46.741512+00:00, title=spam, message=UotYBXwLooXL
date=2015-01-24 18:00:46.741512+00:00, title=ham, message=vHjJYITVvFBS
date=2015-01-24 18:00:46.741512+00:00, title=egg, message=oMOOtsFnrGBL
date=2015-01-24 18:00:46.741512+00:00, title=egg, message=QhlKBXLsraQL
date=2015-01-24 18:00:46.741512+00:00, title=egg, message=khQxmqzpoeOC
date=2015-01-24 18:00:46.741512+00:00, title=egg, message=lFRsLoVFsHoO
date=2015-01-24 18:00:46.741512+00:00, title=spam, message=lheWOYPpRiJR
date=2015-01-24 18:00:46.741512+00:00, title=egg, message=kCRhCPSdmgbE
date=2015-01-24 18:00:46.741512+00:00, title=egg, message=hElOIWYlJAqz
date=2015-01-24 18:00:46.741512+00:00, title=ham, message=GrEFddntNXyQ

まとめ

Factoryboyでテストデータを自動生成してみた.