gh-107713: Reduce usage of mocks in `test_clinic.py`
diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py
index f594e39a90546a..d13d8623f8093b 100644
--- a/Lib/test/test_clinic.py
+++ b/Lib/test/test_clinic.py
@@ -7,7 +7,6 @@
 from test.support.os_helper import TESTFN, unlink
 from textwrap import dedent
 from unittest import TestCase
-import collections
 import contextlib
 import inspect
 import os.path
@@ -21,6 +20,13 @@
     from clinic import DSLParser
 
 
+def _make_clinic(*, filename='clinic_tests'):
+    clang = clinic.CLanguage(None)
+    c = clinic.Clinic(clang, filename=filename)
+    c.block_parser = clinic.BlockParser('', clang)
+    return c
+
+
 def _expect_failure(tc, parser, code, errmsg, *, filename=None, lineno=None):
     """Helper for the parser tests.
 
@@ -41,81 +47,6 @@ def _expect_failure(tc, parser, code, errmsg, *, filename=None, lineno=None):
         tc.assertEqual(cm.exception.lineno, lineno)
 
 
-class FakeConverter:
-    def __init__(self, name, args):
-        self.name = name
-        self.args = args
-
-
-class FakeConverterFactory:
-    def __init__(self, name):
-        self.name = name
-
-    def __call__(self, name, default, **kwargs):
-        return FakeConverter(self.name, kwargs)
-
-
-class FakeConvertersDict:
-    def __init__(self):
-        self.used_converters = {}
-
-    def get(self, name, default):
-        return self.used_converters.setdefault(name, FakeConverterFactory(name))
-
-c = clinic.Clinic(language='C', filename = "file")
-
-class FakeClinic:
-    def __init__(self):
-        self.converters = FakeConvertersDict()
-        self.legacy_converters = FakeConvertersDict()
-        self.language = clinic.CLanguage(None)
-        self.filename = "clinic_tests"
-        self.destination_buffers = {}
-        self.block_parser = clinic.BlockParser('', self.language)
-        self.modules = collections.OrderedDict()
-        self.classes = collections.OrderedDict()
-        clinic.clinic = self
-        self.name = "FakeClinic"
-        self.line_prefix = self.line_suffix = ''
-        self.destinations = {}
-        self.add_destination("block", "buffer")
-        self.add_destination("file", "buffer")
-        self.add_destination("suppress", "suppress")
-        d = self.destinations.get
-        self.field_destinations = collections.OrderedDict((
-            ('docstring_prototype', d('suppress')),
-            ('docstring_definition', d('block')),
-            ('methoddef_define', d('block')),
-            ('impl_prototype', d('block')),
-            ('parser_prototype', d('suppress')),
-            ('parser_definition', d('block')),
-            ('impl_definition', d('block')),
-        ))
-        self.functions = []
-
-    def get_destination(self, name):
-        d = self.destinations.get(name)
-        if not d:
-            sys.exit("Destination does not exist: " + repr(name))
-        return d
-
-    def add_destination(self, name, type, *args):
-        if name in self.destinations:
-            sys.exit("Destination already exists: " + repr(name))
-        self.destinations[name] = clinic.Destination(name, type, self, *args)
-
-    def is_directive(self, name):
-        return name == "module"
-
-    def directive(self, name, args):
-        self.called_directives[name] = args
-
-    _module_and_class = clinic.Clinic._module_and_class
-
-    def __repr__(self):
-        return "<FakeClinic object>"
-
-
 class ClinicWholeFileTest(TestCase):
     maxDiff = None
 
@@ -124,7 +55,7 @@ def expect_failure(self, raw, errmsg, *, filename=None, lineno=None):
                         filename=filename, lineno=lineno)
 
     def setUp(self):
-        self.clinic = clinic.Clinic(clinic.CLanguage(None), filename="test.c")
+        self.clinic = _make_clinic(filename="test.c")
 
     def test_eol(self):
         # regression test:
@@ -848,7 +779,7 @@ def test_clinic_1(self):
 class ClinicParserTest(TestCase):
 
     def parse(self, text):
-        c = FakeClinic()
+        c = _make_clinic()
         parser = DSLParser(c)
         block = clinic.Block(text)
         parser.parse(block)
@@ -872,7 +803,7 @@ def checkDocstring(self, fn, expected):
                          dedent(expected).strip())
 
     def test_trivial(self):
-        parser = DSLParser(FakeClinic())
+        parser = DSLParser(_make_clinic())
         block = clinic.Block("""
             module os
             os.access
@@ -1119,7 +1050,7 @@ def test_cloning_nonexistent_function_correctly_fails(self):
         with support.captured_stderr() as stderr:
             self.expect_failure(block, err, lineno=0)
         expected_debug_print = dedent("""\
-            cls=None, module=<FakeClinic object>, existing='fooooooooooooooooo'
+            cls=None, module=<clinic.Clinic object>, existing='fooooooooooooooooo'
             (cls or module).functions=[]
         """)
         stderr = stderr.getvalue()
@@ -1740,8 +1671,7 @@ def test_indent_stack_illegal_outdent(self):
         self.expect_failure(block, err)
 
     def test_directive(self):
-        c = FakeClinic()
-        parser = DSLParser(c)
+        parser = DSLParser(_make_clinic())
         parser.flag = False
         parser.directives['setflag'] = lambda : setattr(parser, 'flag', True)
         block = clinic.Block("setflag")
@@ -3147,22 +3077,24 @@ def test_Block_repr(self):
         self.assertEqual(repr(block3), expected_repr_3)
 
     def test_Destination_repr(self):
+        c = _make_clinic()
+
         destination = clinic.Destination(
-            "foo", type="file", clinic=FakeClinic(), args=("eggs",)
+            "foo", type="file", clinic=c, args=("eggs",)
         )
         self.assertEqual(
             repr(destination), "<clinic.Destination 'foo' type='file' file='eggs'>"
         )
 
-        destination2 = clinic.Destination("bar", type="buffer", clinic=FakeClinic())
+        destination2 = clinic.Destination("bar", type="buffer", clinic=c)
         self.assertEqual(repr(destination2), "<clinic.Destination 'bar' type='buffer'>")
 
     def test_Module_repr(self):
-        module = clinic.Module("foo", FakeClinic())
+        module = clinic.Module("foo", _make_clinic())
         self.assertRegex(repr(module), r"<clinic.Module 'foo' at \d+>")
 
     def test_Class_repr(self):
-        cls = clinic.Class("foo", FakeClinic(), None, 'some_typedef', 'some_type_object')
+        cls = clinic.Class("foo", _make_clinic(), None, 'some_typedef', 'some_type_object')
         self.assertRegex(repr(cls), r"<clinic.Class 'foo' at \d+>")
 
     def test_FunctionKind_repr(self):
@@ -3176,7 +3108,7 @@ def test_FunctionKind_repr(self):
     def test_Function_and_Parameter_reprs(self):
         function = clinic.Function(
             name='foo',
-            module=FakeClinic(),
+            module=_make_clinic(),
             cls=None,
             c_basename=None,
             full_name='foofoo',
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index 4dfe90b314f543..2bed98c23674e0 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -2424,6 +2424,9 @@ def _module_and_class(
 
         return module, cls
 
+    def __repr__(self) -> str:
+        return "<clinic.Clinic object>"
+
 
 def parse_file(
         filename: str,


<!-- gh-issue-number: gh-107713 -->
* Issue: gh-107713
<!-- /gh-issue-number -->

Fixes #107713