Roy Smith wrote: > I realize the subject line is kind of meaningless, so let me explain :-) > > I've got some unit tests that look like: > > class Foo(TestCase): > def test_t1(self): > RECEIPT = "some string" > > def test_t2(self): > RECEIPT = "some other string" > > def test_t3(self): > RECEIPT = "yet a third string" > > and so on. It's important that the strings be mutually unique. In the > example above, it's trivial to look at them and observe that they're all > different, but in real life, the strings are about 2500 characters long, > hex-encoded. It even turns out that a couple of the strings are > identical in the first 1000 or so characters, so it's not trivial to do > by visual inspection. > > So, I figured I would write a meta-test, which used introspection to > find all the methods in the class, extract the strings from them (they > are all assigned to a variable named RECEIPT), and check to make sure > they're all different. > > Is it possible to do that? It is straight-forward using the inspect > module to discover the methods, but I don't see any way to find what > strings are assigned to a variable with a given name. Of course, that > assignment doesn't even happen until the function is executed, so > perhaps what I want just isn't possible? > > It turns out, I solved the problem with more mundane tools: > > grep 'RECEIPT = ' test.py | sort | uniq -c > > and I could have also solved the problem by putting all the strings in a > dict and having the functions pull them out of there. But, I'm still > interested in exploring if there is any way to do this with > introspection, as an academic exercise.
Instead of using introspection you could make it explicit with a decorator: $ cat unique_receipt.py import functools import sys import unittest _receipts = {} def unique_receipt(receipt): def deco(f): if receipt in _receipts: raise ValueError( "Duplicate receipt {!r} in \n {} and \n {}".format( receipt, _receipts[receipt], f)) _receipts[receipt] = f @functools.wraps(f) def g(self): return f(self, receipt) return g return deco class Foo(unittest.TestCase): @unique_receipt("foo") def test_t1(self, RECEIPT): pass @unique_receipt("bar") def test_t2(self, RECEIPT): pass @unique_receipt("foo") def test_t3(self, RECEIPT): pass if __name__ == "__main__": unittest.main() $ python unique_receipt.py Traceback (most recent call last): File "unique_receipt.py", line 19, in <module> class Foo(unittest.TestCase): File "unique_receipt.py", line 28, in Foo @unique_receipt("foo") File "unique_receipt.py", line 11, in deco receipt, _receipts[receipt], f)) ValueError: Duplicate receipt 'foo' in <function test_t1 at 0x7fc8714af5f0> and <function test_t3 at 0x7fc8714af7d0> -- https://mail.python.org/mailman/listinfo/python-list