A TG Developer Gets Ploned

29 messages Options
Embed this post
Permalink
1 2
percious () Re: A TG Developer Gets Ploned
Reply Threaded More More options
Print post
Permalink
In reply to this post by kteague
Part IIa.

Ok, so i got fed up with ArgoUML, because I would create objects (with
our local Plone expert sitting right there) and when I went to update
my "Product" the changes I made would not appear, or even worse,
objects I had created that worked before would disappear!

Anyway, my next thing to try was the "buildout" version of ZP so I
followed the instructions on: http://plone.org/documentation/tutorial/buildout/tutorial-all-pages

Installation when smoothly, but then I tried to add a plone site and I
got the following message:
Site Error

An error was encountered while publishing this resource.

Error Type: ConnectionStateError
Error Value: Shouldn't load state for 0x0aac when the connection is
closed

Troubleshooting Suggestions

    * The URL may be incorrect.
    * The parameters passed to this resource may be incorrect.
    * A resource that this resource relies on may be encountering an
error.

For more detailed information about the error, please refer to the
error log.

If the error persists please contact the site maintainer. Thank you
for your patience.

And here is the dump from instance.log:
2007-09-24T11:51:07 ERROR Zope.SiteErrorLog
http://localhost:8080/manage_addProduct/CMFPlone/addPloneSiteForm
Traceback (innermost last):
  Module ZPublisher.Publish, line 119, in publish
  Module ZPublisher.mapply, line 88, in mapply
  Module ZPublisher.Publish, line 42, in call_object
  Module Products.CMFPlone.factory, line 63, in addPloneSiteForm
  Module Shared.DC.Scripts.Bindings, line 313, in __call__
  Module Shared.DC.Scripts.Bindings, line 350, in _bindAndExec
  Module Products.PageTemplates.PageTemplateFile, line 129, in _exec
  Module Products.PageTemplates.PageTemplate, line 89, in pt_render
  Module zope.pagetemplate.pagetemplate, line 117, in pt_render
  Module zope.tal.talinterpreter, line 271, in __call__
  Module zope.tal.talinterpreter, line 346, in interpret
  Module zope.tal.talinterpreter, line 855, in do_condition
  Module zope.tal.talinterpreter, line 346, in interpret
  Module zope.tal.talinterpreter, line 536, in do_optTag_tal
  Module zope.tal.talinterpreter, line 521, in do_optTag
  Module zope.tal.talinterpreter, line 516, in no_tag
  Module zope.tal.talinterpreter, line 346, in interpret
  Module zope.tal.talinterpreter, line 824, in do_loop_tal
  Module zope.tal.talinterpreter, line 346, in interpret
  Module zope.tal.talinterpreter, line 631, in do_insertText_tal
  Module zope.tal.talinterpreter, line 841, in translate
  Module Products.PageTemplates.Expressions, line 208, in translate
  Module Products.Five.i18n, line 66, in translate
  Module Products.PlacelessTranslationService.utility, line 24, in
translate
  Module ZODB.Connection, line 758, in setstate
ConnectionStateError: Shouldn't load state for 0x0aac when the
connection is closed

Now, I have no idea what went wrong, but perhaps someone can point me
in the right direction.

In the mean time, I am going back to the unified installer *cringe* so
I can make some progress.

cheers,
-chris



On Sep 23, 2:19 pm, Kevin Teague <[hidden email]> wrote:

> percious wrote:
>
> > The response from the community, as well as the knowledgeable staff
> > where I work was to install Z/P with it's own Python environment,
> > which as I explained earlier, does not work for me.
>
> > It seems like Zope and Plone are not willing to play in the sandbox
> > with others.  Twisted is a MAJOR player in the python world, and to
> > not be able to have Plone and Twisted on my machine in the same Python
> > instance is sort of a drag.  Great, now I get two copies of
> > everything, my Zope sandbox, and my Twisted sandbox.  Imagine if every
> > package was like this?
>
> In the playground of Python there are many sandboxes, and each sandbox has a
> different type of sand in it. Some sandboxes have have coarse sand with lots
> of small pebbles in them, other sandboxes have smooth white sand. Some kids
> like to hunker down in a single sandbox all day, digging all the way to the
> bottom of the box. Other kids run from one sandbox to the next, as they are
> fond of the variety. But when I mix my sandboxes, I always feel like that
> kid
> who is filling up his bucket with sand from one sandbox and dumping it into
> other
> sandboxes. Sure it seems like a neat idea at the time, to try and get all of
> sand in all of the sandboxes of an equal mix of all types of sand, but after
> a while you realize it's too much work and you liked it better the old way
> when each of the sandboxes had their own distinctive character. Only now,
> reverting the sandboxes to their original pristine states is only possible
> by dumping out the sandboxes and making a trip to the gravel pit for fresh
> sand.
>
> Or speaking somewhat less metaphorically ...
>
> I understand that a lot of Python developers who like to manage only a
> single
> Python installation. It's simple and clean. But Twisted, Zope/Plone, and
>  TurboGears are not just Python packages, they are all integrated libraries
> (or are applications that contain integrated libraries).
>
> By integrated libaries I mean that specific versions of all of those
> libraries
> are tested to work together (usually by running a suite of integration
> tests).
> They are tested using specific versions of each library. If Twisted is
> tested
> with library X version 1, and library Y version 2, while Zope is tested
> with library X version 2 and library Y version 1. Trying to wedge all of
> that
> into the same sandbox can have unexpected consequences.
>
> I've learned the hard and painful way of trying to toss too
> many disparate concerns into a single sandbox. This can be especially
> problematic when you later on need to hand off maintenance of one section of
> your sandbox to another developer.
>
> Each application should be given it's own space - give each sandbox it's
> own space. The fewer files one application shares with another another
> application, the better, IMO.
>
> --
> View this message in context:http://www.nabble.com/A-TG-Developer-Gets-Ploned-tf4477049s6742.html#...
> Sent from the General Questions mailing list archive at Nabble.com.
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2005.http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
> _______________________________________________
> Plone-Users mailing list
> [hidden email]://lists.sourceforge.net/lists/listinfo/plone-users


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Plone-Users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/plone-users
Martin Aspeli-2 () Re: A TG Developer Gets Ploned
Reply Threaded More More options
Print post
Permalink
percious wrote:

> Part IIa.
>
> Ok, so i got fed up with ArgoUML, because I would create objects (with
> our local Plone expert sitting right there) and when I went to update
> my "Product" the changes I made would not appear, or even worse,
> objects I had created that worked before would disappear!
>
> Anyway, my next thing to try was the "buildout" version of ZP so I
> followed the instructions on: http://plone.org/documentation/tutorial/buildout/tutorial-all-pages
>
> Installation when smoothly, but then I tried to add a plone site and I
> got the following message:
> Site Error
>
> An error was encountered while publishing this resource.
>
> Error Type: ConnectionStateError
> Error Value: Shouldn't load state for 0x0aac when the connection is
> closed
>
> Troubleshooting Suggestions
>
>     * The URL may be incorrect.
>     * The parameters passed to this resource may be incorrect.
>     * A resource that this resource relies on may be encountering an
> error.
>
> For more detailed information about the error, please refer to the
> error log.
>
> If the error persists please contact the site maintainer. Thank you
> for your patience.
>
> And here is the dump from instance.log:
> 2007-09-24T11:51:07 ERROR Zope.SiteErrorLog
> http://localhost:8080/manage_addProduct/CMFPlone/addPloneSiteForm
> Traceback (innermost last):
>   Module ZPublisher.Publish, line 119, in publish
>   Module ZPublisher.mapply, line 88, in mapply
>   Module ZPublisher.Publish, line 42, in call_object
>   Module Products.CMFPlone.factory, line 63, in addPloneSiteForm
>   Module Shared.DC.Scripts.Bindings, line 313, in __call__
>   Module Shared.DC.Scripts.Bindings, line 350, in _bindAndExec
>   Module Products.PageTemplates.PageTemplateFile, line 129, in _exec
>   Module Products.PageTemplates.PageTemplate, line 89, in pt_render
>   Module zope.pagetemplate.pagetemplate, line 117, in pt_render
>   Module zope.tal.talinterpreter, line 271, in __call__
>   Module zope.tal.talinterpreter, line 346, in interpret
>   Module zope.tal.talinterpreter, line 855, in do_condition
>   Module zope.tal.talinterpreter, line 346, in interpret
>   Module zope.tal.talinterpreter, line 536, in do_optTag_tal
>   Module zope.tal.talinterpreter, line 521, in do_optTag
>   Module zope.tal.talinterpreter, line 516, in no_tag
>   Module zope.tal.talinterpreter, line 346, in interpret
>   Module zope.tal.talinterpreter, line 824, in do_loop_tal
>   Module zope.tal.talinterpreter, line 346, in interpret
>   Module zope.tal.talinterpreter, line 631, in do_insertText_tal
>   Module zope.tal.talinterpreter, line 841, in translate
>   Module Products.PageTemplates.Expressions, line 208, in translate
>   Module Products.Five.i18n, line 66, in translate
>   Module Products.PlacelessTranslationService.utility, line 24, in
> translate
>   Module ZODB.Connection, line 758, in setstate
> ConnectionStateError: Shouldn't load state for 0x0aac when the
> connection is closed
>
> Now, I have no idea what went wrong, but perhaps someone can point me
> in the right direction.

I have actually seen this error once or twice before, but never been
able to fully reproduce it. Sometimes goes wrong for sure (i.e. it's a
bug). However, the workaround is simple: restart Zope, and it should
work again.

Martin

--
Acquisition is a jealous mistress


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Plone-Users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/plone-users
percious () Re: A TG Developer Gets Ploned
Reply Threaded More More options
Print post
Permalink
Part IV

Creating a Product with Plone.

ArgoUML is a piece of, well, you know.  So I upgraded to Poseidon and
whatever my company is paying for this tool, it's worth it.  I find it
entertaining that Poseidon makes you buy a license to do cut-and-
paste, since that is exactly the gripe I have with ArgoUML.  Also
frustrating was the inability to test out whether the XMI files
produced by Poseidon actually work with Archgenxml.  They do, but I
needed the license to find out.  Also, ArgoUML gave me drop-downs for
the tagged values based on a "starter_project" which someone gave me
that had all of the plone tagged values.  I loaded the same file into
Poseidon and it did not have the same effect.  I hated that ArgoUML
did not do completion on these fields, and did not even let you enter
them in by the keyboard.  I pretty much refused to use it after
dealing with those issues.  I'd rather just type them in myself if I
have to.

I really hate UML tools, but I am being forced to use them... oh
well.  OTOH, archgenxml does an excellent job of merging in my changes
from the UML tool.  Nice job there.  It doesn't kill any of my code.
The only problem that I see is that if I remove a class, it still
lingers around.  Also, I have had to restart ZP on every iteration.
It would be nice if ZP autoreloaded.  I think it used to do this on
previous versions, but this is broken now.  It seems like Plone loads
content into the server when I go to the page which makes page loads
very long the first time I access my new stuff.  At least my users
should not feel this pain.

Once the process is learned for loading your content into the site it
is rather simple:
1) Modify UML diagram, export XMI
2) Arch-gen XML your XMI
3) update through site-setup on the webpage
4) Restart ZP

On the contrary, TG has the autoloader working, although I have had
problems with it and have had to shut it off.  It monitored the
directories where my code was held, and reloaded whenever there was a
save, which sometimes caused it to crash if there was a syntax error.
I really liked this feature, and when I had a problem with my
controller (read: Base Content) definition, it threw useful error
messages to the screen.  It seems like sometimes I will make a change
to the UML diagram that ZP doesn't like, it just doesn't load and I am
sent pondering why.  Then I can check the logs, and sometimes I get my
answer, sometimes I don't.  It would be nice if the application
updating log displayed whatever error message is available for that
update right to the web instead of having to check the external log
file.

So now I am loading in some content and I am a happy camper, right?

Plone really did a service to the developers with the
ATVocabularyManager product.  Once it is installed and the correct
hooks are in your code it is really easy to maintain.  So easy that
the Users could do it, if they could only get access...  I really like
this, and it would take a week or so to do this in TG.  Plus all the
AJAX stuff is really jazzy, and I hate writing JS, so its nice to have
that done for you.  Also, the integrated security is awesome and I am
sure I will get it fixed.  The board is pretty active here and I
appreciate all the feedback.

The one thing I would like to see is a de-coupling of the code
required in your archetypes/basecontent from the vocabulary.  It seems
kind of odd to me that you have to create a vocabulary from a web
interface, then write code that uses that interface.  This could make
testing sort of tricky, but I will get into that on the next part in
this mini-series.  Maybe if it was all defined through the web it
would be getting a bit too Django-y?

One other style point that I am trying to get a grip on.  The
Archetype defines the widget used for display.  Does anyone else see
this as a clear break in the VMC paradigm?  Seems like BaseContent
would be a better place to define associations between your models and
your display.  There are even hooks in the Archetype which define
which vocabulary to display for a given field.  Seems weird to me.

Regards.
chris


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Plone-Users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/plone-users
percious () Re: A TG Developer Gets Ploned
Reply Threaded More More options
Print post
Permalink
Part Va - UnitTesting

Ok, so I am all hunky-dory with my application working, the nuances of
Poseidon figured out.  I sort of have a handle on how to work in the
plone environment, so now it is time to do some unit testing.  So far
I am only through the unit-testing for my Content creation.  I plan to
do more functional webbrowser testing for the next part.

Mostly I followed the instructions here:
http://plone.org/documentation/tutorial/testing
Somehow the page changed while I was actually working on it, and now I
have to learn a bunch more about "contexts" but for now I am just
going to test all of my code the old fashoned "unit test" way.
Anyway, here is a copy of my test code.  See if you can identify some
new features which I would find horribly valuable if they had been
done for me:

"""ftir is the name of my product
it has the very simple archetecture of:
Experiments->InfaredExperients->(Colaborator|DataFile)*
->indicates encapuslation

"""

from base import ftirTestCase
from Products.ATVocabularyManager.config import TOOL_NAME as
ATVOCABULARYTOOL

from Products.ftir.Contents.Colaborator import Colaborator
from Products.CMFCore.utils import getToolByName
import types

class TestProductInstall(ftirTestCase):
    """Base class for integration tests for the 'ftir' product.
    """

    def afterSetUp(self):
        self.types = ('InfaredExperiment', 'Colaborator',
'Experiments', 'DataFile')
        self.vocabularies = ('Instruments',        'Organizations',
'Customers',
                             'SampleDescriptions', 'StorageLocations',
'Comments',  'Companies')
    def testTypesInstalled(self):
        for t in self.types:
            self.failUnless(t in
self.portal.portal_types.listContentTypes(),
                            '%s content type not installed' % t)

    def testVocabulariesInstalled(self):
 
portal=getToolByName(self.portal,'portal_url').getPortalObject()
        atvm = getToolByName(portal, ATVOCABULARYTOOL)
        for v in self.vocabularies:
            assert v in atvm, "missing vocabulary: %s"%v

class TestContent(ftirTestCase):
    contentRelationships = ()
    testForExistance = ()
    contentIDFormat='%s-item'
    contentToLookFor = ()

    def _createContent(self, folder, contentTypes):
        folders = []
        for item in contentTypes:
            if isinstance(item, types.StringTypes):
                id = folder.invokeFactory(item, self.contentIDFormat
%item)
                folder = getattr(folder, id)
                folders.append(folder)
                continue
            folders.extend(self._createContent(folder, item))
        return folders

    def afterSetUp(self):
        folders = self._createContent(self.folder,
self.contentRelationships)

        #make the folders a searchable dictionary
        self.folders = {}
        for x in folders:
            self.folders[x.__class__.__name__] = x

    def testCreate(self):
        #see that the items we expect to see in the database are there
        for folder, content in self.contentToLookFor:
            if folder is None:
                folder = self.folder
            else:
                folder = self.folders[folder]
            results = folder.portal_catalog(id=self.contentIDFormat
%content)
            assert len(results) == 1, results

class TestColaborator(TestContent):
    contentRelationships = ('Experiments', 'InfaredExperiment',
'Colaborator')
    contentToLookFor = (('InfaredExperiment', 'Colaborator',),)

class TestDataFile(TestContent):
    contentRelationships = ('Experiments', 'InfaredExperiment',
'DataFile')
    contentToLookFor = (('InfaredExperiment', 'DataFile',),)

class TestInfaredExperiement(TestContent):
    contentRelationships = ('Experiments', 'InfaredExperiment')
    contentToLookFor = (('Experiments', 'InfaredExperiment'),)

class TestExperiments(TestContent):
    contentRelationships = ('Experiments',)
    contentToLookFor = ((None, 'Experiments'),)


class TestIntegration(TestContent):
    contentRelationships = ('Experiments', 'InfaredExperiment',
('DataFile', 'Colaborator'))
    contentToLookFor = (('Experiments', 'InfaredExperiment',),
                        ('InfaredExperiment', 'Colaborator',),
                        ('InfaredExperiment', 'DataFile',))

def test_suite():
    from unittest import TestSuite, makeSuite
    from inspect import isclass
    import sys

    suite = TestSuite()

    #retrieve all test classes from this file
    module = sys.modules[__name__]
    for item in dir(module):
        klass = getattr(module, item)
        if item[:4].lower() == 'test' and isclass(klass):
            suite.addTest(makeSuite(klass))

    return suite

Answers:
1)TestContent: Goes through a tree of content, creates what you
desire, and checks the nodes you desire.  Once caveat, you can only
create 1 of each ContentType.
2)Auto-loading "test" classes.  No more having to do "addSuite" a
bajillion times.
3)ATVocabularies are tested

Oh, and about ATVocabularies and initialization.  I figured out that
there is a file in "Extensions" that you can create called
AppInstall.py where you can initialize your ATVocabularies.  Mine
looks something like this:

from Products.ATVocabularyManager.config import TOOL_NAME as
ATVOCABULARYTOOL
from Products.CMFCore.utils import getToolByName
from Products.ATVocabularyManager.utils.vocabs import
createSimpleVocabs

def install(self):
       """
         let's install the vocab
       """

       vocabs = { 'Instruments': (
              ('ftir-510', u'FTIR 510'),
              ),
              'Organizations': (
              ('University-of-Colorado', u'University of Colorado'),
              ),
              'Customers': (
              ('General-Electric', u'General Electric'),
              ),
              'SampleDescriptions': (
              ('a-si', u'a-Si'),
              ('ucsi-c-Si', u'ucSi/c-Si'),
              ),
              'StorageLocations':(
              ('510-c-drive', r'510 c\drive'),
              ('520-c-drive', r'520 c\drive'),
              ),
              'Comments':(
              ('t-vs-air-2cm-1', r' %T vs air, 2cm-1'),
              ('absorbance-coeff-thickness-corrected', r'Absorbance
coeff-thickness corrected'),
              ),
              'Companies':(
              ('General-Electric', u'General Electric'),
              ),
       }


       portal=getToolByName(self,'portal_url').getPortalObject()
       atvm = getToolByName(portal, ATVOCABULARYTOOL)
       createSimpleVocabs(atvm, vocabs)

Very nice indeed.

Comments.......

One thing I noticed was that there was no validation going on during
factory invocation.  Therefore, I was able to put an object in the
database with missing required fields.  I am not sure if this is
correct behavior, or what the theory is about this, but I am
interested if anyone has any information about this.

Also, the lack of support for nosetests makes me feel like I am back
in 2005.  Hopefully with buildout and other improvements Plone will
get up to speed on this valuable package.

cheers.
-chris


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Plone-Users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/plone-users
Martin Aspeli-2 () Re: A TG Developer Gets Ploned
Reply Threaded More More options
Print post
Permalink
Hi,

> Mostly I followed the instructions here:
> http://plone.org/documentation/tutorial/testing
> Somehow the page changed while I was actually working on it, and now I
> have to learn a bunch more about "contexts" but for now I am just
> going to test all of my code the old fashoned "unit test" way.

Er, sorry about that. I was editing it last night. It's better now
though. ;-)

> One thing I noticed was that there was no validation going on during
> factory invocation.  Therefore, I was able to put an object in the
> database with missing required fields.  I am not sure if this is
> correct behavior, or what the theory is about this, but I am
> interested if anyone has any information about this.

The validation happens on input, so if you'd written a functional test
you would've seen the errors. You can also call the validation machinery
explicitly, of course, but there's no direct validation on 'set'.

> Also, the lack of support for nosetests makes me feel like I am back
> in 2005.  Hopefully with buildout and other improvements Plone will
> get up to speed on this valuable package.

I guess people here aren't so used to nosetests. Maybe you can explain
why they're so great and what we may have to do to use them?

Martin

--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Plone-Users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/plone-users
percious () Re: A TG Developer Gets Ploned
Reply Threaded More More options
Print post
Permalink
Hey, No problem about updating the tutorial.  It's great to see that
the page is being updated.

Indeed validation does occur when tested through the web.  Again MVC
argument.  I wonder if some validation is more pertinent to the Model
side of things, theoretically.  I know TG does most of it's validation
on the view/controller side, much like Plone, but it does have support
for missing required data within the model.  Perhaps this is more a
feature of SQLAlchemy, and were I to implement a plone site support
SQA I would get my desired behavior.

Here is a link to nosetests:
http://code.google.com/p/python-nose/wiki/NoseFeatures

Much of the features of the testing "framework" have already been
implemented by plone, so they may be easy to adapt.

First and Foremost:  Test discovery.  Nose offers a more flexible way
of discovering tests in 0.10 .  "If you tell nose something is a test,
it will believe you"  Plone/Zope does test file discovery too, which I
like.  However, all of my test modules will have something like:

def test_suite():
    from unittest import TestSuite, makeSuite
    from inspect import isclass
    import sys

    suite = TestSuite()

    #retrieve all test classes from this file
    module = sys.modules[__name__]
    for item in dir(module):
        klass = getattr(module, item)
        if item[:4].lower() == 'test' and isclass(klass):
            suite.addTest(makeSuite(klass))

    return suite

at the bottom, which seems like unnecessary boiler plate (further
iterations I did move test_suite into base.py, but I still have to
import sys and pass sys.modules(__name__) into it.)


Secondly (and still important to me):  Test Code Boiler-plate
removal.  I know it seems minor, but I no longer have to sub-class
unittest.TestCase (or PloneTestCase) to get my tests to run.  Nose
just finds any class or function that starts with "Test" in files that
start with "test" or tEst or TeSt (etc.) and runs them.  Also, setUp
can be setup.  I find "afterSetUp" to be long and sort of confusing (I
do realize why it is called that, however). Jason Pellerin also
implemented some handy function decorators and made it so you can
create test generators.  @raises is nice because the assertRaises
function does not work very well with object creation, for instance.
So, if you wanted to test that a bad set in the initializer of a class
it would look something like this:

<...file to test...>

import types
class MyClass:
    def __init__(self, s):
        if not isinstance(s, types.StringTypes):
            raise TypeError('arg1 is not a string')

<...test code (in nose)...>
from myclass import MyClass
from nose.tools import raises

def setup():
    "module level setup here"

def teardown():
    "module level teardown here"

class TestMyClass:
    def setup(self):
        "class level setup here"

    def teardown(self):
        "class level teardown here"

    def testCreate(self):
        m = MyClass('s')

    @raises(TypeError)
    def _create(self, arg1):
        MyClass(arg1)

    def testCreateBad(self):
        badInput = ((), {}, 1, 1.3, [])
        for input in badInput:
            yield self._create, input

the nice thing about nosetests is the ability to create test iterators
(notice the yield) so that if the first thing you test fails it keeps
going.

take a look at the "testVocabulariesInstalled" function in my original
code.  You will notice that it will fail on the first missing
vocabulary.  This could cause costly test-development iterations if
you have more than one missing vocabulary.  Consider the nosetests
solution:

def assertVocabularyInstalled(self, v, atvm):
    assert v in atvm, "missing vocabulary: %s"%v

def testVocabulariesInstalled(self):
    portal=getToolByName(self.portal,'portal_url').getPortalObject()
    atvm = getToolByName(portal, ATVOCABULARYTOOL)
    for v in self.vocabularies:
        yield assertVocabularyInstalled(v, atvm)

Now you find out which vocabularies are missing the first time you run
it.  Excellent.

Another decorator that is useful is @with_setup which allows you to
set specific setup/teardown functions to a test method so that you can
avoid side-effects in other methods.  This is great for database work
because now you dont have to zap the entire database every run if you
want to work with a class-specific data set, with some functions doing
other things.

All this functionality you get for free which I think is great.  As I
said before Plone/Zope implemented some of this functionality, but
using nosetests you get so much more and you get it for nothing.  So,
what would it take to move over to nosetests?

Well I am not sure what kind of setup goes on in a PloneTestCase or
when you run zopectl -test, but they would probably need to be made
into functions that you can include in your module-level setup/
teardowns.  The functions would need to be written in such a way that
they are like singletons, IE they only run when the first module gets
loaded.  Other than that, all previous tests should be compatible
(including doctests) with nosetests, because nosetests looks for
doctests and anything that extends unittest.  You might consider
emailing Jason about what he thinks of the idea, he has been very
receptive to my questions in the past.

Overall testing has been great with plone and zope.  I wish I had
started it a bit sooner.  I certainly learned a lot about the inner
workings of the framework while I was trying to figure out how to
test...

Thanks again for all your help Martin.

-chris


On Oct 19, 5:11 pm, Martin Aspeli <[hidden email]> wrote:

> Hi,
>
> > Mostly I followed the instructions here:
> >http://plone.org/documentation/tutorial/testing
> > Somehow the page changed while I was actually working on it, and now I
> > have to learn a bunch more about "contexts" but for now I am just
> > going to test all of my code the old fashoned "unit test" way.
>
> Er, sorry about that. I was editing it last night. It's better now
> though. ;-)
>
> > One thing I noticed was that there was no validation going on during
> > factory invocation.  Therefore, I was able to put an object in the
> > database with missing required fields.  I am not sure if this is
> > correct behavior, or what the theory is about this, but I am
> > interested if anyone has any information about this.
>
> The validation happens on input, so if you'd written a functional test
> you would've seen the errors. You can also call the validation machinery
> explicitly, of course, but there's no direct validation on 'set'.
>
> > Also, the lack of support for nosetests makes me feel like I am back
> > in 2005.  Hopefully with buildout and other improvements Plone will
> > get up to speed on this valuable package.
>
> I guess people here aren't so used to nosetests. Maybe you can explain
> why they're so great and what we may have to do to use them?
>
> Martin
>
> --
> Author of `Professional Plone Development`, a book for developers who
> want to work with Plone. Seehttp://martinaspeli.net/plone-book
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems?  Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >>http://get.splunk.com/
> _______________________________________________
> Plone-Users mailing list
> [hidden email]://lists.sourceforge.net/lists/listinfo/plone-users


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Plone-Users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/plone-users
percious () Re: A TG Developer Gets Ploned
Reply Threaded More More options
Print post
Permalink
In reply to this post by percious
Part Vb - Functional Testing.

Ok, I will admit it, I am not big into doctests.  Its not that I don't
know how to use them, I just like the unit test framework.  I like
being able to subclass and remove boiler plate.  I like that my test
code follows the structure of my object code.  So.  I used unittest
style coding to do my functional tests.  It works just great.  Here is
a snipit:

class TestWebpage(ftirFunctionalTestCase):

    def afterSetUp(self):
        self.browser = Browser()
        self.portal.error_log._ignored_exceptions = ()
        self.portal_url =  self.portal.absolute_url()

    def _login(self):
        browser = self.browser
        browser.open(self.portal_url)
        browser.getControl(name='__ac_name').value = portal_owner
        browser.getControl(name='__ac_password').value =
default_password
        browser.getControl(name='submit').click()

    def testLogin(self):
        """since this is a functional test, this is tested
elsewhere"""
        self._login()
        assert self.browser.url == self.portal_url
        assert "You are now logged in" in self.browser.contents

    ...

    def testAllInOne(self):
        self._login()
        assert self.browser.url == self.portal_url
        assert "You are now logged in" in self.browser.contents
        self._addExperiments()
        assert """id="parent-fieldname-title">
            Experiments-item""" in self.browser.contents,
self.browser.contents
        self._addInfaredExperimentBad()
        assert """Samplenumber is required, please correct.""" in
self.browser.contents, self.browser.contents
        self._addInfaredExperiment()
        assert """id="parent-fieldname-title">
            InfaredExperiment-item""" in self.browser.contents,
self.browser.contents
        self._addColaborator()
        assert """id="parent-fieldname-title">
            Colaborator-item""" in self.browser.contents,
self.browser.contents
        self._addDataFile()
        assert """id="parent-fieldname-title">
            DataFile-item""" in self.browser.contents,
self.browser.contents

        ...

the only thing that is a bit pesky is learning where to get the
controls, but a little web browser action and some command-u work and
we are all there.  I now have a living breathing fully tested
(including missing required fields) application.  I can sleep at night
because I know it will be working when I come in in the morning.

I guess this concludes the walk-through of my experience with Plone
and Zope, but I may keep this thread alive to comment about
differences I see between frameworks.  Who knows, I may be comparing
plone to Ruby on Rails or (gasp) Django.

Special thanks to Martin who made so many comments and helped me out
when I was a bit frustrated in the beginning.  If you are at Pycon
this year, make sure you let me buy you a beer.

cheers.
-chris


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Plone-Users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/plone-users
Wichert Akkerman () Re: A TG Developer Gets Ploned
Reply Threaded More More options
Print post
Permalink
Previously percious wrote:
> Part Vb - Functional Testing.
>
> Ok, I will admit it, I am not big into doctests.  Its not that I don't
> know how to use them, I just like the unit test framework.  I like
> being able to subclass and remove boiler plate.  I like that my test
> code follows the structure of my object code.  So.  I used unittest
> style coding to do my functional tests.  It works just great.  Here is
> a snipit:

FWIW, I agree. I find doctests to be painful things.

Wichert.

--
Wichert Akkerman <[hidden email]>    It is simple to make things.
http://www.wiggy.net/                   It is hard to make things simple.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Plone-Users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/plone-users
Matthew Wilkes () Re: A TG Developer Gets Ploned
Reply Threaded More More options
Print post
Permalink
In reply to this post by percious
Some javascript/style in this post has been disabled (why?)

On 22 Oct 2007, at 15:20, percious wrote:

the only thing that is a bit pesky is learning where to get the

controls, but a little web browser action and some command-u work and

we are all there



It generates doc-tests, but I'm sure the code would be helpful in the pure-python test method too.

Matt

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Plone-Users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/plone-users
1 2