On Apr 10, 2010, at 12:28 PM, DrLongGhost wrote:
> I have a couple questions regarding the best way to do date math in
> SQLAlchemy with Postgresql and how I can write fixture-based unit
> tests for this without requiring an actual database in my test.
>
> There's 2 specific types of dates which I need to be retrieving.
> Written in SQL these would be:
> 1) CURRENT_TIMESTAMP
> 2) CURRENT_TIMESTAMP + interval 'X months'
>
> I know that I can use sqlalchemy.func.current_timestamp() to retrieve
> the first, but this breaks when I try to unit test it and there is no
> database session present. For example, consider the following code:
>
> @property
> def is_active(self):
> return ((not self.date_closed) or
> (self.date_closed >= sa.func.current_timestamp()))
the above code may return a python boolean, or may return a SQL expression. I
don't see how the above code actually accomplishes something useful -
"func.current_timestamp()" doesn't execute against the database in any case,
unless the return value of is_active() is used in a flush(), in which case its
only evaluated on the database side, and you only see its result if you then
re-SELECT the value (which the Session would do for you, when the expired
attribute is accessed). Your unit tests couldn't possibly rely upon flush()
and then re-fetching expired attributes if they also require no database to be
present. If you're actually trying to simulate full roundtrips to your
database and back without a database in use, that doesn't make much sense.
I'd just run my unit tests against a Postgresql database intended for tests, if
indeed you're looking for functionality that occurs via round trips through
flush and back - thats how this is normally done. The level of mocking needed
to "simulate" that would render your unit tests as not really testing what
actually occurs in your application.
> One idea my boss suggested was to use the Fudge
> module in my tests to overload sqlalchemy.func.current_timestamp()
> with a function that uses python's datetime module to return the
> current timestamp. Thus, when run in production, my code will use the
> database to get the current time, but when run in a unit test, we
> avoid a broken test by instead using python's datetime to get the
> current timestamp.
You could just use a function "my_current_timestamp" which your test suite can
mock to return a datetime instead of a SQL expression. But I don't see this
approach working for anything beyond the most small and trivial cases.
> Does anyone have any experience or examples of this type of approach?
>
> Also, while this seems like it will work for getting the current time,
> how would I use the same approach to get "CURRENT_TIMESTAMP + interval
> 'X months'"? I don't see a pre-written
> "sqlalchemy.func.current_timestamp_plus_interval('X months')
to get a SQL expression like that, call func.current_timestamp() +
datetime.interval(days=60) (note that you can't specify intervals in terms of
months since a "month" is not a fixed unit of time). Defintiely use 0.6 for
such expressions as many improvements have been made to PG date arithmetic in
0.6. If you were using "my_current_timestamp" as an abstraction from
func.current_timestamp(), it would work both as a SQL expression and as an
all-Python expression. See examples/derived_attributes/ in the distro for a
little exploration on that concept.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.