I’ve implemented a version of the Verifier class in many test scripts, so +1 to its inclusion. I’ve never needed something like your IsInstance, however.
pytest wants to display LHS and RHS and highlight their diff on failure of assert A == B, where a custom repr may help, but I don’t think that applies when using mock.assert_called_with.
import unittest
from unittest.mock import MagicMock
class Test(unittest.TestCase):
def runTest(self):
mock = MagicMock()
mock.func(1)
mock.func.assert_called_once()
self.assertIsInstance(mock.func.call_args[0][0], int)
self.assertTrue(mock.func.call_args[0][0] < 10)
While the proposal does simplify the existing approach, I wonder if the IsInstance test on a call argument is special or used often enough to justify it as a dedicated helper class. It seems to me that we should offer either a dedicated helper class for every equivalent assert* method, or just a Verifier helper class to minimize the burden of support with just a generalized class.
I could definitely see a world where we just add Verifier which makes it easy to use isinstance() via a lambda or similar to get the same behavior without needing IsInstance.
For me it winds up being when I have a type that doesn’t define __eq__(). Previously I wind up using ANY or manually going through mock_calls then args/kwargs to find and check the specific argument I’m couldn’t easily check.
For me I would use IsInstance for cases where I just want to be sure the right type was passed (and not something like None). I would use Verifier for slightly more complex cases, probably alongside a lambda to verify short things like: “The arg was smaller than 5”.
I’ve also made a number of one off Verifier-like classes when the type does have __eq__(), but I only care about some of the values or a value might be hard to control. For example: an integration test where the database is automatically setting a created_at field. Most of the time I want to confirm that all the fields of the dataclass have the correct value, but am less interested in the exact value of the one datatime instance.
These both fail against types that already know how to compare themselves against arbitrary types, preventing IsInstance.__eq__ or Verifier.__eq__ from being called at all.
Do you have an example? These follow very similar logic to ANY in unittest.mock today. I thought it does comparisons with the thing in the assert call on the correct side so it’s __eq__ gets called.
No I think when I ran my test, I was careless about what got passed to mock.func and IsInstance, and interpreted the expected error as a false positive.
I think dirty_equals.IsInstance is exactly your proposed IsInstance class, while dirty_equals.FunctionCheck is exactly your proposed Verifier class, so the usage with mock.assert_called_once_with would be the same as that of your proposal.
Oh wow you’re right. I can definitely use this where needed. I think there could be value in something like this being an included battery, but this library works well for me.