[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-02-28 Thread Antoine Pitrou

Antoine Pitrou added the comment:

Just got bitten by this again. Context: I have a protocol which is sending JSON 
datagrams over the wire and I'm checking the sent data. I can't exactly check 
the JSON-encoded content since dict ordering is undefined. So right now I have 
to write:

self.assertEqual(q.transport.send.call_count, 1)
(dgram, target), _ = q.transport.send.call_args
self.assertEqual(target, (PEER, PORT))
self.assertEqual(json.loads(dgram), { ... })

Clumsy, clumsy (note that I am too lazy to add a check for the kwargs).

Would be much better if I could simply write:

dgram, = q.tranport.assert_called_once_with(mock.ANY, (PEER, PORT))
self.assertEqual(json.loads(dgram), { ... })

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-02-28 Thread Michael Foord

Michael Foord added the comment:

Note that there is nothing stopping you using the mock.ANY and 
assert_called_once_with style assert currently. You're making your assert more 
clumsy than it needs to be.

With my proposal you could write:

q.tranport.assert_called_once_with(mock.ANY, (PEER, PORT))
dgram = q.tranport.call_args.args[0]
self.assertEqual(json.loads(dgram),expected)

You could currently be doing:

q.tranport.assert_called_once_with(mock.ANY, (PEER, PORT))
dgram = q.tranport.call_args[0][0]
self.assertEqual(json.loads(dgram), expected)

--
assignee:  - michael.foord

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-02-28 Thread Antoine Pitrou

Antoine Pitrou added the comment:

I still have to do some tuple unpacking myself while assert_* already did it 
first. It can be tedious and error-prone (especially if there are several 
arguments to get).

If the assert methods returning something bothers you, how about introducing a 
new method match_call_with(...)?

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-02-28 Thread Michael Foord

Michael Foord added the comment:

Or create a JsonMatcher class that does it for you.


class JsonMatcher(object):
   def __init__(self, expected):
   self.expected = expected

   def __eq__(self, other):
   return json.loads(other) == self.expected

q.tranport.assert_called_once_with(JsonMatcher(expected), (PEER, PORT))

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-02-11 Thread Michael Foord

Michael Foord added the comment:

I still don't particularly like the idea of the assert_* methods returning 
something.

If the call args tuples had args and kwargs attributes, for which there are 
outstanding feature requests, then you could simply do:

my_mock(1, someobj(), bar=someotherobj())

foo = my_mock.call_args.args[1]
bar = my_mock.call_args.kwargs['bar']

By avoiding the extra step of tuple unpacking this is still nice and readable 
(IMO).

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-01-31 Thread Antoine Pitrou

Antoine Pitrou added the comment:

I think a better possibility would be to return an indexable match object (as 
bit like re match objects):

  my_mock(1, someobj(), bar=someotherobj()):
  match = my_mock.assert_called_with(
  1, ANY, bar=ANY)
  self.assertIsInstance(match[0], someobj)
  self.assertIsInstance(match['bar'], someotherobj)

 It's a *little* cumbersome, but not something I do very often and not
 much extra code. I'm not sure that having assert_called_with return
 objects is an intuitive API either. 

It has happened to me quite a bit in the latest days :-)
assert_called_with returning something may fall in the not very pure 
category, but we already have assertRaises and friends returning a context 
manager, and it has proved quite practical.

Also, your proposed workaround wouldn't work for assert_any_call().

Perhaps we should wait for other people to chime in.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-01-28 Thread Antoine Pitrou

New submission from Antoine Pitrou:

assert_called_with currently compares every argument for equality, which is not 
very practical when one of the arguments is a complex object, of which you only 
want to check certain properties.

It could be very nice if you could write e.g.:

from mock import Mock, PLACEHOLDER

...
my_mock(1, someobj(), bar=someotherobj()):
foo, bar = my_mock.assert_called_with(
1, PLACEHOLDER, bar=PLACEHOLDER)
self.assertIsInstance(bar, someobj)
self.assertIsInstance(foo, someotherobj)


(another name for PLACEHOLDER could be CAPTURE, regex-style :-))

--
messages: 180852
nosy: michael.foord, pitrou
priority: normal
severity: normal
status: open
title: assert_called_with could be more powerful if it allowed placeholders
type: enhancement
versions: Python 3.4

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-01-28 Thread Michael Foord

Michael Foord added the comment:

You mean like mock.ANY ?

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-01-28 Thread Michael Foord

Michael Foord added the comment:

Oh, you want the assert_called_with call to *return* the objects compared with 
the placeholder? 

Well, mock.ANY already exists and you can pull the arguments out for individual 
assertions using some_mock.call_args.

args, kwargs = some_mock.call_args

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-01-28 Thread Antoine Pitrou

Antoine Pitrou added the comment:

I'm noticing that with multiple ANY keyword arguments, the order in the result 
tuple is undefined. So perhaps ANY could be instantiable in those cases where 
disambiguation is required:

foo, bar = my_mock.assert_called_with(1, foo=ANY(0), bar=ANY(1))
self.assertIsInstance(bar, someobj)
self.assertIsInstance(foo, someotherobj)

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-01-28 Thread Antoine Pitrou

Antoine Pitrou added the comment:

Ah, well... I agree mock.ANY sounds cool :-)
Perhaps it could be mentioned in the docs for assert_etc.? Otherwise you only 
learn about it if you are masochistic enough to read the doc till the end :-)

 you can pull the arguments out for individual assertions using
 some_mock.call_args.

Yeah, but it's cumbersome and it boils down to doing the matching by hand, 
while assert_called_something already does it.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-01-28 Thread Michael Foord

Michael Foord added the comment:

Yes there are definitely room for documentation improvements.

And, yes - pulling the args out from some_mock.call_args boils down to doing 
the matching by hand. You only do it when you *want* to do the matching by 
hand.

Your use case I would write:

from mock import Mock, ANY

...
my_mock(1, someobj(), bar=someotherobj())
my_mock.assert_called_with(1, ANY, bar=ANY)

args, kwargs = my_mock.call_args
foo = args[1]
bar = kwargs['bar']

self.assertIsInstance(bar, someobj)
self.assertIsInstance(foo, someotherobj)


It's a *little* cumbersome, but not something I do very often and not much 
extra code. I'm not sure that having assert_called_with return objects is an 
intuitive API either. (And having to specify tuple indices in a call to ANY is 
a bit odd too.)

Custom matchers that do the comparison in their __eq__ method would be another 
possibility:

class IsInstance(object):
  def __init__(self, Type):
self.Type = Type
  def __eq__(self, other):
   return isinstance(other, self.Type)


my_mock.assert_called_with(1, IsInstance(someobj), bar=IsInstance(someotherobj))

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue17063] assert_called_with could be more powerful if it allowed placeholders

2013-01-28 Thread Ezio Melotti

Changes by Ezio Melotti ezio.melo...@gmail.com:


--
nosy: +ezio.melotti

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue17063
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com