Skip to content

marbles can't execute assertions that don't accept a msg argument #78

@thejunglejane

Description

@thejunglejane
  • marbles.core version: 0.9.4
  • marbles.mixins version: 0.9.4
  • Python version: 3.6.2
  • Operating System: Linux

Description

The unittest docs specify that:

All the assert methods accept a msg argument that, if specified, is used as the error message on failure (see also longMessage). Note that the msg keyword argument can be passed to assertRaises(), assertRaisesRegex(), assertWarns(), assertWarnsRegex() only when they are used as a context manager.

If these assertion methods are used as functions and not context managers, marbles will try it's best to find the msg argument, but because these methods don't accept a msg argument when they're used as functions, marbles will end up grabbing an argument that's intended for the callable and then the callable will be sad.

What I Did

I originally found this while trying to run unittest's own tests (specifically, the test_assertions.py tests) under marbles, but you can reproduce this specific bug with the following test case:

import unittest


class MyTestCase(unittest.TestCase):

    def test_foo(self):
        self.assertRaises(self.failureException,
                          self.assertAlmostEqual, 1.0000001, 1.0)


if __name__ == '__main__':
    unittest.main()

running this produces the following:

$ python -m marbles test.py
E
======================================================================
ERROR: test_foo (test.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 8, in test_foo
    self.assertAlmostEqual, 1.0000001, 1.0)
  File ".../lib/python3.6/site-packages/marbles/core/marbles.py", line 538, in wrapper
    return attr(*args, msg=annotation, **kwargs)
  File ".../lib/python3.6/unittest/case.py", line 733, in assertRaises
    return context.handle('assertRaises', args, kwargs)
  File ".../lib/python3.6/unittest/case.py", line 178, in handle
    callable_obj(*args, **kwargs)
  File ".../lib/python3.6/site-packages/marbles/core/marbles.py", line 538, in wrapper
    return attr(*args, msg=annotation, **kwargs)
TypeError: assertAlmostEqual() missing 1 required positional argument: 'second'

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (errors=1)

Additional context

This is related to a more general issue which is that marbles expects every assertion to accept a msg argument. If a non-unittest assertion (e.g., mixin assertion, a user-defined assertion, etc.) doesn't accept a msg argument, marbles won't be able to execute that assertion.

An example of this occurs in unittest's own tests. The TestLongMessage tests define a custom assertion, assertMessages that doesn't accept a msg argument. When a test method calls this assertion, marbles will dig into its arguments to try to pull out the note and msg arguments, and then try to make the assertion. In this case, one or two things could happen:

  1. marbles might grab something that is not a msg
  2. when marbles tries to make the assertion it will pass what it thought was the msg as a keyword argument to the original assertion, causing the original assertion to complain about getting an unexpected keyword argument

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions