5

I'm writing some unit tests (using the unittest module) for my application, and want to write something which can verify that a method I'm calling returns a "file-like" object. Since this isn't a simple isinstance call, I wonder what the best-practice would be for determining this?

So, in outline:

possible_file = self.dao.get_file("anotherfile.pdf")
self.assertTrue(possible_file is file-like)

Perhaps I have to care which specific interface this file object implements, or which methods that make it file-like I want to support?

Thanks,

R

0

3 Answers 3

7

There is no "official definition" of what objects are "sufficiently file-like", because the various uses of file-like objects have such different requirements -- e.g., some only require read or write methods, other require some subset of the various line-reading methods... all the ways to some requiring the fileno method, which can't even be supplied by the "very file-like objects" offered by StringIO and cStringIO modules in the standard library. It's definitely a question of "shades of gray", not a black-and-white taxonomy!

So, you need to determine which methods you need. To check for them, I recommended defining your own FileLikeEnoughForMe abstract base class with abstractmethod decorators, and checking the object with an isinstance for that class, if you're on Python 2.6 or better: this is the recommended idiom these days, rather than a bunch of hasattr checks which would be less readable and more complex (when properly beefed up with checks that those attributes are actually methods, etc;-).

Sign up to request clarification or add additional context in comments.

4 Comments

Hi Alex, Thanks for the pointer, this is interesting stuff, although am still getting my head around it. Do you suggest to just use this for the unittest or should this be a general approach to managing file-like objects inside an application?
@Richard, I'm barely "getting my feet wet" myself with production use of ABCs in Python (though the analogies with Haskell typeclasses, C++'s abstract base classes, Java interfaces, etc, do help me;-) so I can't (yet) solidly recommend them or otherwise in that context. I think they'll be just fine (again by analogy with alternatives I do know very well) but I need a little more real-world tussling with them "under my belt" to feel really confident either way;-). But, for testing purposes, I already do know they're "the cat's pajamas", i.e., excellent and useful indeed.
arg - no code markup in comments!
@Richard, have you looked at the code examples at docs.python.org/library/abc.html? Specifically the MyIterable example and its override of __subclasshook__ -- that shows how to check for the presence of certain methods (though it's a simplified example that doesn't check they are methods). It's not the best way to use ABCs, in general, because the lack of any explicit registration (or subclassing) robs you of the crucial advantage of verifying intent (the famous "problem of the draw method"), but if you're checking for presence that's the way to do it in 2.6+.
4

The classical Python mentality is that it's easier to ask forgiveness than permission. In other words, don't check, catch the exception caused by writeing to it.

The new way is to use an IO abstract base class in an isinstance check. This was introduced when people realised that duck typing is awesome, but sometimes you really do want an instance check.

In your case (unittesting), you probably want to try it and see:

thingy = ...
try:
    thingy.write( ... )
    thingy.writeline( ... )
    ...
    thingy.read( )
except AttributeError:
    ...

6 Comments

trying to write to the file might not be appropriate in a unit test context.
+1 for classical and renaissance thought patterns
@Ned: really? If you're implementing a file-like class, surely you should test that it does write down what you give it? But if you really don't want that, then you can use hasattr.
@Ned, wouldn't that depend on what the file writing is actually doing? i.e. shouldn't a unit test "clean up" after testing to see if that part of the program really does write?
@Wayne, @katrielalex: yes, you might want to write to it, and you might get clean up automatically depending on what the file is. My point was that the logic that goes in typical programming (ask forgiveness) might not be appropriate in a unit test, depending on what the test was trying to accomplish. That's all.
|
2

Check, if returned object provides interface you are looking for. Like this for example:

self.assert_(hasattr(possible_file, 'write'))
self.assert_(hasattr(possible_file, 'read'))

2 Comments

Don't do this unless you're sure that you want it.
Yeah, well I wouldn't do that. But he asked for a way to check, if something is file like, not to use it as a file.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.