During the Pycon sprint I ended up writing some nasty tests for a simple feature.
Let’s say you’re writing a test for a class like this:
class Foo:
def foo():
if os.environ['FOO'] == 'bar':
...
elif os.name != 'posix':
...
elif somemodule.some_function():
...
It’s the usual isolation problem that leads people to using mocks and stubs. What’s bothering me is the need to replace those imported names (os.environ, os.name, etc.) for the duration of the test, and cleanly restore them after the test.
One approach, which I used in the patch I submitted for that feature, is to monkeypatch during test setup, replacing the problematic values and functions; and then restore the originals during teardown.
This just smells bad to me; it stinks in proportion to the number of things you monkeypatch. I ended up with four, which is plenty of stink. Why? If your setup and teardown code drift out of sync, or your teardown raises an exception before it finishes, or or or … you get very obscure failures in unrelated parts of your system.
My crazy idea is this: What if there were a way to deep-copy the global namespace seen by the object under test, and inject things into this fake globals copy, without modifying the real globals? That would be totally safe: other instances and classes would see the world as usual, and when the test exits, the copy would just get thrown away.
But I think it’s just not possible. Oh well.
Off to France! I’ll be back at TOPP on 3/27.

No Comments
RSSNo comments yet.
Leave a comment