Fixture + GoogleAppEngine
fixtureをGoogleAppEngineのDataStoreテストで使う。json編
参考 Using Fixture To Test A Google App Engine Site
DataSetsをjson化するのにfixture.dataset.converterでdataset_to_jsonが提供されていたりもする。ただdate_created(auto_now_add=True)のようなフィールドはDataSetsで前もって値を指定できないので、ここでjson化したデータを、実際(date_createdの付いた)のjsonのレスポンスと比較しても同じにはならない。
.zshrc
gaedir=/usr/local/google_appengine
if [ -d $gaedir ] ; then ;
export PATH=${PATH}:$gaedir
export PYTHONPATH=${PYTHONPATH}:${gaedir}:${gaedir}/lib/antlr3:\
${gaedir}/lib/cacerts:${gaedir}/lib/django:${gaedir}/lib/ipaddr:\
${gaedir}/lib/webob:${gaedir}/lib/yaml/lib
fi;
$ source ~/.zshrc $ pip install WebTest $ pip install nose $ pip install NoseGAE
app.yaml
application: sampleblog # _ はapplicationの識別子として使えないので注意 version: 1 runtime: python api_version: 1 handlers: - url: /.* script: blog.py
blog.py
#coding:utf-8
import logging
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from django.utils import simplejson
class Entry(db.Model):
title = db.StringProperty()
body = db.TextProperty()
date_created = db.DateTimeProperty(auto_now_add=True)
class Comment(db.Model):
entry = db.ReferenceProperty(Entry)
comment = db.TextProperty()
date_created = db.DateTimeProperty(auto_now_add=True)
class EntriesHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'application/json;charset=utf-8'
entries = []
for entry in Entry.all():
comments = []
for comment in Comment.all().filter("entry =", entry):
comment_dict = \
dict(comment=comment.comment,
date_created=comment.date_created.isoformat())
comments.append(comment_dict)
entry_dict = dict(title=entry.title,
body=entry.body,
date_created=entry.date_created.isoformat(),
comments=comments)
entries.append(entry_dict)
json = simplejson.dumps(entries, indent=True)
#logging.info(json)
self.response.out.write(json)
routing = [('/entries', EntriesHandler)]
application = webapp.WSGIApplication(
routing,
debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
tests/datasets.py (http://fixture.googlecode.com/hg/fixture/examples/google_appengine_example/tests/datasets.py)
from fixture import DataSet
class EntryData(DataSet):
class great_monday:
title = "Monday Was Great"
body = """\
Monday was the best day ever. I got up (a little late, but that's OK) then I ground some coffee.
Mmmm ... coffee! I love coffee. Do you know about
<a href="http://www.metropoliscoffee.com/">Metropolis</a> coffee? It's amazing. Delicious.
I drank a beautiful cup of french pressed
<a href="http://www.metropoliscoffee.com/shop/coffee/blends.php">Spice Island</a>, had a shave
and went to work. What a day!
"""
class CommentData(DataSet):
class monday_liked_it:
entry = EntryData.great_monday
comment = """\
I'm so glad you have a blog because I want to know what you are doing everyday. Heh, that sounds
creepy. What I mean is it's so COOL that you had a great Monday. I like Mondays too.
"""
class monday_sucked:
entry = EntryData.great_monday
comment = """\
Are you serious? Mannnnnn, Monday really sucked.
"""
load_data_locally.py
(http://fixture.googlecode.com/hg/fixture/examples/google_appengine_example/load_data_locally.py)一部修正
import sys
import os
import optparse
from fixture import GoogleDatastoreFixture
from fixture.style import NamedDataStyle
def main():
p = optparse.OptionParser(usage="%prog [options]")
default = "/tmp/dev_appserver.datastore"
p.add_option("--datastore_path", default=default, help=(
"Path to datastore file. This must match the value used for "
"the same option when running dev_appserver.py if you want to view the data. "
"Default: %s" % default))
default = "/tmp/dev_appserver.datastore.history"
p.add_option("--history_path", default=default, help=(
"Path to datastore history file. This doesn't need to match the one you use for "
"dev_appserver.py. Default: %s" % default))
default = "/usr/local/google_appengine"
p.add_option("--google_path", default=default, help=(
"Path to google module directory. Default: %s" % default))
(options, args) = p.parse_args()
if not os.path.exists(options.google_path):
p.error("Could not find google module path at %s. You'll need to specify the path" % options.google_path)
groot = options.google_path
sys.path.append(groot)
sys.path.append(os.path.join(groot, "lib/django"))
sys.path.append(os.path.join(groot, "lib/webob"))
sys.path.append(os.path.join(groot, "lib/yaml/lib"))
from google.appengine.tools import dev_appserver
import blog
from tests import datasets
config, explicit_matcher = dev_appserver.\
LoadAppConfig(os.path.dirname(__file__), {})
dev_appserver.SetupStubs(
config.application,
clear_datastore=False, # just removes the files when True
datastore_path=options.datastore_path,
history_path=options.history_path,
blobstore_path=None, # 追加 KeyError: 'blobstore_path' を避ける
login_url=None)
datafixture = GoogleDatastoreFixture(env={'EntryData': blog.Entry,
'CommentData': blog.Comment})
data = datafixture.data(datasets.CommentData, datasets.EntryData)
data.setup()
print "Data loaded into datastore %s" % \
(options.datastore_path or "[default]")
if __name__ == '__main__':
main()
tests/test_entries.py
#coding:utf-8
import unittest
from fixture import GoogleDatastoreFixture
from webtest import TestApp
import blog
from datasets import CommentData, EntryData
from django.utils import simplejson
datafixture = GoogleDatastoreFixture(env={'EntryData': blog.Entry,
'CommentData': blog.Comment})
class TestListEntries(unittest.TestCase):
def setUp(self):
self.app = TestApp(blog.application)
self.data = datafixture.data(CommentData, EntryData)
self.data.setup()
def tearDown(self):
self.data.teardown()
def test_entries(self):
response = self.app.get("/entries")
assert simplejson.dumps(EntryData.great_monday.title) in response
assert simplejson.dumps(EntryData.great_monday.body) in response
assert simplejson.dumps(CommentData.monday_liked_it.comment) \
in response
assert simplejson.dumps(CommentData.monday_sucked.comment) \
in response
Create custom datasets.
$ ./load_data_locally.py --datastore_path=./my.datastore
Run server with custom data.
$ dev_appserver.py . --datastore_path=./my.datastore
Run tests.
$ nosetests -v --with-gae test_entries (tests.test_entries.TestListEntries) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.296s OKPosted: May 26th, 2010 | Author: yamakk | Filed under: 技術 | Tags: database, fixture, gae, googleappengine, json, python | No Comments »
Leave a Reply