From anuraguniyal at yahoo.com Wed Aug 1 14:30:25 2007 From: anuraguniyal at yahoo.com (anurag uniyal) Date: Wed, 1 Aug 2007 05:30:25 -0700 (PDT) Subject: [py-dev] py.test error? Message-ID: <869852.83955.qm@web37301.mail.mud.yahoo.com> While running py.test on my unitests I got following error in py.test code? It occurred when I changed an assert statement so that it fails. I tried to replicate this in a small sample script but could not replicate it. Here is the complete output: ______ entrypoint: Test_CollectionPrefs().test_recursive_attribute_access ______ def runtraced(self, colitem): if self.shouldclose(): raise Exit, "received external close signal" outcome = None colitem.startcapture() try: self.start(colitem) try: try: if colitem._stickyfailure: raise colitem._stickyfailure > outcome = self.run(colitem) [/usr/lib/python2.4/site-packages/py/test/session.py:83] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def run(self, colitem): if self.config.option.collectonly and isinstance(colitem, py.test.collect.Item): return if isinstance(colitem, py.test.collect.Item): colitem._skipbykeyword(self.config.option.keyword) > res = colitem.run() [/usr/lib/python2.4/site-packages/py/test/session.py:106] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def run(self): """ setup and execute the underlying test function. """ self._state.prepare(self) > self.execute(self.obj, *self._args) [/usr/lib/python2.4/site-packages/py/test/item.py:67] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def execute(self, target, *args): """ execute the given test function. """ > target(*args) [/usr/lib/python2.4/site-packages/py/test/item.py:71] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def __init__(self, *args): BuiltinAssertionError.__init__(self, *args) if args: self.msg = str(args[0]) else: f = sys._getframe(1) try: source = py.code.Frame(f).statement source = str(source.deindent()).strip() except py.error.ENOENT: source = None # this can also occur during reinterpretation, when the # co_filename is set to "". if source: > self.msg = exprinfo.interpret(source, f, should_fail=True) [/usr/lib/python2.4/site-packages/py/magic/assertion.py:22] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def interpret(source, frame, should_fail=False): module = Interpretable(parse(source, 'exec').node) #print "got module", module if isinstance(frame, py.std.types.FrameType): frame = py.code.Frame(frame) try: module.run(frame) except Failure, e: > return getfailure(e) [/usr/lib/python2.4/site-packages/py/magic/exprinfo.py:424] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def getfailure(e): > explanation = e.node.nice_explanation() [/usr/lib/python2.4/site-packages/py/magic/exprinfo.py:450] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def nice_explanation(self): # uck! See CallFunc for where \n{ and \n} escape sequences are used raw_lines = (self.explanation or '').split('\n') # escape newlines not followed by { and } lines = [raw_lines[0]] for l in raw_lines[1:]: if l.startswith('{') or l.startswith('}'): lines.append(l) else: lines[-1] += '\\n' + l result = lines[:1] stack = [0] stackcnt = [0] for line in lines[1:]: if line.startswith('{'): if stackcnt[-1]: s = 'and ' else: s = 'where ' stack.append(len(result)) stackcnt[-1] += 1 stackcnt.append(0) result.append(' +' + ' '*(len(stack)-1) + s + line[1:]) else: assert line.startswith('}') stack.pop() stackcnt.pop() E result[stack[-1]] += line[1:] > IndexError: list index out of range [/usr/lib/python2.4/site-packages/py/magic/exprinfo.py:78] _______________________________________________________________ ____________________________________________________________________________________ Be a better Globetrotter. Get better travel answers from someone who knows. Yahoo! Answers - Check it out. http://answers.yahoo.com/dir/?link=list&sid=396545469 From holger at merlinux.de Fri Aug 3 17:54:43 2007 From: holger at merlinux.de (holger krekel) Date: Fri, 3 Aug 2007 17:54:43 +0200 Subject: [py-dev] py.test error? In-Reply-To: <869852.83955.qm@web37301.mail.mud.yahoo.com> References: <869852.83955.qm@web37301.mail.mud.yahoo.com> Message-ID: <20070803155443.GZ4574@solar.trillke> Hi Anurag! indeed your example points to a py lib problem, probably during parsing or interpretation of the expression of the assert statement. Could you maybe provide a (minimally) failing test, reproducing the problem? That should make it easier to fix the problem. best & thanks, holger On Wed, Aug 01, 2007 at 05:30 -0700, anurag uniyal wrote: > While running py.test on my unitests I got following error in py.test code? > It occurred when I changed an assert statement so that it fails. > I tried to replicate this in a small sample script but could not replicate it. > > Here is the complete output: > > ______ entrypoint: Test_CollectionPrefs().test_recursive_attribute_access ______ > > def runtraced(self, colitem): > if self.shouldclose(): > raise Exit, "received external close signal" > > outcome = None > colitem.startcapture() > try: > self.start(colitem) > try: > try: > if colitem._stickyfailure: > raise colitem._stickyfailure > > outcome = self.run(colitem) > > [/usr/lib/python2.4/site-packages/py/test/session.py:83] > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > def run(self, colitem): > if self.config.option.collectonly and isinstance(colitem, py.test.collect.Item): > return > if isinstance(colitem, py.test.collect.Item): > colitem._skipbykeyword(self.config.option.keyword) > > res = colitem.run() > > [/usr/lib/python2.4/site-packages/py/test/session.py:106] > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > def run(self): > """ setup and execute the underlying test function. """ > self._state.prepare(self) > > self.execute(self.obj, *self._args) > > [/usr/lib/python2.4/site-packages/py/test/item.py:67] > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > def execute(self, target, *args): > """ execute the given test function. """ > > target(*args) > > [/usr/lib/python2.4/site-packages/py/test/item.py:71] > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > def __init__(self, *args): > BuiltinAssertionError.__init__(self, *args) > if args: > self.msg = str(args[0]) > else: > f = sys._getframe(1) > try: > source = py.code.Frame(f).statement > source = str(source.deindent()).strip() > except py.error.ENOENT: > source = None > # this can also occur during reinterpretation, when the > # co_filename is set to "". > if source: > > self.msg = exprinfo.interpret(source, f, should_fail=True) > > [/usr/lib/python2.4/site-packages/py/magic/assertion.py:22] > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > def interpret(source, frame, should_fail=False): > module = Interpretable(parse(source, 'exec').node) > #print "got module", module > if isinstance(frame, py.std.types.FrameType): > frame = py.code.Frame(frame) > try: > module.run(frame) > except Failure, e: > > return getfailure(e) > > [/usr/lib/python2.4/site-packages/py/magic/exprinfo.py:424] > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > def getfailure(e): > > explanation = e.node.nice_explanation() > > [/usr/lib/python2.4/site-packages/py/magic/exprinfo.py:450] > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > def nice_explanation(self): > # uck! See CallFunc for where \n{ and \n} escape sequences are used > raw_lines = (self.explanation or '').split('\n') > # escape newlines not followed by { and } > lines = [raw_lines[0]] > for l in raw_lines[1:]: > if l.startswith('{') or l.startswith('}'): > lines.append(l) > else: > lines[-1] += '\\n' + l > > result = lines[:1] > stack = [0] > stackcnt = [0] > for line in lines[1:]: > if line.startswith('{'): > if stackcnt[-1]: > s = 'and ' > else: > s = 'where ' > stack.append(len(result)) > stackcnt[-1] += 1 > stackcnt.append(0) > result.append(' +' + ' '*(len(stack)-1) + s + line[1:]) > else: > assert line.startswith('}') > stack.pop() > stackcnt.pop() > E result[stack[-1]] += line[1:] > > IndexError: list index out of range > > [/usr/lib/python2.4/site-packages/py/magic/exprinfo.py:78] > _______________________________________________________________ > > > > > > ____________________________________________________________________________________ > Be a better Globetrotter. Get better travel answers from someone who knows. Yahoo! Answers - Check it out. > http://answers.yahoo.com/dir/?link=list&sid=396545469 > _______________________________________________ > py-dev mailing list > py-dev at codespeak.net > http://codespeak.net/mailman/listinfo/py-dev > -- merlinux GmbH Steinbergstr. 42 31139 Hildesheim http://merlinux.de tel +49 5121 20800 75 (fax 77) From jbjoerk at gmail.com Wed Aug 8 00:48:05 2007 From: jbjoerk at gmail.com (=?ISO-8859-1?Q?Johan_Bj=F6rk?=) Date: Tue, 7 Aug 2007 15:48:05 -0700 Subject: [py-dev] py.test and asserts in method_teardown Message-ID: <5fcbe0720708071548s6b41580cob2eb6736cd5b3ac7@mail.gmail.com> Hi, First post on the list, please excuse me if I don't follow normal guidelines for posting here... I'm having an assert in my method_teardown, which gives rather confusing results. See attached short example (ugly) Running py.test on this testclass, you will get an output similar to: entrypoint: TestMyClass().testApa3 _________________________________________ def teardown_method(self,method): if(salmon): E assert 0 > assert 0 [/Users/phb/Documents/Development/radar/pytest/test_class.py:9] I would have expected to get "testApa2" as the entrypoint. Ideas? Thanks /Johan -------------- next part -------------- A non-text attachment was scrubbed... Name: test_class.py Type: application/octet-stream Size: 319 bytes Desc: not available URL: From fijal at genesilico.pl Wed Aug 8 10:44:36 2007 From: fijal at genesilico.pl (Maciek Fijalkowski) Date: Wed, 08 Aug 2007 10:44:36 +0200 Subject: [py-dev] py.test and asserts in method_teardown In-Reply-To: <5fcbe0720708071548s6b41580cob2eb6736cd5b3ac7@mail.gmail.com> References: <5fcbe0720708071548s6b41580cob2eb6736cd5b3ac7@mail.gmail.com> Message-ID: <46B98274.2060501@genesilico.pl> Johan Bj?rk wrote: > Hi, > > First post on the list, please excuse me if I don't follow normal > guidelines for posting here... > > > I'm having an assert in my method_teardown, which gives rather > confusing results. > > See attached short example (ugly) > Running py.test on this testclass, you will get an output similar to: > > entrypoint: TestMyClass().testApa3 _________________________________________ > > def teardown_method(self,method): > if(salmon): > E assert 0 > >> assert 0 >> > > [/Users/phb/Documents/Development/radar/pytest/test_class.py:9] > > I would have expected to get "testApa2" as the entrypoint. > > Ideas? > > Thanks > /Johan > > Yes, this is known issue, although thanks for spotting. The reason is that teardown_method is called only when trying to access next test. I hope to have it fixed this week. (I can explain in more detail if you're interested) Cheers, fijal PS Posting this way is perfectly fine. :. From jbjoerk at gmail.com Wed Aug 8 21:57:03 2007 From: jbjoerk at gmail.com (=?ISO-8859-1?Q?Johan_Bj=F6rk?=) Date: Wed, 8 Aug 2007 12:57:03 -0700 Subject: [py-dev] py.test and asserts in method_teardown In-Reply-To: <46B98274.2060501@genesilico.pl> References: <5fcbe0720708071548s6b41580cob2eb6736cd5b3ac7@mail.gmail.com> <46B98274.2060501@genesilico.pl> Message-ID: <5fcbe0720708081257ka0251d6oc30703fbcebd5af@mail.gmail.com> Hi, Thanks for the response. Just to make sure, teardown_method IS supposed to be called at every teardown right? I'm setting up some state in databases that it's pretty important that I clean up (even if there are no following test) /Johan On 8/8/07, Maciek Fijalkowski wrote: > Johan Bj?rk wrote: > > Hi, > > > > First post on the list, please excuse me if I don't follow normal > > guidelines for posting here... > > > > > > I'm having an assert in my method_teardown, which gives rather > > confusing results. > > > > See attached short example (ugly) > > Running py.test on this testclass, you will get an output similar to: > > > > entrypoint: TestMyClass().testApa3 _________________________________________ > > > > def teardown_method(self,method): > > if(salmon): > > E assert 0 > > > >> assert 0 > >> > > > > [/Users/phb/Documents/Development/radar/pytest/test_class.py:9] > > > > I would have expected to get "testApa2" as the entrypoint. > > > > Ideas? > > > > Thanks > > /Johan > > > > > Yes, this is known issue, although thanks for spotting. > > The reason is that teardown_method is called only when trying to access > next test. I hope to have it fixed this week. (I can explain in more > detail if you're interested) > > Cheers, > fijal > > > PS Posting this way is perfectly fine. > > > > :. > > From fijal at genesilico.pl Wed Aug 8 22:19:23 2007 From: fijal at genesilico.pl (Maciek Fijalkowski) Date: Wed, 08 Aug 2007 22:19:23 +0200 Subject: [py-dev] py.test and asserts in method_teardown In-Reply-To: <5fcbe0720708081257ka0251d6oc30703fbcebd5af@mail.gmail.com> References: <5fcbe0720708071548s6b41580cob2eb6736cd5b3ac7@mail.gmail.com> <46B98274.2060501@genesilico.pl> <5fcbe0720708081257ka0251d6oc30703fbcebd5af@mail.gmail.com> Message-ID: <46BA254B.7090206@genesilico.pl> Johan Bj?rk wrote: > Hi, > Thanks for the response. > Just to make sure, teardown_method IS supposed to be called at every > teardown right? I'm setting up some state in databases that it's > pretty important that I clean up (even if there are no following test) > > /Johan > > On 8/8/07, Maciek Fijalkowski wrote: > >> Johan Bj?rk wrote: >> >>> Hi, >>> >>> First post on the list, please excuse me if I don't follow normal >>> guidelines for posting here... >>> >>> >>> I'm having an assert in my method_teardown, which gives rather >>> confusing results. >>> >>> See attached short example (ugly) >>> Running py.test on this testclass, you will get an output similar to: >>> >>> entrypoint: TestMyClass().testApa3 _________________________________________ >>> >>> def teardown_method(self,method): >>> if(salmon): >>> E assert 0 >>> >>> >>>> assert 0 >>>> >>>> >>> [/Users/phb/Documents/Development/radar/pytest/test_class.py:9] >>> >>> I would have expected to get "testApa2" as the entrypoint. >>> >>> Ideas? >>> >>> Thanks >>> /Johan >>> >>> >>> >> Yes, this is known issue, although thanks for spotting. >> >> The reason is that teardown_method is called only when trying to access >> next test. I hope to have it fixed this week. (I can explain in more >> detail if you're interested) >> >> Cheers, >> fijal >> >> >> PS Posting this way is perfectly fine. >> >> >> >> :. >> >> Yes, teardown will be called. The only place where you don't call it is if you have no test at all. like: class X: def setup_method(cls): stuff def teardown_method(cls): stuff otherwise it'll be called :. From holger at merlinux.de Wed Aug 8 22:36:44 2007 From: holger at merlinux.de (holger krekel) Date: Wed, 8 Aug 2007 22:36:44 +0200 Subject: [py-dev] py.test and asserts in method_teardown In-Reply-To: <5fcbe0720708081257ka0251d6oc30703fbcebd5af@mail.gmail.com> References: <5fcbe0720708071548s6b41580cob2eb6736cd5b3ac7@mail.gmail.com> <46B98274.2060501@genesilico.pl> <5fcbe0720708081257ka0251d6oc30703fbcebd5af@mail.gmail.com> Message-ID: <20070808203644.GP4574@solar.trillke> Hi Johan, On Wed, Aug 08, 2007 at 12:57 -0700, Johan Bj?rk wrote: > Thanks for the response. > Just to make sure, teardown_method IS supposed to be called at every > teardown right? I'm setting up some state in databases that it's > pretty important that I clean up (even if there are no following test) for each setup_X the according teardown_X is called with X being "module", "class" or "method". However, in the curent code base, the invocation of teardowns is indeed done lazily (as Maciej points out), i.e. for def teardown_method(self): ... def test_1(self): ... def test_2(self): ... teardown_method(self, test_1) will be called when the test_2 is actually setup. This serves to avoid un-neccessary teardown/setup cycles. However for methods, including generative test methods (those having a "yield" in them), we could probably see to teardown less lazily as its clear that teardown needs to be called on the next test, anyway. In any case, your reported situation highlights a reporting bug as it relates the failure to the wrong test method. I guess it makes sense to aim at a more specialized reporting of setup/teardown problems. best & thanks for pointing the problem out, holger > /Johan > > On 8/8/07, Maciek Fijalkowski wrote: > > Johan Bj?rk wrote: > > > Hi, > > > > > > First post on the list, please excuse me if I don't follow normal > > > guidelines for posting here... > > > > > > > > > I'm having an assert in my method_teardown, which gives rather > > > confusing results. > > > > > > See attached short example (ugly) > > > Running py.test on this testclass, you will get an output similar to: > > > > > > entrypoint: TestMyClass().testApa3 _________________________________________ > > > > > > def teardown_method(self,method): > > > if(salmon): > > > E assert 0 > > > > > >> assert 0 > > >> > > > > > > [/Users/phb/Documents/Development/radar/pytest/test_class.py:9] > > > > > > I would have expected to get "testApa2" as the entrypoint. > > > > > > Ideas? > > > > > > Thanks > > > /Johan > > > > > > > > Yes, this is known issue, although thanks for spotting. > > > > The reason is that teardown_method is called only when trying to access > > next test. I hope to have it fixed this week. (I can explain in more > > detail if you're interested) > > > > Cheers, > > fijal > > > > > > PS Posting this way is perfectly fine. > > > > > > > > :. > > > > > _______________________________________________ > py-dev mailing list > py-dev at codespeak.net > http://codespeak.net/mailman/listinfo/py-dev > -- merlinux GmbH Steinbergstr. 42 31139 Hildesheim http://merlinux.de tel +49 5121 20800 75 (fax 77) From holger at merlinux.de Tue Aug 14 15:37:19 2007 From: holger at merlinux.de (holger krekel) Date: Tue, 14 Aug 2007 15:37:19 +0200 Subject: [py-dev] [py-svn] r45649 - py/trunk/py In-Reply-To: <20070814094904.93E7A8110@code0.codespeak.net> References: <20070814094904.93E7A8110@code0.codespeak.net> Message-ID: <20070814133718.GM4329@solar.trillke> Hi Maciej, (cc py-dev), i see the idea/need for more differentiated ways of skipping (or test failures) but don't like adding new names to the geneneral py.test namespace like this. What about decorating functions in special ways? best, holger On Tue, Aug 14, 2007 at 11:49 +0200, fijal at codespeak.net wrote: > Author: fijal > Date: Tue Aug 14 11:49:04 2007 > New Revision: 45649 > > Modified: > py/trunk/py/__init__.py > Log: > Two possible skip reasons > > > Modified: py/trunk/py/__init__.py > ============================================================================== > --- py/trunk/py/__init__.py (original) > +++ py/trunk/py/__init__.py Tue Aug 14 11:49:04 2007 > @@ -31,6 +31,8 @@ > 'test.skip' : ('./test/item.py', 'skip'), > 'test.fail' : ('./test/item.py', 'fail'), > 'test.exit' : ('./test/session.py', 'exit'), > + 'test.broken' : ('./test/item.py', 'Broken'), > + 'test.notimplemented' : ('./test/item.py', '_NotImplemented'), > > # configuration/initialization related test api > 'test.config' : ('./test/config.py', 'config_per_process'), > _______________________________________________ > py-svn mailing list > py-svn at codespeak.net > http://codespeak.net/mailman/listinfo/py-svn > -- merlinux GmbH Steinbergstr. 42 31139 Hildesheim http://merlinux.de tel +49 5121 20800 75 (fax 77) From fijal at genesilico.pl Tue Aug 14 15:47:20 2007 From: fijal at genesilico.pl (Maciek Fijalkowski) Date: Tue, 14 Aug 2007 15:47:20 +0200 Subject: [py-dev] [py-svn] r45649 - py/trunk/py In-Reply-To: <20070814133718.GM4329@solar.trillke> References: <20070814094904.93E7A8110@code0.codespeak.net> <20070814133718.GM4329@solar.trillke> Message-ID: <46C1B268.9040208@genesilico.pl> holger krekel wrote: > Hi Maciej, (cc py-dev), > > i see the idea/need for more differentiated ways > of skipping (or test failures) but don't like adding > new names to the geneneral py.test namespace like this. > > What about decorating functions in special ways? > > best, > > holger > To be honest, i don't see any good syntax for that (I mean that current one is not good as well), so I can basically agree to anything. What I would like to have is the ability for a reporter to distinguish what's that (hence Skipped exception should carry a bit more info than just message). So for me, whatever. Cheers, fijal :. From fijal at genesilico.pl Tue Aug 14 15:48:19 2007 From: fijal at genesilico.pl (Maciek Fijalkowski) Date: Tue, 14 Aug 2007 15:48:19 +0200 Subject: [py-dev] [py-svn] r45649 - py/trunk/py In-Reply-To: <20070814133718.GM4329@solar.trillke> References: <20070814094904.93E7A8110@code0.codespeak.net> <20070814133718.GM4329@solar.trillke> Message-ID: <46C1B2A3.3030906@genesilico.pl> well, to be honest it's not whatever. py.test.skip(py.test.broken(...)) sounds a bit too long for me. So I would really like to have sth shorter, no idea what yet. Cheers, fijal :. From immanuel.scholz at tu-dresden.de Thu Aug 30 10:25:35 2007 From: immanuel.scholz at tu-dresden.de (Immanuel Scholz) Date: Thu, 30 Aug 2007 10:25:35 +0200 Subject: [py-dev] py.test: broken assert evaluate twice Message-ID: <46D67EFF.9060907@tu-dresden.de> Hi list, I am rather new to py library and just started using py.test. You may already have noticed, that the "assert" in magic-mode will evaluate its arguments (e.g. the parts of an equality check) more than once. This will not work, if the arguments have side effects, as in: i = 1 def foo(): global i i += 1 return i def test_foo(): assert foo() == 3 Is there a common solution to this, other than the annoying foo_result = foo() assert foo_result == 3 thingie? Maybe py.test could preemptive cache all calls to assert beforehand? Is this possible? Ciao, Imi. -- DF0E A04F 7063 69C5 A76B 7557 0A77 608F 9172 3535 From fijal at genesilico.pl Thu Aug 30 10:37:25 2007 From: fijal at genesilico.pl (Maciek Fijalkowski) Date: Thu, 30 Aug 2007 10:37:25 +0200 Subject: [py-dev] py.test: broken assert evaluate twice In-Reply-To: <46D67EFF.9060907@tu-dresden.de> References: <46D67EFF.9060907@tu-dresden.de> Message-ID: <46D681C5.9030402@genesilico.pl> Immanuel Scholz wrote: > Hi list, > > I am rather new to py library and just started using py.test. > > You may already have noticed, that the "assert" in magic-mode will > evaluate its arguments (e.g. the parts of an equality check) more than > once. This will not work, if the arguments have side effects, as in: > > i = 1 > def foo(): > global i > i += 1 > return i > > def test_foo(): > assert foo() == 3 > > > Is there a common solution to this, other than the annoying > > foo_result = foo() > assert foo_result == 3 > > thingie? Maybe py.test could preemptive cache all calls to assert > beforehand? Is this possible? > > > Ciao, Imi. > > It's sophisticated, as long as it's lazy - ie when assert works (is not broken) there is no magic at all. There are few solutions. One is the above solution, and we do this all the time in pypy. Other one is to use --nomagic, but you don't get all nice info out of that :) Cheers, fijal :. From immanuel.scholz at tu-dresden.de Thu Aug 30 10:58:56 2007 From: immanuel.scholz at tu-dresden.de (Immanuel Scholz) Date: Thu, 30 Aug 2007 10:58:56 +0200 Subject: [py-dev] py.test: broken assert evaluate twice In-Reply-To: <46D681C5.9030402@genesilico.pl> References: <46D67EFF.9060907@tu-dresden.de> <46D681C5.9030402@genesilico.pl> Message-ID: <46D686D0.9030002@tu-dresden.de> >> i = 1 >> def foo(): >> global i >> i += 1 >> return i >> >> def test_foo(): >> assert foo() == 3 >> >> >> Is there a common solution to this, other than the annoying >> >> foo_result = foo() >> assert foo_result == 3 >> >> thingie? Maybe py.test could preemptive cache all calls to assert >> beforehand? Is this possible? > > It's sophisticated, as long as it's lazy - ie when assert works (is not > broken) there is no magic at all. There are few solutions. One is the > above solution, and we do this all the time in pypy. Other one is to use > --nomagic, but you don't get all nice info out of that :) --nomagic isn't a cute solution either, as you get no information at all about the problem, and when people unaware of this run the test code without the option, they still get false information. I was thinking of a more comfortable solution. Is it possible in python to capture the assert call before it is made and cache the argument and then call to the original "assert"? This way, you don't have to remember to cache the call everytime yourself. The stuff is most annoying when testing functions that are some kind of generator and spits out another value on each call. Ciao, Imi. -- DF0E A04F 7063 69C5 A76B 7557 0A77 608F 9172 3535 From fijal at genesilico.pl Thu Aug 30 11:05:07 2007 From: fijal at genesilico.pl (Maciek Fijalkowski) Date: Thu, 30 Aug 2007 11:05:07 +0200 Subject: [py-dev] py.test: broken assert evaluate twice In-Reply-To: <46D686D0.9030002@tu-dresden.de> References: <46D67EFF.9060907@tu-dresden.de> <46D681C5.9030402@genesilico.pl> <46D686D0.9030002@tu-dresden.de> Message-ID: <46D68843.5020402@genesilico.pl> Immanuel Scholz wrote: >>> i = 1 >>> def foo(): >>> global i >>> i += 1 >>> return i >>> >>> def test_foo(): >>> assert foo() == 3 >>> >>> >>> Is there a common solution to this, other than the annoying >>> >>> foo_result = foo() >>> assert foo_result == 3 >>> >>> thingie? Maybe py.test could preemptive cache all calls to assert >>> beforehand? Is this possible? >>> >> It's sophisticated, as long as it's lazy - ie when assert works (is not >> broken) there is no magic at all. There are few solutions. One is the >> above solution, and we do this all the time in pypy. Other one is to use >> --nomagic, but you don't get all nice info out of that :) >> > > --nomagic isn't a cute solution either, as you get no information at all > about the problem, and when people unaware of this run the test code > without the option, they still get false information. > > I was thinking of a more comfortable solution. Is it possible in python > to capture the assert call before it is made and cache the argument and > then call to the original "assert"? This way, you don't have to remember > to cache the call everytime yourself. > > > The stuff is most annoying when testing functions that are some kind of > generator and spits out another value on each call. > > Ciao, Imi. > > I don't know :) I can help you dig into codebase if you would like to (btw, our primary channel is IRC for such things, as it's way easier, #pylib on irc.freenode.net) Cheers, fijal :.