[Twisted-Python] Direct access to main server class

glyph at divmod.com glyph at divmod.com
Tue Aug 29 08:35:10 EDT 2006

On Tue, 29 Aug 2006 09:57:36 +0200, Terry Jones <terry at jon.es> wrote:
>>>>>> "glyph" == glyph  <glyph at divmod.com> writes:

>glyph> However, even disregarding that, _some_ code in your system is
>glyph> instantiating authenticated users

>Right, that's what I was saying.

Whew.  Okay, great.

>I agree [security through obscurity is] almost always an error (and those that choose it
>reflexively are also particularly prone to the attendant false sense of
>security. One would hope that some form of Darwinian selection might kick
>in, but it never does).

Oh... sometimes it does.  I know a story about a sysadmin who seriously thought that SSH was "secure" enough that his root password could be "root" because it was "easier to remember", as long as he changed the port number... (Hint: at the end of the story, he is not happy.  Also he doesn't have a job.)

>glyph> So, I disagree in the strongest possible terms: it *isn't* an issue,

>I don't understand how the above sentence follows from the one before (and
>no, I'm not trolling either!).

I was responding to this in the original email (emphasis mine):

>>>Maybe they wont get far, but *it's an issue*: especially if
the system has been built to allow this, and the unit tests show precisely
how to pull it off.

I suppose I misunderstood what you meant by that.  Thank goodness :).

>OK, I think we have the same aim: I'm trying to NOT write obtuse and
>complex tests. That's why I was originally asking if there's an easy way to
>make tests go through the front door (via twisted.cred) to get something
>they can start making calls on.

If you want to do white-box testing via cred, it's not very hard; you can just construct a Portal in setUp and call "login" on it.  *Some* tests should be written that way, to test the code that builds the "front door", so to speak, but I think that JP's advice is still generally correct here.  You really only want to do that in tests for cred itself, tests for deployment code that creates a Portal, or perhaps for an implementation of a cred interface such as a checker or realm.  Most of your tests for user objects should be instantiating the user objects directly; this should also promote less coupling, so that you will avoid the temptation to do something required to the avatar object during the login process, reducing the need for set-up boilerplate in non-test situations as well.

This is actually part of the design of cred, too; it's the reason it doesn't specify any requirements in particular about the avatar interface.  Once you're through the login process, cred objects are supposed to be plain old python objects that don't do anything but respond to method calls made by your protocol.  The login / setup procedure shouldn't be a required part of their operation.

For example, your avatar object might require a reference to a database.  One way to acquire that would be to have some code in your IRealm implementation set a required attribute on the avatar object.  Another way would be to simply pass it to the avatar object's constructor.  I think the benefits of the latter approach are clear when you consider it, even though it may sometimes seem reasonable as you're writing the code to put more logic in requestAvatar since that is the "right" way to "get" an avatar object.

If it's simply a constructor argument, then you can provide a mock implementation for tests to avoid expensive database setup/teardown operations, making your tests faster.  Even if the DB object is too complex to bother mocking for tests, you can simulate error conditions that you want to write tests for by wrapping it up.  This is all _possible_ by going through some other object, of course (set it as an attribute on the Realm, or something like that) but it is more complex.  It's not clear where to modify your tests.  Presumably you'd have to subclass and override setUp or something like that.  In the constructor case, however, you just change the object that you pass in in the test body itself.

I could keep writing about my opinions on good test practice for an even longer essay... actually, I probably will, in a blog post.  For now, though, I think I've belabored the point enough :).  Hope this helps!

More information about the Twisted-Python mailing list