[Twisted-Python] Direct access to main server class

Jean-Paul Calderone exarkun at divmod.com
Mon Aug 28 11:01:55 EDT 2006


On Mon, 28 Aug 2006 16:05:23 +0200, Terry Jones <terry at jon.es> wrote:
>Here's a hopefully not-too-dumb question...
>
>I have a class that provides a service that I plan to make accessible via
>Twisted. I wrote the class and various unit tests. So I could formerly do
>simple things like:
>
>    import unittest
>
>    class myTest:
>       def setUp():
>           self.c = MyClass()
>
>       def tearDown():
>           self.c.close()
>
>       def testX():
>           self.assert_(self.c.X() == 4)
>
>
>I recently added users, passwords, and permissions to the system. So now
>many method calls need a requesting user object passed to them, and check
>that the user has permission to carry out the action. I added simple
>twisted.cred class to provide realms, avatars, portal with checkers, etc.

Aside from the rest of your question and my response, this sounds inside
out.  The general idea is that the user object itself has methods which
implement the actions which the protocol allows to be taken.  If a user
lacks permission to perform a particular action, or has restrictions on
the particulars with which they may invoke that action, or whatever other
logic may be necessary on a per-user basis, that is represented by a
different implementation of the login interface.

It may not necessarily be the case that factoring your code as I've just
described would be better than what you are doing now, but if you haven't
considered it before, it may be worth doing so now.

>
>In the myApp.tac file, I create an instance of my top-level class (MyClass
>above). In the case of providing access to my service via Nevow, I
>instantiate a NevowSite and pass it the portal. That is all, I think, as it
>should be.
>
>But now I'm left wondering what happens to the old unit testing code. It
>obviously cannot just create a MyClass instance. The unit testing code
>should be using the service by authenticating itself just like any other
>client. But I'm not sure how best to do that. The unit test code wants to
>perform all manner of tests, and preferably this would be done by just
>making available the instance of MyClass created in my app's .tac file,
>allowing the test code to call its methods. But somehow that no longer
>feels quite right - the connection is in fact local, but it's coming in
>somehow through twisted.cred.
>
>I hope I'm being more or less clear about my dilemma, and I suppose this
>must be a situation people have to deal with all the time.

It's a little fuzzy.  Let me see if I can accurately summarize.

   Your server is started up from a .tac file.

   The .tac file creates some objects and gives them particular
   relationships.

   The relationships created in the .tac file are necessary for correct
   operation of the server.

   The unit tests have no way to run the code in the .tac file in order
   to duplicate these relationships.

If these statements are accurate, I would suggest moving some code out of
the .tac file into a real module, from whence your unit tests can import
and use it.

>
>Two solutions come to mind:
>
>  1) Fake it. Call directly into my code to make myself an authenticated
>     user object, and then start passing it in to methods on my own
>     class. This is ugly though, plus if the service is already running
>     it's a bad solution because it goes behind the back of twisted and
>     asks for trouble.

This actually sounds a little like what I described above.  What makes you
say it is ugly?  To me, it sounds like organizing your code so that you
can test it a unit at a time.  The tests which do this are testing the
behavior of your code when authentication has already succeeded.  You should
also have tests for your authentication code, of course - but that's a
separate unit.

>
>  2) Make all the methods of my class available via RPC and have all the
>     unit test code use them. This seems like a major pain, though I
>     suppose it would work.

In the past I have done this, and I have regretted it.  This kind of test
is unnecessarily expensive to run and unnecessarily difficult to debug.

>
>I'd much rather just have the unit test code connect as a special local
>user and get back the instance of MyClass created by my .tac file and call
>its methods. Is that easy to do?

If you move the code responsible for instantiating MyClass out of the .tac
file into a real module, then it is easy :)  Otherwise it may as well be
impossible.

>
>OK, sorry for another typically long posting....

No problem.  I hope this was of some help.

Jean-Paul




More information about the Twisted-Python mailing list