google-appengine  

[google-appengine] Re: Testing GAE application best practices

Andi Albrecht
Fri, 03 Jul 2009 05:34:56 -0700

On Fri, Jul 3, 2009 at 2:18 PM, Michelschr<michels...@gmail.com> wrote:
>
> Hi,
>
> Thanks for your comments!
>
> The in-browser tests are a very important complement to tests with the
> django client.
>
> I will suggest first Windmill instead of Selenium because at the end I
> suspect that we will arrive at a better integration with the Python
> world.
>
> I begin/prefer tests with the django client for several reasons:
> - I have access to everything in python, like for example the models,
> thus I can make a get, verify what append in the DB, clean some
> things, try again, change os.environ... test again... You see what I
> means?
> - I can have an idea of the coverage of my tests and thus I see where
> it could be important to make more efforts on tests first...

I'd prefer tests using the Django client too. At least as long I won't
have to test any kind of browser behavior, in that case windmill or
webdriver (has Python bindings too) seem to be suitable tools. Besides
the advantages you've mentioned, UnitTests/Django tests are easy to
run on the command line :)

>
> The big question is if it's possible to have coverage information when
> running for example Windmill tests?? (I suspect this is not
> straightforward, because you can get coverage information only in
> child threats...)
> Could anyone help-us to answer this question???

I don't know. I think it should be possible to run the SDK server in
some kind of "coverage mode", but I'm not sure about that.

>
> Michel
>
> On Jul 3, 10:32 am, Akume <akume...@gmail.com> wrote:
>> ok so i got selenium RC to work and it's probably a better solution
>> for functional testing of the browser than using the internal django
>> client.  why?  well because it runs in the browser via it's remote
>> control server so you can test content on all browsers.  and it can
>> be integrated for use with the plugin for firefox (though they need to
>> fix it for firefox 3.5).
>>
>> On Jul 3, 12:53 am, Akume <akume...@gmail.com> wrote:
>>
>> > i couldn't agree more.  google needs to make it easier for us to do
>> > proper testing on
>> > our app engine apps.  i found another solution to represent the client
>> > for functional
>> > testing.  using selenium RC.  however i'm running into an annoying
>> > timeout since i'm
>> > using gaeunit as the test runner.  if it's not one thing it's
>> > another.  still working
>> > on it.  i'll let you know how it goes.
>>
>> > -akume
>>
>> > On Jul 2, 2:15 pm, Michelschr <michels...@gmail.com> wrote:
>>
>> > > Hi,
>>
>> > > First of all, I think that Google should do the job of establishing
>> > > good practices and environments for testing GAE applications. That's
>> > > the only pragmatic solution! I don't means big integrated things but
>> > > small pieces that we can easily integrate in our environment of
>> > > choice. A lot of people like you or a newbie like me do their best to
>> > > build just basic things and I think that a large amount of
>> > > professionals will simply go for Django or Rails if they cannot find
>> > > the elementary tools.
>>
>> > > That said, I should also mention this interesting 
>> > > discussion:http://groups.google.com/group/google-appengine-python/browse_thread/...
>>
>> > > On my side, I have specific objectives and I still cannot said that my
>> > > solution is relevant, because it's specific and not yet sufficiently
>> > > tested. I will try to explain you everything, hoping I will forget
>> > > nothing...
>>
>> > > For me, it's a poor choice to send the files with the tests to GAE.
>> > > That's why I try to exclude Gaeunit or classic django directory
>> > > structures.
>>
>> > > On the other hand, my business is to develop applications and not
>> > > testing environments... and on the side of GAE/django integration, I
>> > > think that App Engine Patch do a pretty good job... It would be nice
>> > > if AEP can do for me (because Google don't do it) all the job of
>> > > integrating the different parts when I run tests...
>>
>> > > Well, to conclude on my specific motivations, I like the Netbeans6.7
>> > > IDE which offer a perfect integration of tests, with coverage
>> > > information etc... Thus, let's describe each step at a time...
>>
>> > > 1) The test runner should start GAE/django, is it possible to benefit
>> > > from AEP? Here is the patch that I did to the nb_test_runner.py
>> > > (Netbeans):
>> > > (...)# Driver for running tests from NetBeans
>> > > ##############################################################################
>>
>> > > def init_gae_django(): # ++++++++++++++++++++++++++++++++++++++++++++++
>> > > +++++++++
>> > >     os.environ['RUNNING_CONTEXT'] = 'test'
>> > >     os.environ['SERVER_NAME'] = 'testserver'
>> > >     os.environ['SERVER_PORT'] = '80'
>> > >     os.environ['SERVER_SOFTWARE'] = 'Devel'
>> > >     os.environ['USER_EMAIL'] = '' # set to '' for not logged in user
>>
>> > >     from common.appenginepatch import aecmd
>> > >     aecmd.PROJECT_DIR = os.getcwd() + "/togae"
>> > >     aecmd.setup_env() # +++++++++++++++++++++++++++++++++++++++++++++++
>> > > +++++++++
>>
>> > > if __name__ == '__main__':
>> > >     import unittest
>> > >     import doctest
>> > >     init_gae_django() # Here my patch and funct above
>> > > ######################
>> > > (...)
>> > > You should adapt this to your environment... I try to reuse the core
>> > > business of AEP to the max, because we need a lot of patches in django
>> > > to have the things working together... I am not sure that this is a
>> > > good solution, comments are welcome! (so AEP shoud simply be in your
>> > > path, Netbeans make the cwd as the root of the project and I put all
>> > > the code in the ./togae directory, what will be send to GAE... The
>> > > test are in a ./mytest directory, just beside... AEP will try to start
>> > > its sample app and make some warnings... but after I changed the
>> > > PROJECT_DIR it find the right things, like app.yaml and
>> > > settings.py...)
>>
>> > > 2) Settings.py should be adapted a bit to run in both environment,
>> > > here are my modifications for the settings.py of Rietveld/codereview:
>> > > # Copyright 2008 Google Inc.
>> > > (...)
>> > > """Minimal Django settings."""
>>
>> > > import os
>>
>> > > try: # Here my patch ###################### 5 lines
>> > >     if os.environ['RUNNING_CONTEXT'] == 'test':
>> > >         DATABASE_ENGINE = 'appengine'
>> > >         DATABASE_SUPPORTS_TRANSACTIONS = False
>> > >         DJANGO_STYLE_MODEL_KIND = False
>>
>> > > finally: APPEND_SLASH = False
>>
>> > > DEBUG = os.environ['SERVER_SOFTWARE'].startswith('Dev')
>> > > INSTALLED_APPS = (
>> > >     'codereview',
>> > > )
>> > > (...)
>> > > The try: is the only modification that I had to make to the Rietveld/
>> > > codereview code! The little problem is that the 2 environments require
>> > > different settings, that's why I use "os.environ['RUNNING_CONTEXT'] =
>> > > 'test'" in the test runner! In that case, I add the things that are
>> > > required by django/AEP like DATABASE_ENGINE = 'appengine' or
>> > > DJANGO_STYLE_MODEL_KIND = False... Don't ask me where I founded
>> > > that... I never founded any documentation about them...
>>
>> > > 3) I think, that's all... Netbeans find the tests, AEP find the
>> > > project... It seems to work... with tests as the one I published in
>> > > the previous mail...
>>
>> > > 4) Nice to have: coverage information!
>> > > With the previous settings, Netbeans6.7 will give you nice coverage
>> > > information, including on the patched/zipped django code an on your
>> > > tests... (What!? You run the patched/zipped files for tests!?!?)
>> > > I prefer to receive coverage information only about the real code that
>> > > form the application, in the /togae directory. Thus I made another
>> > > little patch to the Netbeans coverage_wrapper.py:
>> > > (...)
>> > > @atexit.register
>> > > def convert_to_nb_format():
>> > >     import marshal
>>
>> > >     output_file = open(output, 'wb')
>>
>> > >     c1_dict = marshal.load(open(input, 'rb'))
>>
>> > >     for k in c1_dict.keys():
>> > >         if k.startswith(os.getcwd()+"/togae/"):     # Here my patch
>> > > ###################### 1 line
>> > >             output_file.write(k.__str__())
>> > >             output_file.write('\n')
>> > >             x = c1_dict.get(k)
>> > >             output_file.write(x.keys().__str__())
>> > >             output_file.write('\n')
>>
>> > >     output_file.close()
>>
>> > > # Run coverage.py
>> > > execfile(coverage_py_file)
>> > > (...)
>>
>> > > That's what I have up to now... It is still not really tested and thus
>> > > every comments will be welcome!
>> > > Hope it helps,
>>
>> > > Michel
>>
>> > > On Jul 2, 8:50 pm, Akume <akume...@gmail.com> wrote:
>>
>> > > > i noticed that you're importing TestCase from django.test.
>> > > > what are you using to run your unit test? nosegae? i tried to
>> > > > implement your solution by changing the environment variable but
>> > > > still no success. i still get a status_code of 301.  i'm using
>> > > > gaeunit as my testrunner.  that may be the reason why.
>>
>> > > > On Jul 2, 8:10 am, Michelschr <michels...@gmail.com> wrote:
>>
>> > > > > Hello,
>>
>> > > > > You can simulate being logged or not by using os.environ
>> > > > > ['USER_EMAIL']. The following tests pass on Rietveld/codereview:
>>
>> > > > > from django.test.client import Client
>> > > > > from django.test import TestCase
>> > > > > import os
>>
>> > > > > class Test(TestCase):
>> > > > >   def setUp(self):
>> > > > >     self.client = Client()
>>
>> > > > >   def testStart(self):
>> > > > >     response = self.client.get('/')
>> > > > >     self.failUnlessEqual(response.status_code, 200)
>> > > > >     self.assertContains(response,'Code Review')
>>
>> > > > >     os.environ['USER_EMAIL'] = '' # simulate not logged in
>> > > > >     response = self.client.get('/mine')
>> > > > >     self.failUnlessEqual(response.status_code, 302)
>>
>> > > > >     os.environ['USER_EMAIL'] = 't...@example.com' # simulate logged 
>> > > > > in
>> > > > >     response = self.client.get('/mine')
>> > > > >     self.failUnlessEqual(response.status_code, 200)
>> > > > >     self.assertContains(response,'Issues Created by me')
>>
>> > > > >     os.environ['USER_EMAIL'] = '' # simulate not logged in
>> > > > >     response = self.client.get('/mine')
>> > > > >     self.failUnlessEqual(response.status_code, 302)
>>
>> > > > > Hope it helps,
>>
>> > > > > Michel
>>
>> > > > > On Jun 30, 1:33 am, Akume <akume...@gmail.com> wrote:
>>
>> > > > > > ok,
>> > > > > > what about this scenario.  some of my pages require a login prior 
>> > > > > > to
>> > > > > > seeing the content and i can't see to get this to work using the
>> > > > > > django
>> > > > > > client.  any suggestions?  this is what my test looks like so far.
>>
>> > > > > > import unittest
>> > > > > > from django.test.client import Client
>>
>> > > > > > class Test(unittest.TestCase):
>> > > > > >   def setUp(self):
>> > > > > >     self.client = Client()
>>
>> > > > > >   def testStart(self):
>> > > > > >     response = self.client.get('/app/layout')
>> > > > > >     self.failUnlessEqual(response.status_code, 301)
>>
>> > > > > > #attempting to log in here.
>> > > > > >     response = 
>> > > > > > self.client.get('/_ah/login?continue=http%3A//localhost
>> > > > > > %3A8081/app/layout')
>> > > > > >     self.failUnlessEqual(response.status_code, 302)
>>
>> > > > > >     # another attempt at logging in.
>> > > > > >     #response = self.client.get('/_ah/login?email=Aliquam.nec
>> > > > > > %40Vestibulumante.edu&action=Login&continue=http%3A%2F%2Flocalhost
>> > > > > > %3A8081%2Fapp%2Flayout')
>> > > > > >     response = self.client.login(path='/app/layout',
>>
>> ...
>>
>> read more »
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To post to this group, send email to google-appengine@googlegroups.com
To unsubscribe from this group, send email to 
google-appengine+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en
-~----------~----~----~----~------~----~------~--~---