Earlier  
Posted Nick Remark
#openstack-nova - 2019-10-02
13:57:29 dansmith efried: yes it does
13:57:31 dansmith efried: run it
13:57:37 efried oic
13:57:44 mriedem note that mock.patch(wraps=...) does that as well
13:57:45 dansmith gibi: that runs the original
13:58:04 dansmith ah, didn't know about wraps
13:58:12 gibi dansmith: let me try that with a bound method
13:58:17 mriedem wraps is kind of weird to use
13:58:20 mriedem not documented very well
13:58:58 efried What spy does is allow you to keep track of things per invocation of the wrapped method, which wraps= doesn't
13:59:29 efried also selectively change the behavior
13:59:42 efried like "run normally the first time, raise the second time"
13:59:54 dansmith I don't see how it's different from side_effect
14:04:21 gibi dansmith: side_effect is not good for calling the original if the original is a bound method http://paste.openstack.org/show/780754/
14:05:02 dansmith gibi: that's because you're mocking the class not the object
14:05:15 dansmith I think you're just using your spy in a different order
14:05:27 dansmith if you mock.patch.object(a) I think you'll be fine
14:06:10 gibi dansmith: but in the functional test when we mock we tend not to have easy access to the instantiated objects just the classes
14:06:35 dansmith in that one scenario you mean, but not necessarily as a general rule
14:07:24 dansmith efried's use of spy in the patch above that does not seem to be very clean to me, especially for a supposed functional test
14:07:34 gibi dansmith: my goal is to want to get rid of (or contain) the scope magic and the original function handling in cases like https://github.com/openstack/nova/blob/bf37bec80baa527ac013dfaa7480ef2761ed2cb9/nova/tests/functional/regressions/test_bug_1843090.py#L100
14:07:59 dansmith but anyway, not saying it's not useful, it just seems like in a lot of cases, you could get away with base mock stuff instead of having to learn a new convention
14:08:11 efried oh, yeah, in the vast majority of cases
14:08:33 gibi spy is not a replacement for mock. There are cases where I think mock is hard to use to achive the same thing
14:08:43 gibi like the funct test I linket above
14:08:52 dansmith gibi: understand. using side_effect to provide a sequence of run,fail is more conventional than what either the old or new code in that patch is doing
14:09:02 dansmith assuming you can hook at the right spot to mock the object itself
14:09:40 efried dansmith: I don't think you can use side_effect to run,fail
14:09:46 dansmith efried: of course you can
14:09:53 dansmith efried: provide it a list and it will iterate on each call
14:09:55 efried because when you pass an iterable to side_effect, it's return values, not callables.
14:10:00 dansmith nope
14:10:07 dansmith return_value behaves like that, side_effect does not
14:10:28 efried side_effect=one_thing calls one_thing
14:10:28 efried side_effect=[one, two] *returns* one followed by two
14:10:33 gibi dansmith: btw, mocking f through the instance doesn't work either http://paste.openstack.org/show/780755/
14:10:54 dansmith efried: "If side_effect is an iterable then each call to the mock will return the next value from the iterable."
14:11:01 efried ^
14:11:56 dansmith efried: https://pastebin.com/bLpt6Skz
14:12:22 dansmith gibi: it's all about calling convention, it's tricky and magical, but you're not doing anything different other than the ordering
14:12:46 efried dansmith: yup, that didn't print "Foo ran 1"
14:13:12 efried try to get it to do that the first time, and raise the second
14:13:13 gibi dansmith: tell me how can I call the original with side_effect if the original is a bound method because I failed to find a way
14:13:26 efried gibi: you can't
14:13:27 dansmith efried: it printed 1, my local env has a different foo
14:14:13 dansmith efried: wait, what are you arguing? that it didn't run foo? I didn't ask it to
14:14:22 efried I know. And you can't.
14:14:36 efried that's what spy helps with
14:14:54 gibi exaclty what efried is asking is what I'm after. having the original function is called while spying on the call
14:15:07 dansmith ah, I see what you mean.. a lambda in the list will solve that
14:15:20 gibi dansmith: no, the lambda would be returned, not called
14:15:29 efried ^
14:15:38 dansmith gibi: having the original called is what side_effect=callable will do, but the list, fine fine, I see
14:16:20 gibi dansmith: but I cannot do that^^ if the original is a bound method as mock does not pass proper arglist to the callable
14:16:42 dansmith you guys seem to be describing a world where spy will make it easier to not write terrible tests like what efried is adding (and what he replaced), yet he's using spy to (if called once, then explode)
14:16:56 efried what did I write?
14:17:10 dansmith efried: this: https://review.opendev.org/#/c/685950/3/nova/tests/functional/regressions/test_bug_1843090.py
14:17:40 efried gibi gets credit for those
14:17:53 efried I think
14:17:55 dansmith oh sorry, I thought you were commenting on your own
14:18:37 dansmith I should have provided a url instead of a name :)
14:18:38 gibi dansmith: I want to make the test in test_bug_1843090.py better with spy. If there is other way to make it better then I'm open to suggestion
14:19:07 dansmith gibi: okay, but you're not in that change, right? you're still counting calls and failing once it's been called
14:19:19 dansmith and doing gross stuff like mangling the original object to tell if you've been called twice
14:19:59 dansmith so where is your call,fail bit you said was easy with spy?
14:20:00 gibi dansmith: we need the logic like first call fails to trigger a re-schedule but the second succeds so that the re-schedule succeeds.
14:20:01 artom Actually yeah
14:20:19 dansmith fine, where is your fail,call ? :)
14:20:20 gibi dansmith: is there a nicer way to code that?
14:20:26 artom What we're doing in https://review.opendev.org/#/c/685950/3/nova/tests/functional/regressions/test_bug_1843090.py is exactly what we said we shouldn't do in https://review.opendev.org/#/c/685950/2/nova/tests/functional/compute/test_live_migration.py@23
14:21:13 dansmith gibi: well, for one thing you should keep track of your mock calls outside of the runtime objects you're handling
14:21:37 efried dansmith: Checking the actual mock's call_count is hard because you have to define the method before you create the mock before you define the method, but you have to reference the mock from within the method.
14:21:44 dansmith gibi: point being I'm not sure what spy is making nicer about that test because it seems like the same ickiness, but with a different calling convention
14:22:03 gibi dansmith: it hides the scope magic efried is just described
14:22:15 gibi dansmith: it automates the call to the original function
14:22:16 dansmith efried: everywhere else we keep a list above the scope and chuck things into there inside the handler
14:22:36 dansmith gibi: so it saves the one line of saving a reference to the original method?
14:22:50 gibi dansmith: and it hides the outer scope list
14:23:14 dansmith but replaces it with the terrible hack of modifying the runtime objects instead of keeping that fully within the test!
14:23:17 efried and when there are multiple calls to the same method nested inside whatever's happening inside the context manager, it gives you a way to introspect them individually
14:23:31 gibi dansmith: and it remembers that we have to use new= instead of side_effect if the mocked function is bound method
14:23:55 efried with mock.patch:
14:23:56 efried do_thing()
14:23:56 efried do_thing calls foo() N times with different args or whatever
14:23:57 openstackgerrit Matt Riedemann proposed openstack/nova master: Add functional regression test for migrate part of bug 1781286 https://review.opendev.org/686017
14:23:57 openstack bug 1781286 in OpenStack Compute (nova) "CantStartEngineError in cell conductor during reschedule - get_host_availability_zone up-call" [Medium,In progress] https://launchpad.net/bugs/1781286 - Assigned to Matt Riedemann (mriedem)
14:23:57 openstackgerrit Matt Riedemann proposed openstack/nova master: Add Selection.availability_zone field https://review.opendev.org/685807
14:23:57 openstackgerrit Matt Riedemann proposed openstack/nova master: Set Instance AZ from Selection AZ during build reschedule https://review.opendev.org/686047
14:23:57 openstackgerrit Matt Riedemann proposed openstack/nova master: Set Instance AZ from Selection AZ during migrate reschedule https://review.opendev.org/686050
14:23:58 openstackgerrit Matt Riedemann proposed openstack/nova master: Update cells v2 up-call caveats doc https://review.opendev.org/686053
14:24:42 efried dansmith: I also suggested a way we don't have to do the
14:24:42 efried spy.claim_calls_on_node = getattr(spy, 'claim_calls_on_node', [])
14:24:42 efried thing, which puts creation of the tracker container back in the hands of the caller.
14:25:07 efried same #LOC, just a little more scrutable
14:25:13 dansmith efried: yes, initializing that "context" elsewhere would be a lot better
14:25:59 dansmith anyway, it seems to do a lot for you and gibi, that's all that matters. it's something else I have to learn to comprehend the test, but...
14:26:09 efried gibi: I can work that ^ up if you like, at least for demonstration purposes.
14:26:19 efried maybe it'll read more intuitively to dansmith
14:26:59 dansmith no, not more intuitively, it'll just make the handler less gross
14:28:37 mriedem i found out yesterday that we patch mock.patch globally using something in oslotest for fixing the autospec'ing stuff - what claudiub worked on a long time ago. i saw those changes merge but didn't realize we were patching the mock library.

Earlier   Later