Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test DateTimeProperty in App Engine NDB?

I'm trying to test a filter for the DateTimeProperty with App Engine's NDB but I have it set to auto_now?

Is there a way to get around this for unit testing?

Example:

class MyModel(ndb.Model)
  timestamp = ndb.DateTimeProperty(auto_now)
  name = ndb.StringProperty()


def testMyModelFilter(self):
  test1 = MyModel()
  test1.timestamp = datetime.datetime.now() - datetime.timedelta(hours=2)
  test1.put()
  test2 = MyModel()
  test2.timestamp = datetime.datetime.now() - datetime.timedelta(hours=1)
  test2.put()

  hour_ago = datetime.datetime.now() - datetime.timedelta(hours=1)
  fetched = MyModel.query().filter(MyModel.timestamp < hour_ago).fetch(
      None, keys_only=True)

Unfortunately, when I commit it to the datastore with test.put(), it uses the time when it was put().

like image 923
wag2639 Avatar asked Oct 23 '12 06:10

wag2639


People also ask

What is NDB in App Engine?

The Google Datastore NDB Client Library allows App Engine Python apps to connect to Datastore. The NDB client library builds on the older DB Datastore library adding the following data store features: The StructuredProperty class, which allows entities to have nested structure.

What is cloud NDB?

App Engine NDB enables Python 2 apps to store and query data in Datastore databases. Cloud NDB enables Python 2 and Python 3 apps to store and query data in the same databases, however the product that manages those databases has changed from Datastore to Firestore in Datastore mode (Datastore).


1 Answers

So one thing you can try (as alluded to by @mjibson) is overriding your model during the test. Since MyModel itself is an object, you can modify the _auto_now property of timestamp to False for your test. For example:

def testMyModelFilter(self):
  # Change the auto_now parameter to False
  MyModel.timestamp._auto_now = False

  # Test as usual...
  test1 = MyModel()
  test1.timestamp = datetime.datetime.now() - datetime.timedelta(hours=2)
  test1.put()
  test2 = MyModel()
  test2.timestamp = datetime.datetime.now() - datetime.timedelta(hours=1)
  test2.put()

  hour_ago = datetime.datetime.now() - datetime.timedelta(hours=1)
  fetched = MyModel.query().filter(MyModel.timestamp < hour_ago).fetch(
      None, keys_only=True)

I remember seeing this technique somewhere else, so I'll link if I can find it (if it works, of course :) ).

like image 79
RocketDonkey Avatar answered Sep 23 '22 09:09

RocketDonkey