Skip to content

unittest: Detect duplicate method names #105560

Closed as not planned
Closed as not planned
@vstinner

Description

@vstinner

Currently, when an unittest.TestCase has two test methods with the same name, only the second one is run: the first one is silently ignored. In the past, the Python test suite had many bugs like that: see issue #60283. I just found a new bug today in test_sqlite3: issue #105557.

It would be nice to automatically detect when a test method is redefined. The problem is to avoid false alarms on method redefined on purpose: right now, I don't know if there are legit use cases like that.

Here is a prototype:

import inspect
import warnings

class MyDict(dict):
    def __init__(self, class_name):
        self.class_name = class_name

    def __setitem__(self, name, value):
        # TestLoader.testMethodPrefix = 'test'
        if name.startswith('test'):
            try:
                old_value = self[name]
            except KeyError:
                pass
            else:
                if inspect.isfunction(old_value):
                    warnings.warn(f"BUG: {self.class_name}.{name}() method redefined", stacklevel=2)
        dict.__setitem__(self, name, value)

class MyMetaClass(type):
    @classmethod
    def __prepare__(metacls, class_name, bases, **kwds):
        return MyDict(class_name)

class TestCase(metaclass=MyMetaClass):
    pass

class Tests(TestCase):
    def __init__(self):
        self.attr = 1
        self.attr = 2

    def test_bug(self):  # first defintion
        pass

    def test_bug(self):  # second definion
        pass

class RealTests(Tests):
    def test_bug(self):  # implementation
        print("run tests")


tests = RealTests()

Output:

poc.py:36: UserWarning: BUG: Tests.test_bug() method redefined
  def test_bug(self):  # second definion

It only emits a warning on the second Tests.test_bug() method definition. It doesn't emit a warning when RealTests redefines test_bug(): is it a legit use case to override an "abstract" test method of a "base" test case class? This case can also be detected if needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions