0

My approach to this question might be completely wrong, so please don't hesitate to correct it. I also added ATDD in the question title, because I am trying to test the output of my web api which is bigger than just a unit test.

I am using:

  • Google App Engine 1.7.1
  • GAE High Replication Datastore
  • Python 2.7.3

I setup my tests using the boilerplate code:

self.testbed = testbed.Testbed()
self.testbed.activate()
self.policy = datastore_stub_util.PseudoRandomHRConsistencyPolicy(probability=0)
self.testbed.init_datastore_v3_stub()

Then I call a mock object setup to setup my entities and persist them to the testbed datastore. I use a counter to add 5 artists with artist_id 1 - 5:

def add_mock_artist_with(self, artist_id, link_id, name):
    new_artist = dto.Artist(key_name=str(artist_id),
        name=name,
        link_id= str(link_id))
    new_artist.put()

My test is that my web api returns:

{
    "artists": [
            {
            "artist": {
                "name": "Artist 1",
                "links": {
                    "self": {
                        "href": "https://my_server.com/artist/1/"
                    }
                }
            }
        },
.
.
.      
            {
            "artist": {
                "name": "Artist 5",
                "links": {
                    "self": {
                        "href": "https://my_server.com/artist/5/"
                    }
                }
            }
        }
    ],
    "links": {
        "self": {
            "href": "https://my_server.com/artists/"
        }
    }
}

Initially I thought that if I were to startup a new test bed every time I run the tests, I could count on my artists being entered sequentially into the data store and therefore would get ids 1 - 5. My tests passed initially, but over time started to fail because of ids not matching (I would get a link like: "href": "https://my_server.com/artist/78/"). I felt a little guilty relying on ids being generated sequentially, so I resolved to fix it. I stumbled upon the concept of a key being either a name or a generated id. I updated my templates for the returned JSON to use:

artist.key().id_or_name()

In the case of a mock object, I supplied the key name on construction with:

key_name=str(artist_id) 

For non-mock construction, I did not include that line of code and let GAE assign the id.

Since my template used key().id_or_name() to output the property, all went well and the tests passed.

However, now when I test the return of an individual artist which would be available by following http://my_server.com/artist/5/, my test fails. To grab the artist out of the datastore, I use the following code:

def retrieve_artist_by(id):
    artist = dto.Artist.get_by_id()

In production, this will work fine because it will all be id based. However, in my test, it is not finding anything because I have used the key_name=str(artist_id) in my mock construction, and the name is not the same as the id.

I was hoping for something similar to:

artist = dto.Artist.get_by_id_or_name()

Any ideas?

Erds
  • 513
  • 5
  • 16

2 Answers2

0

Perhaps not the answer you are looking for, but it's possible to find out if you are running on the production or deployment servers and execute a different code path.

In Python, how can I test if I'm in Google App Engine SDK? http://code.google.com/appengine/docs/python/runtime.html#The%5FEnvironment

os.environ['SERVER_SOFTWARE'].startswith('Development')
Community
  • 1
  • 1
Paul Collingwood
  • 9,053
  • 3
  • 23
  • 36
0

Here is what I am using right now. I don't like it, but it should be performant in prod as I will be using generated ids. In test, if it doesn't find it by id, it will attempt to look up by name.

def retrieve_artist_by(id):
    artist = dto.Artist.get_by_id(id)

    if artist is None:
        artist = dto.Artist.get_by_key_name(str(id))


    return artist
Erds
  • 513
  • 5
  • 16