Repository: twisted/twisted

Issue:
type annotate more tests
**Is your feature request related to a problem? Please describe.**
tests are pretty easy to type annotate just lots of manual `-> None:`

**Describe the solution you'd like**
type annotate some more tests


Discussion:

Resolving patch:
diff --git a/src/twisted/_threads/_team.py b/src/twisted/_threads/_team.py
--- a/src/twisted/_threads/_team.py
+++ b/src/twisted/_threads/_team.py
@@ -6,7 +6,7 @@
 Implementation of a L{Team} of workers; a thread-pool that can allocate work to
 workers.
 """
-
+from __future__ import annotations
 
 from collections import deque
 from typing import Callable, Optional, Set
diff --git a/src/twisted/web/http.py b/src/twisted/web/http.py
--- a/src/twisted/web/http.py
+++ b/src/twisted/web/http.py
@@ -108,7 +108,7 @@
 import time
 import warnings
 from io import BytesIO
-from typing import AnyStr, Callable, Optional, Tuple
+from typing import AnyStr, Callable, List, Optional, Tuple
 from urllib.parse import (
     ParseResultBytes,
     unquote_to_bytes as unquote,
@@ -835,7 +835,7 @@ def __init__(self, channel, queued=_QUEUED_SENTINEL):
         @param queued: (deprecated) are we in the request queue, or can we
             start writing to the transport?
         """
-        self.notifications = []
+        self.notifications: List[Deferred[None]] = []
         self.channel = channel
 
         # Cache the client and server information, we'll need this
@@ -1098,7 +1098,7 @@ def getCookie(self, key):
         """
         return self.received_cookies.get(key)
 
-    def notifyFinish(self):
+    def notifyFinish(self) -> Deferred[None]:
         """
         Notify when the response to this request has finished.
 


Test patch:
diff --git a/src/twisted/conch/test/test_address.py b/src/twisted/conch/test/test_address.py
--- a/src/twisted/conch/test/test_address.py
+++ b/src/twisted/conch/test/test_address.py
@@ -4,7 +4,9 @@
 """
 Tests for L{SSHTransportAddrress} in ssh/address.py
 """
+from __future__ import annotations
 
+from typing import Callable
 
 from twisted.conch.ssh.address import SSHTransportAddress
 from twisted.internet.address import IPv4Address
@@ -19,7 +21,7 @@ class SSHTransportAddressTests(unittest.TestCase, AddressTestCaseMixin):
     basic functionality of that class (string representation, comparison, &c).
     """
 
-    def _stringRepresentation(self, stringFunction):
+    def _stringRepresentation(self, stringFunction: Callable[[object], str]) -> None:
         """
         The string representation of C{SSHTransportAddress} should be
         "SSHTransportAddress(<stringFunction on address>)".
@@ -29,14 +31,14 @@ def _stringRepresentation(self, stringFunction):
         addressValue = stringFunction(addr.address)
         self.assertEqual(stringValue, "SSHTransportAddress(%s)" % addressValue)
 
-    def buildAddress(self):
+    def buildAddress(self) -> SSHTransportAddress:
         """
         Create an arbitrary new C{SSHTransportAddress}.  A new instance is
         created for each call, but always for the same address.
         """
         return SSHTransportAddress(IPv4Address("TCP", "127.0.0.1", 22))
 
-    def buildDifferentAddress(self):
+    def buildDifferentAddress(self) -> SSHTransportAddress:
         """
         Like C{buildAddress}, but with a different fixed address.
         """
diff --git a/src/twisted/conch/test/test_window.py b/src/twisted/conch/test/test_window.py
--- a/src/twisted/conch/test/test_window.py
+++ b/src/twisted/conch/test/test_window.py
@@ -1,6 +1,9 @@
 """
 Tests for the insults windowing module, L{twisted.conch.insults.window}.
 """
+from __future__ import annotations
+
+from typing import Callable
 
 from twisted.conch.insults.window import ScrolledArea, TextOutput, TopWindow
 from twisted.trial.unittest import TestCase
@@ -11,13 +14,13 @@ class TopWindowTests(TestCase):
     Tests for L{TopWindow}, the root window container class.
     """
 
-    def test_paintScheduling(self):
+    def test_paintScheduling(self) -> None:
         """
         Verify that L{TopWindow.repaint} schedules an actual paint to occur
         using the scheduling object passed to its initializer.
         """
-        paints = []
-        scheduled = []
+        paints: list[None] = []
+        scheduled: list[Callable[[], object]] = []
         root = TopWindow(lambda: paints.append(None), scheduled.append)
 
         # Nothing should have happened yet.
@@ -53,7 +56,7 @@ class ScrolledAreaTests(TestCase):
     another widget and can reposition that viewport using scrollbars.
     """
 
-    def test_parent(self):
+    def test_parent(self) -> None:
         """
         The parent of the widget passed to L{ScrolledArea} is set to a new
         L{Viewport} created by the L{ScrolledArea} which itself has the
diff --git a/src/twisted/internet/test/test_defer_await.py b/src/twisted/internet/test/test_defer_await.py
--- a/src/twisted/internet/test/test_defer_await.py
+++ b/src/twisted/internet/test/test_defer_await.py
@@ -8,6 +8,8 @@
 
 import types
 
+from typing_extensions import NoReturn
+
 from twisted.internet.defer import (
     Deferred,
     ensureDeferred,
@@ -31,26 +33,26 @@ class AwaitTests(TestCase):
     Tests for using Deferreds in conjunction with PEP-492.
     """
 
-    def test_awaitReturnsIterable(self):
+    def test_awaitReturnsIterable(self) -> None:
         """
         C{Deferred.__await__} returns an iterable.
         """
-        d = Deferred()
+        d: Deferred[None] = Deferred()
         awaitedDeferred = d.__await__()
         self.assertEqual(awaitedDeferred, iter(awaitedDeferred))
 
-    def test_deferredFromCoroutine(self):
+    def test_deferredFromCoroutine(self) -> None:
         """
         L{Deferred.fromCoroutine} will turn a coroutine into a L{Deferred}.
         """
 
-        async def run():
+        async def run() -> str:
             d = succeed("bar")
             await d
             res = await run2()
             return res
 
-        async def run2():
+        async def run2() -> str:
             d = succeed("foo")
             res = await d
             return res
@@ -67,13 +69,13 @@ async def run2():
         res = self.successResultOf(d)
         self.assertEqual(res, "foo")
 
-    def test_basic(self):
+    def test_basic(self) -> None:
         """
         L{Deferred.fromCoroutine} allows a function to C{await} on a
         L{Deferred}.
         """
 
-        async def run():
+        async def run() -> str:
             d = succeed("foo")
             res = await d
             return res
@@ -82,12 +84,12 @@ async def run():
         res = self.successResultOf(d)
         self.assertEqual(res, "foo")
 
-    def test_basicEnsureDeferred(self):
+    def test_basicEnsureDeferred(self) -> None:
         """
         L{ensureDeferred} allows a function to C{await} on a L{Deferred}.
         """
 
-        async def run():
+        async def run() -> str:
             d = succeed("foo")
             res = await d
             return res
@@ -96,13 +98,13 @@ async def run():
         res = self.successResultOf(d)
         self.assertEqual(res, "foo")
 
-    def test_exception(self):
+    def test_exception(self) -> None:
         """
         An exception in a coroutine scheduled with L{Deferred.fromCoroutine}
         will cause the returned L{Deferred} to fire with a failure.
         """
 
-        async def run():
+        async def run() -> NoReturn:
             d = succeed("foo")
             await d
             raise ValueError("Oh no!")
@@ -112,19 +114,19 @@ async def run():
         self.assertEqual(type(res.value), ValueError)
         self.assertEqual(res.value.args, ("Oh no!",))
 
-    def test_synchronousDeferredFailureTraceback(self):
+    def test_synchronousDeferredFailureTraceback(self) -> None:
         """
         When a Deferred is awaited upon that has already failed with a Failure
         that has a traceback, both the place that the synchronous traceback
         comes from and the awaiting line are shown in the traceback.
         """
 
-        def raises():
+        def raises() -> None:
             raise SampleException()
 
         it = maybeDeferred(raises)
 
-        async def doomed():
+        async def doomed() -> None:
             return await it
 
         failure = self.failureResultOf(Deferred.fromCoroutine(doomed()))
@@ -132,22 +134,22 @@ async def doomed():
         self.assertIn(", in doomed\n", failure.getTraceback())
         self.assertIn(", in raises\n", failure.getTraceback())
 
-    def test_asyncDeferredFailureTraceback(self):
+    def test_asyncDeferredFailureTraceback(self) -> None:
         """
         When a Deferred is awaited upon that later fails with a Failure that
         has a traceback, both the place that the synchronous traceback comes
         from and the awaiting line are shown in the traceback.
         """
 
-        def returnsFailure():
+        def returnsFailure() -> Failure:
             try:
                 raise SampleException()
             except SampleException:
                 return Failure()
 
-        it = Deferred()
+        it: Deferred[None] = Deferred()
 
-        async def doomed():
+        async def doomed() -> None:
             return await it
 
         started = Deferred.fromCoroutine(doomed())
@@ -157,7 +159,7 @@ async def doomed():
         self.assertIn(", in doomed\n", failure.getTraceback())
         self.assertIn(", in returnsFailure\n", failure.getTraceback())
 
-    def test_twoDeep(self):
+    def test_twoDeep(self) -> None:
         """
         A coroutine scheduled with L{Deferred.fromCoroutine} that awaits a
         L{Deferred} suspends its execution until the inner L{Deferred} fires.
@@ -165,19 +167,19 @@ def test_twoDeep(self):
         reactor = Clock()
         sections = []
 
-        async def runone():
+        async def runone() -> str:
             sections.append(2)
-            d = Deferred()
+            d: Deferred[int] = Deferred()
             reactor.callLater(1, d.callback, 2)
             await d
             sections.append(3)
             return "Yay!"
 
-        async def run():
+        async def run() -> str:
             sections.append(1)
             result = await runone()
             sections.append(4)
-            d = Deferred()
+            d: Deferred[int] = Deferred()
             reactor.callLater(1, d.callback, 1)
             await d
             sections.append(5)
@@ -200,12 +202,12 @@ async def run():
         res = self.successResultOf(d)
         self.assertEqual(res, "Yay!")
 
-    def test_reraise(self):
+    def test_reraise(self) -> None:
         """
         Awaiting an already failed Deferred will raise the exception.
         """
 
-        async def test():
+        async def test() -> int:
             try:
                 await fail(ValueError("Boom"))
             except ValueError as e:
@@ -216,16 +218,16 @@ async def test():
         res = self.successResultOf(Deferred.fromCoroutine(test()))
         self.assertEqual(res, 1)
 
-    def test_chained(self):
+    def test_chained(self) -> None:
         """
         Awaiting a paused & chained Deferred will give the result when it has
         one.
         """
         reactor = Clock()
 
-        async def test():
-            d = Deferred()
-            d2 = Deferred()
+        async def test() -> None:
+            d: Deferred[None] = Deferred()
+            d2: Deferred[None] = Deferred()
             d.addCallback(lambda ignored: d2)
 
             d.callback(None)
diff --git a/src/twisted/names/test/test_tap.py b/src/twisted/names/test/test_tap.py
--- a/src/twisted/names/test/test_tap.py
+++ b/src/twisted/names/test/test_tap.py
@@ -22,7 +22,7 @@ class OptionsTests(SynchronousTestCase):
     are parsed.
     """
 
-    def test_malformedSecondary(self):
+    def test_malformedSecondary(self) -> None:
         """
         If the value supplied for an I{--secondary} option does not provide a
         server IP address, optional port number, and domain name,
@@ -40,7 +40,7 @@ def test_malformedSecondary(self):
             ["--secondary", "1.2.3.4:hello/example.com"],
         )
 
-    def test_secondary(self):
+    def test_secondary(self) -> None:
         """
         An argument of the form C{"ip/domain"} is parsed by L{Options} for the
         I{--secondary} option and added to its list of secondaries, using the
@@ -50,7 +50,7 @@ def test_secondary(self):
         options.parseOptions(["--secondary", "1.2.3.4/example.com"])
         self.assertEqual([(("1.2.3.4", PORT), ["example.com"])], options.secondaries)
 
-    def test_secondaryExplicitPort(self):
+    def test_secondaryExplicitPort(self) -> None:
         """
         An argument of the form C{"ip:port/domain"} can be used to specify an
         alternate port number for which to act as a secondary.
@@ -59,7 +59,7 @@ def test_secondaryExplicitPort(self):
         options.parseOptions(["--secondary", "1.2.3.4:5353/example.com"])
         self.assertEqual([(("1.2.3.4", 5353), ["example.com"])], options.secondaries)
 
-    def test_secondaryAuthorityServices(self):
+    def test_secondaryAuthorityServices(self) -> None:
         """
         After parsing I{--secondary} options, L{Options} constructs a
         L{SecondaryAuthorityService} instance for each configured secondary.
@@ -83,7 +83,7 @@ def test_secondaryAuthorityServices(self):
         self.assertEqual(secondary.primary, "1.2.3.5")
         self.assertEqual(secondary._port, 5354)
 
-    def test_recursiveConfiguration(self):
+    def test_recursiveConfiguration(self) -> None:
         """
         Recursive DNS lookups, if enabled, should be a last-resort option.
         Any other lookup method (cache, local lookup, etc.) should take
@@ -107,12 +107,11 @@ def test_recursiveConfiguration(self):
         # there should be no others (and it leaving a callLater lying about
         # should rightly cause the test to fail).
         if platform.getType() != "posix":
-
             # We want the delayed calls on the reactor, which should be all of
             # ours from the threaded resolver cleanup
             from twisted.internet import reactor
 
-            for x in reactor._newTimedCalls:
+            for x in reactor._newTimedCalls:  # type: ignore[attr-defined]
                 self.assertEqual(x.func.__func__, ThreadedResolver._cleanup)
                 x.cancel()
 
diff --git a/src/twisted/positioning/test/test_base.py b/src/twisted/positioning/test/test_base.py
--- a/src/twisted/positioning/test/test_base.py
+++ b/src/twisted/positioning/test/test_base.py
@@ -3,6 +3,8 @@
 """
 Test cases for positioning primitives.
 """
+from __future__ import annotations
+
 from zope.interface import verify
 
 from twisted.positioning import base
@@ -16,7 +18,7 @@ class AngleTests(TestCase):
     Tests for the L{twisted.positioning.base.Angle} class.
     """
 
-    def test_empty(self):
+    def test_empty(self) -> None:
         """
         The repr of an empty angle says that is of unknown type and unknown
         value.
@@ -24,7 +26,7 @@ def test_empty(self):
         a = base.Angle()
         self.assertEqual("<Angle of unknown type (unknown value)>", repr(a))
 
-    def test_variation(self):
+    def test_variation(self) -> None:
         """
         The repr of an empty variation says that it is a variation of unknown
         value.
@@ -32,7 +34,7 @@ def test_variation(self):
         a = base.Angle(angleType=Angles.VARIATION)
         self.assertEqual("<Variation (unknown value)>", repr(a))
 
-    def test_unknownType(self):
+    def test_unknownType(self) -> None:
         """
         The repr of an angle of unknown type but a given value displays that
         type and value in its repr.
@@ -40,7 +42,7 @@ def test_unknownType(self):
         a = base.Angle(1.0)
         self.assertEqual("<Angle of unknown type (1.0 degrees)>", repr(a))
 
-    def test_bogusType(self):
+    def test_bogusType(self) -> None:
         """
         Trying to create an angle with a bogus type raises C{ValueError}.
         """
@@ -52,7 +54,7 @@ class HeadingTests(TestCase):
     Tests for the L{twisted.positioning.base.Heading} class.
     """
 
-    def test_simple(self):
+    def test_simple(self) -> None:
         """
         Tests that a simple heading has a value in decimal degrees, which is
         also its value when converted to a float. Its variation, and by
@@ -64,7 +66,7 @@ def test_simple(self):
         self.assertIsNone(h.variation)
         self.assertIsNone(h.correctedHeading)
 
-    def test_headingWithoutVariationRepr(self):
+    def test_headingWithoutVariationRepr(self) -> None:
         """
         A repr of a heading with no variation reports its value and that the
         variation is unknown.
@@ -73,7 +75,7 @@ def test_headingWithoutVariationRepr(self):
         expectedRepr = "<Heading (1.0 degrees, unknown variation)>"
         self.assertEqual(repr(heading), expectedRepr)
 
-    def test_headingWithVariationRepr(self):
+    def test_headingWithVariationRepr(self) -> None:
         """
         A repr of a heading with known variation reports its value and the
         value of that variation.
@@ -83,32 +85,32 @@ def test_headingWithVariationRepr(self):
         reprTemplate = "<Heading ({0} degrees, <Variation ({1} degrees)>)>"
         self.assertEqual(repr(heading), reprTemplate.format(angle, variation))
 
-    def test_valueEquality(self):
+    def test_valueEquality(self) -> None:
         """
         Headings with the same values compare equal.
         """
         self.assertEqual(base.Heading(1.0), base.Heading(1.0))
 
-    def test_valueInequality(self):
+    def test_valueInequality(self) -> None:
         """
         Headings with different values compare unequal.
         """
         self.assertNotEqual(base.Heading(1.0), base.Heading(2.0))
 
-    def test_zeroHeadingEdgeCase(self):
+    def test_zeroHeadingEdgeCase(self) -> None:
         """
         Headings can be instantiated with a value of 0 and no variation.
         """
         base.Heading(0)
 
-    def test_zeroHeading180DegreeVariationEdgeCase(self):
+    def test_zeroHeading180DegreeVariationEdgeCase(self) -> None:
         """
         Headings can be instantiated with a value of 0 and a variation of 180
         degrees.
         """
         base.Heading(0, 180)
 
-    def _badValueTest(self, **kw):
+    def _badValueTest(self, **kw: float) -> None:
         """
         Helper function for verifying that bad values raise C{ValueError}.
 
@@ -116,50 +118,50 @@ def _badValueTest(self, **kw):
         """
         self.assertRaises(ValueError, base.Heading.fromFloats, **kw)
 
-    def test_badAngleValueEdgeCase(self):
+    def test_badAngleValueEdgeCase(self) -> None:
         """
         Headings can not be instantiated with a value of 360 degrees.
         """
         self._badValueTest(angleValue=360.0)
 
-    def test_badVariationEdgeCase(self):
+    def test_badVariationEdgeCase(self) -> None:
         """
         Headings can not be instantiated with a variation of -180 degrees.
         """
         self._badValueTest(variationValue=-180.0)
 
-    def test_negativeHeading(self):
+    def test_negativeHeading(self) -> None:
         """
         Negative heading values raise C{ValueError}.
         """
         self._badValueTest(angleValue=-10.0)
 
-    def test_headingTooLarge(self):
+    def test_headingTooLarge(self) -> None:
         """
         Heading values greater than C{360.0} raise C{ValueError}.
         """
         self._badValueTest(angleValue=370.0)
 
-    def test_variationTooNegative(self):
+    def test_variationTooNegative(self) -> None:
         """
         Variation values less than C{-180.0} raise C{ValueError}.
         """
         self._badValueTest(variationValue=-190.0)
 
-    def test_variationTooPositive(self):
+    def test_variationTooPositive(self) -> None:
         """
         Variation values greater than C{180.0} raise C{ValueError}.
         """
         self._badValueTest(variationValue=190.0)
 
-    def test_correctedHeading(self):
+    def test_correctedHeading(self) -> None:
         """
         A heading with a value and a variation has a corrected heading.
         """
         h = base.Heading.fromFloats(1.0, variationValue=-10.0)
         self.assertEqual(h.correctedHeading, base.Angle(11.0, Angles.HEADING))
 
-    def test_correctedHeadingOverflow(self):
+    def test_correctedHeadingOverflow(self) -> None:
         """
         A heading with a value and a variation has the appropriate corrected
         heading value, even when the variation puts it across the 360 degree
@@ -168,7 +170,7 @@ def test_correctedHeadingOverflow(self):
         h = base.Heading.fromFloats(359.0, variationValue=-2.0)
         self.assertEqual(h.correctedHeading, base.Angle(1.0, Angles.HEADING))
 
-    def test_correctedHeadingOverflowEdgeCase(self):
+    def test_correctedHeadingOverflowEdgeCase(self) -> None:
         """
         A heading with a value and a variation has the appropriate corrected
         heading value, even when the variation puts it exactly at the 360
@@ -177,7 +179,7 @@ def test_correctedHeadingOverflowEdgeCase(self):
         h = base.Heading.fromFloats(359.0, variationValue=-1.0)
         self.assertEqual(h.correctedHeading, base.Angle(0.0, Angles.HEADING))
 
-    def test_correctedHeadingUnderflow(self):
+    def test_correctedHeadingUnderflow(self) -> None:
         """
         A heading with a value and a variation has the appropriate corrected
         heading value, even when the variation puts it under the 0 degree
@@ -186,7 +188,7 @@ def test_correctedHeadingUnderflow(self):
         h = base.Heading.fromFloats(1.0, variationValue=2.0)
         self.assertEqual(h.correctedHeading, base.Angle(359.0, Angles.HEADING))
 
-    def test_correctedHeadingUnderflowEdgeCase(self):
+    def test_correctedHeadingUnderflowEdgeCase(self) -> None:
         """
         A heading with a value and a variation has the appropriate corrected
         heading value, even when the variation puts it exactly at the 0
@@ -195,7 +197,7 @@ def test_correctedHeadingUnderflowEdgeCase(self):
         h = base.Heading.fromFloats(1.0, variationValue=1.0)
         self.assertEqual(h.correctedHeading, base.Angle(0.0, Angles.HEADING))
 
-    def test_setVariationSign(self):
+    def test_setVariationSign(self) -> None:
         """
         Setting the sign of a heading changes the variation sign.
         """
@@ -205,7 +207,7 @@ def test_setVariationSign(self):
         h.setSign(-1)
         self.assertEqual(h.variation.inDecimalDegrees, -1.0)
 
-    def test_setBadVariationSign(self):
+    def test_setBadVariationSign(self) -> None:
         """
         Setting the sign of a heading to values that aren't C{-1} or C{1}
         raises C{ValueError} and does not affect the heading.
@@ -220,7 +222,7 @@ def test_setBadVariationSign(self):
         self.assertRaises(ValueError, h.setSign, 50)
         self.assertEqual(h.variation.inDecimalDegrees, 1.0)
 
-    def test_setUnknownVariationSign(self):
+    def test_setUnknownVariationSign(self) -> None:
         """
         Setting the sign on a heading with unknown variation raises
         C{ValueError}.
@@ -231,14 +233,14 @@ def test_setUnknownVariationSign(self):
 
 
 class CoordinateTests(TestCase):
-    def test_float(self):
+    def test_float(self) -> None:
         """
         Coordinates can be converted to floats.
         """
         coordinate = base.Coordinate(10.0)
         self.assertEqual(float(coordinate), 10.0)
 
-    def test_repr(self):
+    def test_repr(self) -> None:
         """
         Coordinates that aren't explicitly latitudes or longitudes have an
         appropriate repr.
@@ -247,7 +249,7 @@ def test_repr(self):
         expectedRepr = f"<Angle of unknown type ({10.0} degrees)>"
         self.assertEqual(repr(coordinate), expectedRepr)
 
-    def test_positiveLatitude(self):
+    def test_positiveLatitude(self) -> None:
         """
         Positive latitudes have a repr that specifies their type and value.
         """
@@ -255,7 +257,7 @@ def test_positiveLatitude(self):
         expectedRepr = f"<Latitude ({10.0} degrees)>"
         self.assertEqual(repr(coordinate), expectedRepr)
 
-    def test_negativeLatitude(self):
+    def test_negativeLatitude(self) -> None:
         """
         Negative latitudes have a repr that specifies their type and value.
         """
@@ -263,7 +265,7 @@ def test_negativeLatitude(self):
         expectedRepr = f"<Latitude ({-50.0} degrees)>"
         self.assertEqual(repr(coordinate), expectedRepr)
 
-    def test_positiveLongitude(self):
+    def test_positiveLongitude(self) -> None:
         """
         Positive longitudes have a repr that specifies their type and value.
         """
@@ -271,7 +273,7 @@ def test_positiveLongitude(self):
         expectedRepr = f"<Longitude ({50.0} degrees)>"
         self.assertEqual(repr(longitude), expectedRepr)
 
-    def test_negativeLongitude(self):
+    def test_negativeLongitude(self) -> None:
         """
         Negative longitudes have a repr that specifies their type and value.
         """
@@ -279,30 +281,30 @@ def test_negativeLongitude(self):
         expectedRepr = f"<Longitude ({-50.0} degrees)>"
         self.assertEqual(repr(longitude), expectedRepr)
 
-    def test_bogusCoordinateType(self):
+    def test_bogusCoordinateType(self) -> None:
         """
         Creating coordinates with bogus types rasies C{ValueError}.
         """
         self.assertRaises(ValueError, base.Coordinate, 150.0, "BOGUS")
 
-    def test_angleTypeNotCoordinate(self):
+    def test_angleTypeNotCoordinate(self) -> None:
         """
         Creating coordinates with angle types that aren't coordinates raises
         C{ValueError}.
         """
         self.assertRaises(ValueError, base.Coordinate, 150.0, Angles.HEADING)
 
-    def test_equality(self):
+    def test_equality(self) -> None:
         """
         Coordinates with the same value and type are equal.
         """
 
-        def makeCoordinate():
+        def makeCoordinate() -> base.Coordinate:
             return base.Coordinate(1.0, Angles.LONGITUDE)
 
         self.assertEqual(makeCoordinate(), makeCoordinate())
 
-    def test_differentAnglesInequality(self):
+    def test_differentAnglesInequality(self) -> None:
         """
         Coordinates with different values aren't equal.
         """
@@ -310,7 +312,7 @@ def test_differentAnglesInequality(self):
         c2 = base.Coordinate(-1.0)
         self.assertNotEqual(c1, c2)
 
-    def test_differentTypesInequality(self):
+    def test_differentTypesInequality(self) -> None:
         """
         Coordinates with the same values but different types aren't equal.
         """
@@ -318,7 +320,7 @@ def test_differentTypesInequality(self):
         c2 = base.Coordinate(1.0, Angles.LONGITUDE)
         self.assertNotEqual(c1, c2)
 
-    def test_sign(self):
+    def test_sign(self) -> None:
         """
         Setting the sign on a coordinate sets the sign of the value of the
         coordinate.
@@ -329,7 +331,7 @@ def test_sign(self):
         c.setSign(-1)
         self.assertEqual(c.inDecimalDegrees, -50.0)
 
-    def test_badVariationSign(self):
+    def test_badVariationSign(self) -> None:
         """
         Setting a bogus sign value (not -1 or 1) on a coordinate raises
         C{ValueError} and doesn't affect the coordinate.
@@ -346,35 +348,35 @@ def test_badVariationSign(self):
         self.assertRaises(ValueError, c.setSign, 50)
         self.assertEqual(c.inDecimalDegrees, 50.0)
 
-    def test_northernHemisphere(self):
+    def test_northernHemisphere(self) -> None:
         """
         Positive latitudes are in the northern hemisphere.
         """
         coordinate = base.Coordinate(1.0, Angles.LATITUDE)
         self.assertEqual(coordinate.hemisphere, Directions.NORTH)
 
-    def test_easternHemisphere(self):
+    def test_easternHemisphere(self) -> None:
         """
         Positive longitudes are in the eastern hemisphere.
         """
         coordinate = base.Coordinate(1.0, Angles.LONGITUDE)
         self.assertEqual(coordinate.hemisphere, Directions.EAST)
 
-    def test_southernHemisphere(self):
+    def test_southernHemisphere(self) -> None:
         """
         Negative latitudes are in the southern hemisphere.
         """
         coordinate = base.Coordinate(-1.0, Angles.LATITUDE)
         self.assertEqual(coordinate.hemisphere, Directions.SOUTH)
 
-    def test_westernHemisphere(self):
+    def test_westernHemisphere(self) -> None:
         """
         Negative longitudes are in the western hemisphere.
         """
         coordinate = base.Coordinate(-1.0, Angles.LONGITUDE)
         self.assertEqual(coordinate.hemisphere, Directions.WEST)
 
-    def test_badHemisphere(self):
+    def test_badHemisphere(self) -> None:
         """
         Accessing the hemisphere for a coordinate that can't compute it
         raises C{ValueError}.
@@ -382,7 +384,7 @@ def test_badHemisphere(self):
         coordinate = base.Coordinate(1.0, None)
         self.assertRaises(ValueError, lambda: coordinate.hemisphere)
 
-    def test_latitudeTooLarge(self):
+    def test_latitudeTooLarge(self) -> None:
         """
         Creating a latitude with a value greater than or equal to 90 degrees
         raises C{ValueError}.
@@ -390,7 +392,7 @@ def test_latitudeTooLarge(self):
         self.assertRaises(ValueError, _makeLatitude, 150.0)
         self.assertRaises(ValueError, _makeLatitude, 90.0)
 
-    def test_latitudeTooSmall(self):
+    def test_latitudeTooSmall(self) -> None:
         """
         Creating a latitude with a value less than or equal to -90 degrees
         raises C{ValueError}.
@@ -398,7 +400,7 @@ def test_latitudeTooSmall(self):
         self.assertRaises(ValueError, _makeLatitude, -150.0)
         self.assertRaises(ValueError, _makeLatitude, -90.0)
 
-    def test_longitudeTooLarge(self):
+    def test_longitudeTooLarge(self) -> None:
         """
         Creating a longitude with a value greater than or equal to 180 degrees
         raises C{ValueError}.
@@ -406,7 +408,7 @@ def test_longitudeTooLarge(self):
         self.assertRaises(ValueError, _makeLongitude, 250.0)
         self.assertRaises(ValueError, _makeLongitude, 180.0)
 
-    def test_longitudeTooSmall(self):
+    def test_longitudeTooSmall(self) -> None:
         """
         Creating a longitude with a value less than or equal to -180 degrees
         raises C{ValueError}.
@@ -414,7 +416,7 @@ def test_longitudeTooSmall(self):
         self.assertRaises(ValueError, _makeLongitude, -250.0)
         self.assertRaises(ValueError, _makeLongitude, -180.0)
 
-    def test_inDegreesMinutesSeconds(self):
+    def test_inDegreesMinutesSeconds(self) -> None:
         """
         Coordinate values can be accessed in degrees, minutes, seconds.
         """
@@ -424,7 +426,7 @@ def test_inDegreesMinutesSeconds(self):
         c = base.Coordinate(50.213, Angles.LATITUDE)
         self.assertEqual(c.inDegreesMinutesSeconds, (50, 12, 46))
 
-    def test_unknownAngleInDegreesMinutesSeconds(self):
+    def test_unknownAngleInDegreesMinutesSeconds(self) -> None:
         """
         If the vaue of a coordinate is L{None}, its values in degrees,
         minutes, seconds is also L{None}.
@@ -433,14 +435,14 @@ def test_unknownAngleInDegreesMinutesSeconds(self):
         self.assertIsNone(c.inDegreesMinutesSeconds)
 
 
-def _makeLatitude(value):
+def _makeLatitude(value: float) -> base.Coordinate:
     """
     Builds and returns a latitude of given value.
     """
     return base.Coordinate(value, Angles.LATITUDE)
 
 
-def _makeLongitude(value):
+def _makeLongitude(value: float) -> base.Coordinate:
     """
     Builds and returns a longitude of given value.
     """
@@ -452,7 +454,7 @@ class AltitudeTests(TestCase):
     Tests for the L{twisted.positioning.base.Altitude} class.
     """
 
-    def test_value(self):
+    def test_value(self) -> None:
         """
         Altitudes can be instantiated and reports the correct value in
         meters and feet, as well as when converted to float.
@@ -462,14 +464,14 @@ def test_value(self):
         self.assertEqual(altitude.inMeters, 1.0)
         self.assertEqual(altitude.inFeet, 1.0 / base.METERS_PER_FOOT)
 
-    def test_repr(self):
+    def test_repr(self) -> None:
         """
         Altitudes report their type and value in their repr.
         """
         altitude = base.Altitude(1.0)
         self.assertEqual(repr(altitude), "<Altitude (1.0 m)>")
 
-    def test_equality(self):
+    def test_equality(self) -> None:
         """
         Altitudes with equal values compare equal.
         """
@@ -477,7 +479,7 @@ def test_equality(self):
         secondAltitude = base.Altitude(1.0)
         self.assertEqual(firstAltitude, secondAltitude)
 
-    def test_inequality(self):
+    def test_inequality(self) -> None:
         """
         Altitudes with different values don't compare equal.
         """
@@ -491,7 +493,7 @@ class SpeedTests(TestCase):
     Tests for the L{twisted.positioning.base.Speed} class.
     """
 
-    def test_value(self):
+    def test_value(self) -> None:
         """
         Speeds can be instantiated, and report their value in meters
         per second, and can be converted to floats.
@@ -500,27 +502,27 @@ def test_value(self):
         self.assertEqual(speed.inMetersPerSecond, 50.0)
         self.assertEqual(float(speed), 50.0)
 
-    def test_repr(self):
+    def test_repr(self) -> None:
         """
         Speeds report their type and value in their repr.
         """
         speed = base.Speed(50.0)
         self.assertEqual(repr(speed), "<Speed (50.0 m/s)>")
 
-    def test_negativeSpeeds(self):
+    def test_negativeSpeeds(self) -> None:
         """
         Creating a negative speed raises C{ValueError}.
         """
         self.assertRaises(ValueError, base.Speed, -1.0)
 
-    def test_inKnots(self):
+    def test_inKnots(self) -> None:
         """
         A speed can be converted into its value in knots.
         """
         speed = base.Speed(1.0)
         self.assertEqual(1 / base.MPS_PER_KNOT, speed.inKnots)
 
-    def test_asFloat(self):
+    def test_asFloat(self) -> None:
         """
         A speed can be converted into a C{float}.
         """
@@ -532,7 +534,7 @@ class ClimbTests(TestCase):
     Tests for L{twisted.positioning.base.Climb}.
     """
 
-    def test_simple(self):
+    def test_simple(self) -> None:
         """
         Speeds can be instantiated, and report their value in meters
         per second, and can be converted to floats.
@@ -541,14 +543,14 @@ def test_simple(self):
         self.assertEqual(climb.inMetersPerSecond, 42.0)
         self.assertEqual(float(climb), 42.0)
 
-    def test_repr(self):
+    def test_repr(self) -> None:
         """
         Climbs report their type and value in their repr.
         """
         climb = base.Climb(42.0)
         self.assertEqual(repr(climb), "<Climb (42.0 m/s)>")
 
-    def test_negativeClimbs(self):
+    def test_negativeClimbs(self) -> None:
         """
         Climbs can have negative values, and still report that value
         in meters per second and when converted to floats.
@@ -557,14 +559,14 @@ def test_negativeClimbs(self):
         self.assertEqual(climb.inMetersPerSecond, -42.0)
         self.assertEqual(float(climb), -42.0)
 
-    def test_speedInKnots(self):
+    def test_speedInKnots(self) -> None:
         """
         A climb can be converted into its value in knots.
         """
         climb = base.Climb(1.0)
         self.assertEqual(1 / base.MPS_PER_KNOT, climb.inKnots)
 
-    def test_asFloat(self):
+    def test_asFloat(self) -> None:
         """
         A climb can be converted into a C{float}.
         """
@@ -576,7 +578,7 @@ class PositionErrorTests(TestCase):
     Tests for L{twisted.positioning.base.PositionError}.
     """
 
-    def test_allUnset(self):
+    def test_allUnset(self) -> None:
         """
         In an empty L{base.PositionError} with no invariant testing, all
         dilutions of positions are L{None}.
@@ -586,7 +588,7 @@ def test_allUnset(self):
         self.assertIsNone(positionError.hdop)
         self.assertIsNone(positionError.vdop)
 
-    def test_allUnsetWithInvariant(self):
+    def test_allUnsetWithInvariant(self) -> None:
         """
         In an empty L{base.PositionError} with invariant testing, all
         dilutions of positions are L{None}.
@@ -596,14 +598,14 @@ def test_allUnsetWithInvariant(self):
         self.assertIsNone(positionError.hdop)
         self.assertIsNone(positionError.vdop)
 
-    def test_withoutInvariant(self):
+    def test_withoutInvariant(self) -> None:
         """
         L{base.PositionError}s can be instantiated with just a HDOP.
         """
         positionError = base.PositionError(hdop=1.0)
         self.assertEqual(positionError.hdop, 1.0)
 
-    def test_withInvariant(self):
+    def test_withInvariant(self) -> None:
         """
         Creating a simple L{base.PositionError} with just a HDOP while
         checking the invariant works.
@@ -611,7 +613,7 @@ def test_withInvariant(self):
         positionError = base.PositionError(hdop=1.0, testInvariant=True)
         self.assertEqual(positionError.hdop, 1.0)
 
-    def test_invalidWithoutInvariant(self):
+    def test_invalidWithoutInvariant(self) -> None:
         """
         Creating a L{base.PositionError} with values set to an impossible
         combination works if the invariant is not checked.
@@ -621,7 +623,7 @@ def test_invalidWithoutInvariant(self):
         self.assertEqual(error.hdop, 1.0)
         self.assertEqual(error.vdop, 1.0)
 
-    def test_invalidWithInvariant(self):
+    def test_invalidWithInvariant(self) -> None:
         """
         Creating a L{base.PositionError} with values set to an impossible
         combination raises C{ValueError} if the invariant is being tested.
@@ -635,7 +637,7 @@ def test_invalidWithInvariant(self):
             testInvariant=True,
         )
 
-    def test_setDOPWithoutInvariant(self):
+    def test_setDOPWithoutInvariant(self) -> None:
         """
         You can set the PDOP value to value inconsisted with HDOP and VDOP
         when not checking the invariant.
@@ -644,7 +646,7 @@ def test_setDOPWithoutInvariant(self):
         pe.pdop = 100.0
         self.assertEqual(pe.pdop, 100.0)
 
-    def test_setDOPWithInvariant(self):
+    def test_setDOPWithInvariant(self) -> None:
         """
         Attempting to set the PDOP value to value inconsisted with HDOP and
         VDOP when checking the invariant raises C{ValueError}.
@@ -652,7 +654,7 @@ def test_setDOPWithInvariant(self):
         pe = base.PositionError(hdop=1.0, vdop=1.0, testInvariant=True)
         pdop = pe.pdop
 
-        def setPDOP(pe):
+        def setPDOP(pe: base.PositionError) -> None:
             pe.pdop = 100.0
 
         self.assertRaises(ValueError, setPDOP, pe)
@@ -660,7 +662,13 @@ def setPDOP(pe):
 
     REPR_TEMPLATE = "<PositionError (pdop: %s, hdop: %s, vdop: %s)>"
 
-    def _testDOP(self, pe, pdop, hdop, vdop):
+    def _testDOP(
+        self,
+        pe: base.PositionError,
+        pdop: float | None,
+        hdop: float | None,
+        vdop: float | None,
+    ) -> None:
         """
         Tests the DOP values in a position error, and the repr of that
         position error.
@@ -679,7 +687,7 @@ def _testDOP(self, pe, pdop, hdop, vdop):
         self.assertEqual(pe.vdop, vdop)
         self.assertEqual(repr(pe), self.REPR_TEMPLATE % (pdop, hdop, vdop))
 
-    def test_positionAndHorizontalSet(self):
+    def test_positionAndHorizontalSet(self) -> None:
         """
         The VDOP is correctly determined from PDOP and HDOP.
         """
@@ -688,7 +696,7 @@ def test_positionAndHorizontalSet(self):
         pe = base.PositionError(pdop=pdop, hdop=hdop)
         self._testDOP(pe, pdop, hdop, vdop)
 
-    def test_positionAndVerticalSet(self):
+    def test_positionAndVerticalSet(self) -> None:
         """
         The HDOP is correctly determined from PDOP and VDOP.
         """
@@ -697,7 +705,7 @@ def test_positionAndVerticalSet(self):
         pe = base.PositionError(pdop=pdop, vdop=vdop)
         self._testDOP(pe, pdop, hdop, vdop)
 
-    def test_horizontalAndVerticalSet(self):
+    def test_horizontalAndVerticalSet(self) -> None:
         """
         The PDOP is correctly determined from HDOP and VDOP.
         """
@@ -712,7 +720,7 @@ class BeaconInformationTests(TestCase):
     Tests for L{twisted.positioning.base.BeaconInformation}.
     """
 
-    def test_minimal(self):
+    def test_minimal(self) -> None:
         """
         For an empty beacon information object, the number of used
         beacons is zero, the number of seen beacons is zero, and the
@@ -727,13 +735,13 @@ def test_minimal(self):
 
     satelliteKwargs = {"azimuth": 1, "elevation": 1, "signalToNoiseRatio": 1.0}
 
-    def test_simple(self):
+    def test_simple(self) -> None:
         """
         Tests a beacon information with a bunch of satellites, none of
         which used in computing a fix.
         """
 
-        def _buildSatellite(**kw):
+        def _buildSatellite(**kw: float) -> base.Satellite:
             kwargs = dict(self.satelliteKwargs)
             kwargs.update(kw)
             return base.Satellite(**kwargs)
@@ -762,7 +770,7 @@ def _buildSatellite(**kw):
             "])>",
         )
 
-    def test_someSatellitesUsed(self):
+    def test_someSatellitesUsed(self) -> None:
         """
         Tests a beacon information with a bunch of satellites, some of
         them used in computing a fix.
@@ -799,7 +807,7 @@ class PositioningBeaconTests(TestCase):
     Tests for L{base.PositioningBeacon}.
     """
 
-    def test_interface(self):
+    def test_interface(self) -> None:
         """
         Tests that L{base.PositioningBeacon} implements L{IPositioningBeacon}.
         """
@@ -807,7 +815,7 @@ def test_interface(self):
         self.assertTrue(implements)
         verify.verifyObject(IPositioningBeacon, base.PositioningBeacon(1))
 
-    def test_repr(self):
+    def test_repr(self) -> None:
         """
         Tests the repr of a positioning beacon.
         """
@@ -819,7 +827,7 @@ class SatelliteTests(TestCase):
     Tests for L{twisted.positioning.base.Satellite}.
     """
 
-    def test_minimal(self):
+    def test_minimal(self) -> None:
         """
         Tests a minimal satellite that only has a known PRN.
 
@@ -835,7 +843,7 @@ def test_minimal(self):
             repr(s), "<Satellite (1), azimuth: None, " "elevation: None, snr: None>"
         )
 
-    def test_simple(self):
+    def test_simple(self) -> None:
         """
         Tests a minimal satellite that only has a known PRN.
 
diff --git a/src/twisted/test/crash_test_dummy.py b/src/twisted/test/crash_test_dummy.py
--- a/src/twisted/test/crash_test_dummy.py
+++ b/src/twisted/test/crash_test_dummy.py
@@ -1,21 +1,23 @@
 # Copyright (c) Twisted Matrix Laboratories.
 # See LICENSE for details.
+from __future__ import annotations
 
+from typing import Literal
 
 from zope.interface import Interface, implementer
 
 from twisted.python import components
 
 
-def foo():
+def foo() -> Literal[2]:
     return 2
 
 
 class X:
-    def __init__(self, x):
+    def __init__(self, x: str) -> None:
         self.x = x
 
-    def do(self):
+    def do(self) -> None:
         # print 'X',self.x,'doing!'
         pass
 
@@ -30,7 +32,7 @@ class IX(Interface):
 
 @implementer(IX)
 class XA(components.Adapter):
-    def method(self):
+    def method(self) -> None:
         # Kick start :(
         pass
 
diff --git a/src/twisted/test/ssl_helpers.py b/src/twisted/test/ssl_helpers.py
--- a/src/twisted/test/ssl_helpers.py
+++ b/src/twisted/test/ssl_helpers.py
@@ -7,6 +7,7 @@
 They are in a separate module so they will not prevent test_ssl importing if
 pyOpenSSL is unavailable.
 """
+from __future__ import annotations
 
 from OpenSSL import SSL
 
@@ -24,7 +25,7 @@ class ClientTLSContext(ssl.ClientContextFactory):
 
     isClient = 1
 
-    def getContext(self):
+    def getContext(self) -> SSL.Context:
         """
         Return an L{SSL.Context} to be use for client-side connections.
 
@@ -42,14 +43,16 @@ class ServerTLSContext:
 
     isClient = 0
 
-    def __init__(self, filename=certPath, method=None):
+    def __init__(
+        self, filename: str | bytes = certPath, method: int | None = None
+    ) -> None:
         self.filename = filename
         if method is None:
             method = SSL.SSLv23_METHOD
 
         self._method = method
 
-    def getContext(self):
+    def getContext(self) -> SSL.Context:
         """
         Return an L{SSL.Context} to be use for server-side connections.
 
diff --git a/src/twisted/test/test_formmethod.py b/src/twisted/test/test_formmethod.py
--- a/src/twisted/test/test_formmethod.py
+++ b/src/twisted/test/test_formmethod.py
@@ -1,31 +1,44 @@
 # Copyright (c) Twisted Matrix Laboratories.
 # See LICENSE for details.
-
+from __future__ import annotations
 
 """
 Test cases for formmethod module.
 """
 
+from typing import Callable, Iterable
+
+from typing_extensions import Concatenate, ParamSpec
+
 from twisted.python import formmethod
 from twisted.trial import unittest
 
+_P = ParamSpec("_P")
+
 
 class ArgumentTests(unittest.TestCase):
-    def argTest(self, argKlass, testPairs, badValues, *args, **kwargs):
+    def argTest(
+        self,
+        argKlass: Callable[Concatenate[str, _P], formmethod.Argument],
+        testPairs: Iterable[tuple[object, object]],
+        badValues: Iterable[object],
+        *args: _P.args,
+        **kwargs: _P.kwargs,
+    ) -> None:
         arg = argKlass("name", *args, **kwargs)
         for val, result in testPairs:
             self.assertEqual(arg.coerce(val), result)
         for val in badValues:
             self.assertRaises(formmethod.InputError, arg.coerce, val)
 
-    def test_argument(self):
+    def test_argument(self) -> None:
         """
         Test that corce correctly raises NotImplementedError.
         """
         arg = formmethod.Argument("name")
         self.assertRaises(NotImplementedError, arg.coerce, "")
 
-    def testString(self):
+    def testString(self) -> None:
         self.argTest(formmethod.String, [("a", "a"), (1, "1"), ("", "")], ())
         self.argTest(
             formmethod.String, [("ab", "ab"), ("abc", "abc")], ("2", ""), min=2
@@ -41,7 +54,7 @@ def testString(self):
             max=3,
         )
 
-    def testInt(self):
+    def testInt(self) -> None:
         self.argTest(
             formmethod.Integer, [("3", 3), ("-2", -2), ("", None)], ("q", "2.3")
         )
@@ -49,7 +62,7 @@ def testInt(self):
             formmethod.Integer, [("3", 3), ("-2", -2)], ("q", "2.3", ""), allowNone=0
         )
 
-    def testFloat(self):
+    def testFloat(self) -> None:
         self.argTest(
             formmethod.Float, [("3", 3.0), ("-2.3", -2.3), ("", None)], ("q", "2.3z")
         )
@@ -60,7 +73,7 @@ def testFloat(self):
             allowNone=0,
         )
 
-    def testChoice(self):
+    def testChoice(self) -> None:
         choices = [("a", "apple", "an apple"), ("b", "banana", "ook")]
         self.argTest(
             formmethod.Choice,
@@ -69,7 +82,7 @@ def testChoice(self):
             choices=choices,
         )
 
-    def testFlags(self):
+    def testFlags(self) -> None:
         flags = [("a", "apple", "an apple"), ("b", "banana", "ook")]
         self.argTest(
             formmethod.Flags,
@@ -78,11 +91,11 @@ def testFlags(self):
             flags=flags,
         )
 
-    def testBoolean(self):
+    def testBoolean(self) -> None:
         tests = [("yes", 1), ("", 0), ("False", 0), ("no", 0)]
         self.argTest(formmethod.Boolean, tests, ())
 
-    def test_file(self):
+    def test_file(self) -> None:
         """
         Test the correctness of the coerce function.
         """
@@ -92,7 +105,7 @@ def test_file(self):
         arg2 = formmethod.File("name")
         self.assertIsNone(arg2.coerce(None))
 
-    def testDate(self):
+    def testDate(self) -> None:
         goodTests = {
             ("2002", "12", "21"): (2002, 12, 21),
             ("1996", "2", "29"): (1996, 2, 29),
@@ -108,12 +121,12 @@ def testDate(self):
         ]
         self.argTest(formmethod.Date, goodTests, badTests)
 
-    def testRangedInteger(self):
+    def testRangedInteger(self) -> None:
         goodTests = {"0": 0, "12": 12, "3": 3}.items()
         badTests = ["-1", "x", "13", "-2000", "3.4"]
         self.argTest(formmethod.IntegerRange, goodTests, badTests, 0, 12)
 
-    def testVerifiedPassword(self):
+    def testVerifiedPassword(self) -> None:
         goodTests = {("foo", "foo"): "foo", ("ab", "ab"): "ab"}.items()
         badTests = [
             ("ab", "a"),
diff --git a/src/twisted/test/test_htb.py b/src/twisted/test/test_htb.py
--- a/src/twisted/test/test_htb.py
+++ b/src/twisted/test/test_htb.py
@@ -10,10 +10,10 @@
 class DummyClock:
     time = 0
 
-    def set(self, when):
+    def set(self, when: int) -> None:
         self.time = when
 
-    def __call__(self):
+    def __call__(self) -> int:
         return self.time
 
 
@@ -23,17 +23,17 @@ class SomeBucket(htb.Bucket):
 
 
 class TestBucketBase(unittest.TestCase):
-    def setUp(self):
+    def setUp(self) -> None:
         self._realTimeFunc = htb.time
         self.clock = DummyClock()
         htb.time = self.clock
 
-    def tearDown(self):
+    def tearDown(self) -> None:
         htb.time = self._realTimeFunc
 
 
 class BucketTests(TestBucketBase):
-    def testBucketSize(self):
+    def testBucketSize(self) -> None:
         """
         Testing the size of the bucket.
         """
@@ -41,7 +41,7 @@ def testBucketSize(self):
         fit = b.add(1000)
         self.assertEqual(100, fit)
 
-    def testBucketDrain(self):
+    def testBucketDrain(self) -> None:
         """
         Testing the bucket's drain rate.
         """
@@ -51,7 +51,7 @@ def testBucketDrain(self):
         fit = b.add(1000)
         self.assertEqual(20, fit)
 
-    def test_bucketEmpty(self):
+    def test_bucketEmpty(self) -> None:
         """
         L{htb.Bucket.drip} returns C{True} if the bucket is empty after that drip.
         """
@@ -66,19 +66,19 @@ def test_bucketEmpty(self):
 
 
 class BucketNestingTests(TestBucketBase):
-    def setUp(self):
+    def setUp(self) -> None:
         TestBucketBase.setUp(self)
         self.parent = SomeBucket()
         self.child1 = SomeBucket(self.parent)
         self.child2 = SomeBucket(self.parent)
 
-    def testBucketParentSize(self):
+    def testBucketParentSize(self) -> None:
         # Use up most of the parent bucket.
         self.child1.add(90)
         fit = self.child2.add(90)
         self.assertEqual(10, fit)
 
-    def testBucketParentRate(self):
+    def testBucketParentRate(self) -> None:
         # Make the parent bucket drain slower.
         self.parent.rate = 1
         # Fill both child1 and parent.
@@ -96,13 +96,13 @@ def testBucketParentRate(self):
 
 
 class ConsumerShaperTests(TestBucketBase):
-    def setUp(self):
+    def setUp(self) -> None:
         TestBucketBase.setUp(self)
         self.underlying = DummyConsumer()
         self.bucket = SomeBucket()
         self.shaped = htb.ShapedConsumer(self.underlying, self.bucket)
 
-    def testRate(self):
+    def testRate(self) -> None:
         # Start off with a full bucket, so the burst-size doesn't factor in
         # to the calculations.
         delta_t = 10
@@ -112,7 +112,7 @@ def testRate(self):
         self.shaped.resumeProducing()
         self.assertEqual(len(self.underlying.getvalue()), delta_t * self.bucket.rate)
 
-    def testBucketRefs(self):
+    def testBucketRefs(self) -> None:
         self.assertEqual(self.bucket._refcount, 1)
         self.shaped.stopProducing()
         self.assertEqual(self.bucket._refcount, 0)
diff --git a/src/twisted/test/test_iosim.py b/src/twisted/test/test_iosim.py
--- a/src/twisted/test/test_iosim.py
+++ b/src/twisted/test/test_iosim.py
@@ -4,7 +4,9 @@
 """
 Tests for L{twisted.test.iosim}.
 """
+from __future__ import annotations
 
+from typing import Literal
 
 from zope.interface import implementer
 
@@ -19,7 +21,7 @@ class FakeTransportTests(TestCase):
     Tests for L{FakeTransport}.
     """
 
-    def test_connectionSerial(self):
+    def test_connectionSerial(self) -> None:
         """
         Each L{FakeTransport} receives a serial number that uniquely identifies
         it.
@@ -30,7 +32,7 @@ def test_connectionSerial(self):
         self.assertIsInstance(b.serial, int)
         self.assertNotEqual(a.serial, b.serial)
 
-    def test_writeSequence(self):
+    def test_writeSequence(self) -> None:
         """
         L{FakeTransport.writeSequence} will write a sequence of L{bytes} to the
         transport.
@@ -42,7 +44,7 @@ def test_writeSequence(self):
 
         self.assertEqual(b"".join(a.stream), b"abcd")
 
-    def test_writeAfterClose(self):
+    def test_writeAfterClose(self) -> None:
         """
         L{FakeTransport.write} will accept writes after transport was closed,
         but the data will be silently discarded.
@@ -64,17 +66,17 @@ class StrictPushProducer:
 
     _state = "running"
 
-    def stopProducing(self):
+    def stopProducing(self) -> None:
         if self._state == "stopped":
             raise ValueError("Cannot stop already-stopped IPushProducer")
         self._state = "stopped"
 
-    def pauseProducing(self):
+    def pauseProducing(self) -> None:
         if self._state != "running":
             raise ValueError(f"Cannot pause {self._state} IPushProducer")
         self._state = "paused"
 
-    def resumeProducing(self):
+    def resumeProducing(self) -> None:
         if self._state != "paused":
             raise ValueError(f"Cannot resume {self._state} IPushProducer")
         self._state = "running"
@@ -85,14 +87,14 @@ class StrictPushProducerTests(TestCase):
     Tests for L{StrictPushProducer}.
     """
 
-    def _initial(self):
+    def _initial(self) -> StrictPushProducer:
         """
         @return: A new L{StrictPushProducer} which has not been through any state
             changes.
         """
         return StrictPushProducer()
 
-    def _stopped(self):
+    def _stopped(self) -> StrictPushProducer:
         """
         @return: A new, stopped L{StrictPushProducer}.
         """
@@ -100,7 +102,7 @@ def _stopped(self):
         producer.stopProducing()
         return producer
 
-    def _paused(self):
+    def _paused(self) -> StrictPushProducer:
         """
         @return: A new, paused L{StrictPushProducer}.
         """
@@ -108,7 +110,7 @@ def _paused(self):
         producer.pauseProducing()
         return producer
 
-    def _resumed(self):
+    def _resumed(self) -> StrictPushProducer:
         """
         @return: A new L{StrictPushProducer} which has been paused and resumed.
         """
@@ -117,7 +119,7 @@ def _resumed(self):
         producer.resumeProducing()
         return producer
 
-    def assertStopped(self, producer):
+    def assertStopped(self, producer: StrictPushProducer) -> None:
         """
         Assert that the given producer is in the stopped state.
 
@@ -126,7 +128,7 @@ def assertStopped(self, producer):
         """
         self.assertEqual(producer._state, "stopped")
 
-    def assertPaused(self, producer):
+    def assertPaused(self, producer: StrictPushProducer) -> None:
         """
         Assert that the given producer is in the paused state.
 
@@ -135,7 +137,7 @@ def assertPaused(self, producer):
         """
         self.assertEqual(producer._state, "paused")
 
-    def assertRunning(self, producer):
+    def assertRunning(self, producer: StrictPushProducer) -> None:
         """
         Assert that the given producer is in the running state.
 
@@ -144,28 +146,28 @@ def assertRunning(self, producer):
         """
         self.assertEqual(producer._state, "running")
 
-    def test_stopThenStop(self):
+    def test_stopThenStop(self) -> None:
         """
         L{StrictPushProducer.stopProducing} raises L{ValueError} if called when
         the producer is stopped.
         """
         self.assertRaises(ValueError, self._stopped().stopProducing)
 
-    def test_stopThenPause(self):
+    def test_stopThenPause(self) -> None:
         """
         L{StrictPushProducer.pauseProducing} raises L{ValueError} if called when
         the producer is stopped.
         """
         self.assertRaises(ValueError, self._stopped().pauseProducing)
 
-    def test_stopThenResume(self):
+    def test_stopThenResume(self) -> None:
         """
         L{StrictPushProducer.resumeProducing} raises L{ValueError} if called when
         the producer is stopped.
         """
         self.assertRaises(ValueError, self._stopped().resumeProducing)
 
-    def test_pauseThenStop(self):
+    def test_pauseThenStop(self) -> None:
         """
         L{StrictPushProducer} is stopped if C{stopProducing} is called on a paused
         producer.
@@ -174,7 +176,7 @@ def test_pauseThenStop(self):
         producer.stopProducing()
         self.assertStopped(producer)
 
-    def test_pauseThenPause(self):
+    def test_pauseThenPause(self) -> None:
         """
         L{StrictPushProducer.pauseProducing} raises L{ValueError} if called on a
         paused producer.
@@ -182,7 +184,7 @@ def test_pauseThenPause(self):
         producer = self._paused()
         self.assertRaises(ValueError, producer.pauseProducing)
 
-    def test_pauseThenResume(self):
+    def test_pauseThenResume(self) -> None:
         """
         L{StrictPushProducer} is resumed if C{resumeProducing} is called on a
         paused producer.
@@ -191,7 +193,7 @@ def test_pauseThenResume(self):
         producer.resumeProducing()
         self.assertRunning(producer)
 
-    def test_resumeThenStop(self):
+    def test_resumeThenStop(self) -> None:
         """
         L{StrictPushProducer} is stopped if C{stopProducing} is called on a
         resumed producer.
@@ -200,7 +202,7 @@ def test_resumeThenStop(self):
         producer.stopProducing()
         self.assertStopped(producer)
 
-    def test_resumeThenPause(self):
+    def test_resumeThenPause(self) -> None:
         """
         L{StrictPushProducer} is paused if C{pauseProducing} is called on a
         resumed producer.
@@ -209,7 +211,7 @@ def test_resumeThenPause(self):
         producer.pauseProducing()
         self.assertPaused(producer)
 
-    def test_resumeThenResume(self):
+    def test_resumeThenResume(self) -> None:
         """
         L{StrictPushProducer.resumeProducing} raises L{ValueError} if called on a
         resumed producer.
@@ -217,7 +219,7 @@ def test_resumeThenResume(self):
         producer = self._resumed()
         self.assertRaises(ValueError, producer.resumeProducing)
 
-    def test_stop(self):
+    def test_stop(self) -> None:
         """
         L{StrictPushProducer} is stopped if C{stopProducing} is called in the
         initial state.
@@ -226,7 +228,7 @@ def test_stop(self):
         producer.stopProducing()
         self.assertStopped(producer)
 
-    def test_pause(self):
+    def test_pause(self) -> None:
         """
         L{StrictPushProducer} is paused if C{pauseProducing} is called in the
         initial state.
@@ -235,7 +237,7 @@ def test_pause(self):
         producer.pauseProducing()
         self.assertPaused(producer)
 
-    def test_resume(self):
+    def test_resume(self) -> None:
         """
         L{StrictPushProducer} raises L{ValueError} if C{resumeProducing} is called
         in the initial state.
@@ -249,7 +251,7 @@ class IOPumpTests(TestCase):
     Tests for L{IOPump}.
     """
 
-    def _testStreamingProducer(self, mode):
+    def _testStreamingProducer(self, mode: Literal["server", "client"]) -> None:
         """
         Connect a couple protocol/transport pairs to an L{IOPump} and then pump
         it.  Verify that a streaming producer registered with one of the
@@ -284,14 +286,14 @@ def _testStreamingProducer(self, mode):
         pump.pump()
         self.assertEqual("running", producer._state)
 
-    def test_serverStreamingProducer(self):
+    def test_serverStreamingProducer(self) -> None:
         """
         L{IOPump.pump} does not call C{resumeProducing} on a L{IPushProducer}
         (stream producer) registered with the server transport.
         """
         self._testStreamingProducer(mode="server")
 
-    def test_clientStreamingProducer(self):
+    def test_clientStreamingProducer(self) -> None:
         """
         L{IOPump.pump} does not call C{resumeProducing} on a L{IPushProducer}
         (stream producer) registered with the client transport.
diff --git a/src/twisted/test/test_lockfile.py b/src/twisted/test/test_lockfile.py
--- a/src/twisted/test/test_lockfile.py
+++ b/src/twisted/test/test_lockfile.py
@@ -5,12 +5,14 @@
 """
 Tests for L{twisted.python.lockfile}.
 """
-
+from __future__ import annotations
 
 import errno
 import os
 from unittest import skipIf, skipUnless
 
+from typing_extensions import NoReturn
+
 from twisted.python import lockfile
 from twisted.python.reflect import requireModule
 from twisted.python.runtime import platform
@@ -35,7 +37,7 @@ class UtilTests(TestCase):
     Tests for the helper functions used to implement L{FilesystemLock}.
     """
 
-    def test_symlinkEEXIST(self):
+    def test_symlinkEEXIST(self) -> None:
         """
         L{lockfile.symlink} raises L{OSError} with C{errno} set to L{EEXIST}
         when an attempt is made to create a symlink which already exists.
@@ -49,7 +51,7 @@ def test_symlinkEEXIST(self):
         platform.isWindows(),
         "special rename EIO handling only necessary and correct on " "Windows.",
     )
-    def test_symlinkEIOWindows(self):
+    def test_symlinkEIOWindows(self) -> None:
         """
         L{lockfile.symlink} raises L{OSError} with C{errno} set to L{EIO} when
         the underlying L{rename} call fails with L{EIO}.
@@ -60,14 +62,14 @@ def test_symlinkEIOWindows(self):
         """
         name = self.mktemp()
 
-        def fakeRename(src, dst):
+        def fakeRename(src: str, dst: str) -> NoReturn:
             raise OSError(errno.EIO, None)
 
         self.patch(lockfile, "rename", fakeRename)
         exc = self.assertRaises(IOError, lockfile.symlink, name, "foo")
         self.assertEqual(exc.errno, errno.EIO)
 
-    def test_readlinkENOENT(self):
+    def test_readlinkENOENT(self) -> None:
         """
         L{lockfile.readlink} raises L{OSError} with C{errno} set to L{ENOENT}
         when an attempt is made to read a symlink which does not exist.
@@ -80,7 +82,7 @@ def test_readlinkENOENT(self):
         platform.isWindows(),
         "special readlink EACCES handling only necessary and " "correct on Windows.",
     )
-    def test_readlinkEACCESWindows(self):
+    def test_readlinkEACCESWindows(self) -> None:
         """
         L{lockfile.readlink} raises L{OSError} with C{errno} set to L{EACCES}
         on Windows when the underlying file open attempt fails with C{EACCES}.
@@ -91,7 +93,7 @@ def test_readlinkEACCESWindows(self):
         """
         name = self.mktemp()
 
-        def fakeOpen(path, mode):
+        def fakeOpen(path: str, mode: str) -> NoReturn:
             raise OSError(errno.EACCES, None)
 
         self.patch(lockfile, "_open", fakeOpen)
@@ -99,7 +101,7 @@ def fakeOpen(path, mode):
         self.assertEqual(exc.errno, errno.EACCES)
 
     @skipIf(skipKill, skipKillReason)
-    def test_kill(self):
+    def test_kill(self) -> None:
         """
         L{lockfile.kill} returns without error if passed the PID of a
         process which exists and signal C{0}.
@@ -107,7 +109,7 @@ def test_kill(self):
         lockfile.kill(os.getpid(), 0)
 
     @skipIf(skipKill, skipKillReason)
-    def test_killESRCH(self):
+    def test_killESRCH(self) -> None:
         """
         L{lockfile.kill} raises L{OSError} with errno of L{ESRCH} if
         passed a PID which does not correspond to any process.
@@ -116,7 +118,7 @@ def test_killESRCH(self):
         exc = self.assertRaises(OSError, lockfile.kill, 2 ** 31 - 1, 0)
         self.assertEqual(exc.errno, errno.ESRCH)
 
-    def test_noKillCall(self):
+    def test_noKillCall(self) -> None:
         """
         Verify that when L{lockfile.kill} does end up as None (e.g. on Windows
         without pywin32), it doesn't end up being called and raising a
@@ -129,8 +131,8 @@ def test_noKillCall(self):
 
 
 class LockingTests(TestCase):
-    def _symlinkErrorTest(self, errno):
-        def fakeSymlink(source, dest):
+    def _symlinkErrorTest(self, errno: int) -> None:
+        def fakeSymlink(source: str, dest: str) -> NoReturn:
             raise OSError(errno, None)
 
         self.patch(lockfile, "symlink", fakeSymlink)
@@ -140,7 +142,7 @@ def fakeSymlink(source, dest):
         exc = self.assertRaises(OSError, lock.lock)
         self.assertEqual(exc.errno, errno)
 
-    def test_symlinkError(self):
+    def test_symlinkError(self) -> None:
         """
         An exception raised by C{symlink} other than C{EEXIST} is passed up to
         the caller of L{FilesystemLock.lock}.
@@ -151,7 +153,7 @@ def test_symlinkError(self):
         platform.isWindows(),
         "POSIX-specific error propagation not expected on Windows.",
     )
-    def test_symlinkErrorPOSIX(self):
+    def test_symlinkErrorPOSIX(self) -> None:
         """
         An L{OSError} raised by C{symlink} on a POSIX platform with an errno of
         C{EACCES} or C{EIO} is passed to the caller of L{FilesystemLock.lock}.
@@ -162,7 +164,7 @@ def test_symlinkErrorPOSIX(self):
         self._symlinkErrorTest(errno.EACCES)
         self._symlinkErrorTest(errno.EIO)
 
-    def test_cleanlyAcquire(self):
+    def test_cleanlyAcquire(self) -> None:
         """
         If the lock has never been held, it can be acquired and the C{clean}
         and C{locked} attributes are set to C{True}.
@@ -173,7 +175,7 @@ def test_cleanlyAcquire(self):
         self.assertTrue(lock.clean)
         self.assertTrue(lock.locked)
 
-    def test_cleanlyRelease(self):
+    def test_cleanlyRelease(self) -> None:
         """
         If a lock is released cleanly, it can be re-acquired and the C{clean}
         and C{locked} attributes are set to C{True}.
@@ -189,7 +191,7 @@ def test_cleanlyRelease(self):
         self.assertTrue(lock.clean)
         self.assertTrue(lock.locked)
 
-    def test_cannotLockLocked(self):
+    def test_cannotLockLocked(self) -> None:
         """
         If a lock is currently locked, it cannot be locked again.
         """
@@ -201,7 +203,7 @@ def test_cannotLockLocked(self):
         self.assertFalse(secondLock.lock())
         self.assertFalse(secondLock.locked)
 
-    def test_uncleanlyAcquire(self):
+    def test_uncleanlyAcquire(self) -> None:
         """
         If a lock was held by a process which no longer exists, it can be
         acquired, the C{clean} attribute is set to C{False}, and the
@@ -209,7 +211,7 @@ def test_uncleanlyAcquire(self):
         """
         owner = 12345
 
-        def fakeKill(pid, signal):
+        def fakeKill(pid: int, signal: int) -> None:
             if signal != 0:
                 raise OSError(errno.EPERM, None)
             if pid == owner:
@@ -226,14 +228,14 @@ def fakeKill(pid, signal):
 
         self.assertEqual(lockfile.readlink(lockf), str(os.getpid()))
 
-    def test_lockReleasedBeforeCheck(self):
+    def test_lockReleasedBeforeCheck(self) -> None:
         """
         If the lock is initially held but then released before it can be
         examined to determine if the process which held it still exists, it is
         acquired and the C{clean} and C{locked} attributes are set to C{True}.
         """
 
-        def fakeReadlink(name):
+        def fakeReadlink(name: str) -> str:
             # Pretend to be another process releasing the lock.
             lockfile.rmlink(lockf)
             # Fall back to the real implementation of readlink.
@@ -242,7 +244,7 @@ def fakeReadlink(name):
 
         readlinkPatch = self.patch(lockfile, "readlink", fakeReadlink)
 
-        def fakeKill(pid, signal):
+        def fakeKill(pid: int, signal: int) -> None:
             if signal != 0:
                 raise OSError(errno.EPERM, None)
             if pid == 43125:
@@ -261,7 +263,7 @@ def fakeKill(pid, signal):
         platform.isWindows(),
         "special rename EIO handling only necessary and correct on " "Windows.",
     )
-    def test_lockReleasedDuringAcquireSymlink(self):
+    def test_lockReleasedDuringAcquireSymlink(self) -> None:
         """
         If the lock is released while an attempt is made to acquire
         it, the lock attempt fails and C{FilesystemLock.lock} returns
@@ -271,7 +273,7 @@ def test_lockReleasedDuringAcquireSymlink(self):
         RemoveDirectory) which is not atomic.
         """
 
-        def fakeSymlink(src, dst):
+        def fakeSymlink(src: str, dst: str) -> NoReturn:
             # While another process id doing os.rmdir which the Windows
             # implementation of rmlink does, a rename call will fail with EIO.
             raise OSError(errno.EIO, None)
@@ -287,14 +289,14 @@ def fakeSymlink(src, dst):
         platform.isWindows(),
         "special readlink EACCES handling only necessary and " "correct on Windows.",
     )
-    def test_lockReleasedDuringAcquireReadlink(self):
+    def test_lockReleasedDuringAcquireReadlink(self) -> None:
         """
         If the lock is initially held but is released while an attempt
         is made to acquire it, the lock attempt fails and
         L{FilesystemLock.lock} returns C{False}.
         """
 
-        def fakeReadlink(name):
+        def fakeReadlink(name: str) -> NoReturn:
             # While another process is doing os.rmdir which the
             # Windows implementation of rmlink does, a readlink call
             # will fail with EACCES.
@@ -308,8 +310,10 @@ def fakeReadlink(name):
         self.assertFalse(lock.lock())
         self.assertFalse(lock.locked)
 
-    def _readlinkErrorTest(self, exceptionType, errno):
-        def fakeReadlink(name):
+    def _readlinkErrorTest(
+        self, exceptionType: type[OSError] | type[IOError], errno: int
+    ) -> None:
+        def fakeReadlink(name: str) -> NoReturn:
             raise exceptionType(errno, None)
 
         self.patch(lockfile, "readlink", fakeReadlink)
@@ -324,7 +328,7 @@ def fakeReadlink(name):
         self.assertEqual(exc.errno, errno)
         self.assertFalse(lock.locked)
 
-    def test_readlinkError(self):
+    def test_readlinkError(self) -> None:
         """
         An exception raised by C{readlink} other than C{ENOENT} is passed up to
         the caller of L{FilesystemLock.lock}.
@@ -336,7 +340,7 @@ def test_readlinkError(self):
         platform.isWindows(),
         "POSIX-specific error propagation not expected on Windows.",
     )
-    def test_readlinkErrorPOSIX(self):
+    def test_readlinkErrorPOSIX(self) -> None:
         """
         Any L{IOError} raised by C{readlink} on a POSIX platform passed to the
         caller of L{FilesystemLock.lock}.
@@ -347,14 +351,14 @@ def test_readlinkErrorPOSIX(self):
         self._readlinkErrorTest(IOError, errno.ENOSYS)
         self._readlinkErrorTest(IOError, errno.EACCES)
 
-    def test_lockCleanedUpConcurrently(self):
+    def test_lockCleanedUpConcurrently(self) -> None:
         """
         If a second process cleans up the lock after a first one checks the
         lock and finds that no process is holding it, the first process does
         not fail when it tries to clean up the lock.
         """
 
-        def fakeRmlink(name):
+        def fakeRmlink(name: str) -> None:
             rmlinkPatch.restore()
             # Pretend to be another process cleaning up the lock.
             lockfile.rmlink(lockf)
@@ -363,7 +367,7 @@ def fakeRmlink(name):
 
         rmlinkPatch = self.patch(lockfile, "rmlink", fakeRmlink)
 
-        def fakeKill(pid, signal):
+        def fakeKill(pid: int, signal: int) -> None:
             if signal != 0:
                 raise OSError(errno.EPERM, None)
             if pid == 43125:
@@ -378,18 +382,18 @@ def fakeKill(pid, signal):
         self.assertTrue(lock.clean)
         self.assertTrue(lock.locked)
 
-    def test_rmlinkError(self):
+    def test_rmlinkError(self) -> None:
         """
         An exception raised by L{rmlink} other than C{ENOENT} is passed up
         to the caller of L{FilesystemLock.lock}.
         """
 
-        def fakeRmlink(name):
+        def fakeRmlink(name: str) -> NoReturn:
             raise OSError(errno.ENOSYS, None)
 
         self.patch(lockfile, "rmlink", fakeRmlink)
 
-        def fakeKill(pid, signal):
+        def fakeKill(pid: int, signal: int) -> None:
             if signal != 0:
                 raise OSError(errno.EPERM, None)
             if pid == 43125:
@@ -407,14 +411,14 @@ def fakeKill(pid, signal):
         self.assertEqual(exc.errno, errno.ENOSYS)
         self.assertFalse(lock.locked)
 
-    def test_killError(self):
+    def test_killError(self) -> None:
         """
         If L{kill} raises an exception other than L{OSError} with errno set to
         C{ESRCH}, the exception is passed up to the caller of
         L{FilesystemLock.lock}.
         """
 
-        def fakeKill(pid, signal):
+        def fakeKill(pid: int, signal: int) -> NoReturn:
             raise OSError(errno.EPERM, None)
 
         self.patch(lockfile, "kill", fakeKill)
@@ -429,7 +433,7 @@ def fakeKill(pid, signal):
         self.assertEqual(exc.errno, errno.EPERM)
         self.assertFalse(lock.locked)
 
-    def test_unlockOther(self):
+    def test_unlockOther(self) -> None:
         """
         L{FilesystemLock.unlock} raises L{ValueError} if called for a lock
         which is held by a different process.
@@ -439,7 +443,7 @@ def test_unlockOther(self):
         lock = lockfile.FilesystemLock(lockf)
         self.assertRaises(ValueError, lock.unlock)
 
-    def test_isLocked(self):
+    def test_isLocked(self) -> None:
         """
         L{isLocked} returns C{True} if the named lock is currently locked,
         C{False} otherwise.
diff --git a/src/twisted/test/test_monkey.py b/src/twisted/test/test_monkey.py
--- a/src/twisted/test/test_monkey.py
+++ b/src/twisted/test/test_monkey.py
@@ -4,14 +4,16 @@
 """
 Tests for L{twisted.python.monkey}.
 """
+from __future__ import annotations
 
+from typing_extensions import NoReturn
 
 from twisted.python.monkey import MonkeyPatcher
 from twisted.trial import unittest
 
 
 class TestObj:
-    def __init__(self):
+    def __init__(self) -> None:
         self.foo = "foo value"
         self.bar = "bar value"
         self.baz = "baz value"
@@ -22,12 +24,12 @@ class MonkeyPatcherTests(unittest.SynchronousTestCase):
     Tests for L{MonkeyPatcher} monkey-patching class.
     """
 
-    def setUp(self):
+    def setUp(self) -> None:
         self.testObject = TestObj()
         self.originalObject = TestObj()
         self.monkeyPatcher = MonkeyPatcher()
 
-    def test_empty(self):
+    def test_empty(self) -> None:
         """
         A monkey patcher without patches shouldn't change a thing.
         """
@@ -39,7 +41,7 @@ def test_empty(self):
         self.assertEqual(self.originalObject.bar, self.testObject.bar)
         self.assertEqual(self.originalObject.baz, self.testObject.baz)
 
-    def test_constructWithPatches(self):
+    def test_constructWithPatches(self) -> None:
         """
         Constructing a L{MonkeyPatcher} with patches should add all of the
         given patches to the patch list.
@@ -52,7 +54,7 @@ def test_constructWithPatches(self):
         self.assertEqual("hehe", self.testObject.bar)
         self.assertEqual(self.originalObject.baz, self.testObject.baz)
 
-    def test_patchExisting(self):
+    def test_patchExisting(self) -> None:
         """
         Patching an attribute that exists sets it to the value defined in the
         patch.
@@ -61,14 +63,14 @@ def test_patchExisting(self):
         self.monkeyPatcher.patch()
         self.assertEqual(self.testObject.foo, "haha")
 
-    def test_patchNonExisting(self):
+    def test_patchNonExisting(self) -> None:
         """
         Patching a non-existing attribute fails with an C{AttributeError}.
         """
         self.monkeyPatcher.addPatch(self.testObject, "nowhere", "blow up please")
         self.assertRaises(AttributeError, self.monkeyPatcher.patch)
 
-    def test_patchAlreadyPatched(self):
+    def test_patchAlreadyPatched(self) -> None:
         """
         Adding a patch for an object and attribute that already have a patch
         overrides the existing patch.
@@ -80,7 +82,7 @@ def test_patchAlreadyPatched(self):
         self.monkeyPatcher.restore()
         self.assertEqual(self.testObject.foo, self.originalObject.foo)
 
-    def test_restoreTwiceIsANoOp(self):
+    def test_restoreTwiceIsANoOp(self) -> None:
         """
         Restoring an already-restored monkey patch is a no-op.
         """
@@ -91,14 +93,14 @@ def test_restoreTwiceIsANoOp(self):
         self.monkeyPatcher.restore()
         self.assertEqual(self.testObject.foo, self.originalObject.foo)
 
-    def test_runWithPatchesDecoration(self):
+    def test_runWithPatchesDecoration(self) -> None:
         """
         runWithPatches should run the given callable, passing in all arguments
         and keyword arguments, and return the return value of the callable.
         """
-        log = []
+        log: list[tuple[int, int, int | None]] = []
 
-        def f(a, b, c=None):
+        def f(a: int, b: int, c: int | None = None) -> str:
             log.append((a, b, c))
             return "foo"
 
@@ -106,13 +108,13 @@ def f(a, b, c=None):
         self.assertEqual("foo", result)
         self.assertEqual([(1, 2, 10)], log)
 
-    def test_repeatedRunWithPatches(self):
+    def test_repeatedRunWithPatches(self) -> None:
         """
         We should be able to call the same function with runWithPatches more
         than once. All patches should apply for each call.
         """
 
-        def f():
+        def f() -> tuple[str, str, str]:
             return (self.testObject.foo, self.testObject.bar, self.testObject.baz)
 
         self.monkeyPatcher.addPatch(self.testObject, "foo", "haha")
@@ -125,7 +127,7 @@ def f():
             ("haha", self.originalObject.bar, self.originalObject.baz), result
         )
 
-    def test_runWithPatchesRestores(self):
+    def test_runWithPatchesRestores(self) -> None:
         """
         C{runWithPatches} should restore the original values after the function
         has executed.
@@ -135,13 +137,13 @@ def test_runWithPatchesRestores(self):
         self.monkeyPatcher.runWithPatches(lambda: None)
         self.assertEqual(self.originalObject.foo, self.testObject.foo)
 
-    def test_runWithPatchesRestoresOnException(self):
+    def test_runWithPatchesRestoresOnException(self) -> None:
         """
         Test runWithPatches restores the original values even when the function
         raises an exception.
         """
 
-        def _():
+        def _() -> NoReturn:
             self.assertEqual(self.testObject.foo, "haha")
             self.assertEqual(self.testObject.bar, "blahblah")
             raise RuntimeError("Something went wrong!")
@@ -153,7 +155,7 @@ def _():
         self.assertEqual(self.testObject.foo, self.originalObject.foo)
         self.assertEqual(self.testObject.bar, self.originalObject.bar)
 
-    def test_contextManager(self):
+    def test_contextManager(self) -> None:
         """
         L{MonkeyPatcher} is a context manager that applies its patches on
         entry and restore original values on exit.
@@ -163,7 +165,7 @@ def test_contextManager(self):
             self.assertEqual(self.testObject.foo, "patched value")
         self.assertEqual(self.testObject.foo, self.originalObject.foo)
 
-    def test_contextManagerPropagatesExceptions(self):
+    def test_contextManagerPropagatesExceptions(self) -> None:
         """
         Exceptions propagate through the L{MonkeyPatcher} context-manager
         exit method.
diff --git a/src/twisted/test/test_rebuild.py b/src/twisted/test/test_rebuild.py
--- a/src/twisted/test/test_rebuild.py
+++ b/src/twisted/test/test_rebuild.py
@@ -1,11 +1,14 @@
 # Copyright (c) Twisted Matrix Laboratories.
 # See LICENSE for details.
 
+from __future__ import annotations
 
 import os
 import sys
 import types
 
+from typing_extensions import NoReturn
+
 from twisted.python import rebuild
 from twisted.trial.unittest import TestCase
 from . import crash_test_dummy
@@ -40,7 +43,7 @@ class HashRaisesRuntimeError:
     def __init__(self) -> None:
         self.hashCalled = False
 
-    def __hash__(self):
+    def __hash__(self) -> NoReturn:
         self.hashCalled = True
         raise RuntimeError("not a TypeError!")
 
diff --git a/src/twisted/test/test_roots.py b/src/twisted/test/test_roots.py
--- a/src/twisted/test/test_roots.py
+++ b/src/twisted/test/test_roots.py
@@ -43,7 +43,7 @@ def testCollection(self) -> None:
 
     def testConstrained(self) -> None:
         class const(roots.Constrained):
-            def nameConstraint(self, name):
+            def nameConstraint(self, name: str) -> bool:
                 return name == "x"
 
         c = const()
diff --git a/src/twisted/trial/test/test_doctest.py b/src/twisted/trial/test/test_doctest.py
--- a/src/twisted/trial/test/test_doctest.py
+++ b/src/twisted/trial/test/test_doctest.py
@@ -4,7 +4,7 @@
 """
 Test Twisted's doctest support.
 """
-
+import unittest as pyunit
 
 from twisted.trial import itrial, reporter, runner, unittest
 from twisted.trial.test import mockdoctest
@@ -15,7 +15,7 @@ class RunnersTests(unittest.SynchronousTestCase):
     Tests for Twisted's doctest support.
     """
 
-    def test_id(self):
+    def test_id(self) -> None:
         """
         Check that the id() of the doctests' case object contains the FQPN of
         the actual tests.
@@ -26,7 +26,7 @@ def test_id(self):
         for test in suite._tests:
             self.assertIn(idPrefix, itrial.ITestCase(test).id())
 
-    def test_basicTrialIntegration(self):
+    def test_basicTrialIntegration(self) -> None:
         """
         L{loadDoctests} loads all of the doctests in the given module.
         """
@@ -34,7 +34,7 @@ def test_basicTrialIntegration(self):
         suite = loader.loadDoctests(mockdoctest)
         self.assertEqual(7, suite.countTestCases())
 
-    def _testRun(self, suite):
+    def _testRun(self, suite: pyunit.TestSuite) -> None:
         """
         Run C{suite} and check the result.
         """
@@ -43,14 +43,14 @@ def _testRun(self, suite):
         self.assertEqual(5, result.successes)
         self.assertEqual(2, len(result.failures))
 
-    def test_expectedResults(self, count=1):
+    def test_expectedResults(self, count: int = 1) -> None:
         """
         Trial can correctly run doctests with its xUnit test APIs.
         """
         suite = runner.TestLoader().loadDoctests(mockdoctest)
         self._testRun(suite)
 
-    def test_repeatable(self):
+    def test_repeatable(self) -> None:
         """
         Doctests should be runnable repeatably.
         """
diff --git a/src/twisted/trial/test/test_output.py b/src/twisted/trial/test/test_output.py
--- a/src/twisted/trial/test/test_output.py
+++ b/src/twisted/trial/test/test_output.py
@@ -4,19 +4,22 @@
 """
 Tests for the output generated by trial.
 """
-
+from __future__ import annotations
 
 import os
 from io import StringIO
+from typing import TypeVar
 
 from twisted.scripts import trial
 from twisted.trial import runner
 from twisted.trial.test import packages
 
+_T = TypeVar("_T")
+
 _noModuleError = "No module named 'frotz'"
 
 
-def runTrial(*args):
+def runTrial(*args: str) -> str:
     from twisted.trial import reporter
 
     config = trial.Options()
@@ -42,19 +45,23 @@ def debug(self) -> None:
 
     parent = "_testImportErrors"
 
-    def runTrial(self, *args):
+    def runTrial(self, *args: str) -> str:
         return runTrial("--temp-directory", self.mktemp(), *args)
 
-    def _print(self, stuff):
+    def _print(self, stuff: _T) -> _T:
         print(stuff)
         return stuff
 
-    def assertIn(self, container, containee, *args, **kwargs):
+    def assertIn(  # type: ignore[override]
+        self, container: str, containee: str, *args: object, **kwargs: object
+    ) -> str:
         # redefined to be useful in callbacks
         super().assertIn(containee, container, *args, **kwargs)
         return container
 
-    def assertNotIn(self, container, containee, *args, **kwargs):
+    def assertNotIn(  # type: ignore[override]
+        self, container: str, containee: str, *args: object, **kwargs: object
+    ) -> str:
         # redefined to be useful in callbacks
         super().assertNotIn(containee, container, *args, **kwargs)
         return container
@@ -62,41 +69,41 @@ def assertNotIn(self, container, containee, *args, **kwargs):
     def test_trialRun(self) -> None:
         self.runTrial()
 
-    def test_nonexistentModule(self):
+    def test_nonexistentModule(self) -> str:
         d = self.runTrial("twisted.doesntexist")
         self.assertIn(d, "[ERROR]")
         self.assertIn(d, "twisted.doesntexist")
         return d
 
-    def test_nonexistentPackage(self):
+    def test_nonexistentPackage(self) -> str:
         d = self.runTrial("doesntexist")
         self.assertIn(d, "doesntexist")
         self.assertIn(d, "ModuleNotFound")
         self.assertIn(d, "[ERROR]")
         return d
 
-    def test_nonexistentPackageWithModule(self):
+    def test_nonexistentPackageWithModule(self) -> str:
         d = self.runTrial("doesntexist.barney")
         self.assertIn(d, "doesntexist.barney")
         self.assertIn(d, "ObjectNotFound")
         self.assertIn(d, "[ERROR]")
         return d
 
-    def test_badpackage(self):
+    def test_badpackage(self) -> str:
         d = self.runTrial("badpackage")
         self.assertIn(d, "[ERROR]")
         self.assertIn(d, "badpackage")
         self.assertNotIn(d, "IOError")
         return d
 
-    def test_moduleInBadpackage(self):
+    def test_moduleInBadpackage(self) -> str:
         d = self.runTrial("badpackage.test_module")
         self.assertIn(d, "[ERROR]")
         self.assertIn(d, "badpackage.test_module")
         self.assertNotIn(d, "IOError")
         return d
 
-    def test_badmodule(self):
+    def test_badmodule(self) -> str:
         d = self.runTrial("package.test_bad_module")
         self.assertIn(d, "[ERROR]")
         self.assertIn(d, "package.test_bad_module")
@@ -104,7 +111,7 @@ def test_badmodule(self):
         self.assertNotIn(d, "<module ")
         return d
 
-    def test_badimport(self):
+    def test_badimport(self) -> str:
         d = self.runTrial("package.test_import_module")
         self.assertIn(d, "[ERROR]")
         self.assertIn(d, "package.test_import_module")
@@ -112,7 +119,7 @@ def test_badimport(self):
         self.assertNotIn(d, "<module ")
         return d
 
-    def test_recurseImport(self):
+    def test_recurseImport(self) -> str:
         d = self.runTrial("package")
         self.assertIn(d, "[ERROR]")
         self.assertIn(d, "test_bad_module")
@@ -121,7 +128,7 @@ def test_recurseImport(self):
         self.assertNotIn(d, "IOError")
         return d
 
-    def test_recurseImportErrors(self):
+    def test_recurseImportErrors(self) -> str:
         d = self.runTrial("package2")
         self.assertIn(d, "[ERROR]")
         self.assertIn(d, "package2")
@@ -131,14 +138,14 @@ def test_recurseImportErrors(self):
         self.assertNotIn(d, "IOError")
         return d
 
-    def test_nonRecurseImportErrors(self):
+    def test_nonRecurseImportErrors(self) -> str:
         d = self.runTrial("-N", "package2")
         self.assertIn(d, "[ERROR]")
         self.assertIn(d, _noModuleError)
         self.assertNotIn(d, "<module ")
         return d
 
-    def test_regularRun(self):
+    def test_regularRun(self) -> str:
         d = self.runTrial("package.test_module")
         self.assertNotIn(d, "[ERROR]")
         self.assertNotIn(d, "IOError")
@@ -146,7 +153,7 @@ def test_regularRun(self):
         self.assertIn(d, "PASSED (successes=1)")
         return d
 
-    def test_filename(self):
+    def test_filename(self) -> str:
         self.mangleSysPath(self.oldPath)
         d = self.runTrial(os.path.join(self.parent, "package", "test_module.py"))
         self.assertNotIn(d, "[ERROR]")
@@ -155,7 +162,7 @@ def test_filename(self):
         self.assertIn(d, "PASSED (successes=1)")
         return d
 
-    def test_dosFile(self):
+    def test_dosFile(self) -> str:
         ## XXX -- not really an output test, more of a script test
         self.mangleSysPath(self.oldPath)
         d = self.runTrial(os.path.join(self.parent, "package", "test_dos_module.py"))
diff --git a/src/twisted/trial/test/test_skip.py b/src/twisted/trial/test/test_skip.py
--- a/src/twisted/trial/test/test_skip.py
+++ b/src/twisted/trial/test/test_skip.py
@@ -18,10 +18,10 @@ class SkipDecoratorUsedOnClass(TestCase):
     this class.
     """
 
-    def test_shouldNeverRun_1(self):
+    def test_shouldNeverRun_1(self) -> None:
         raise Exception("Test should skip and never reach here")
 
-    def test_shouldNeverRun_2(self):
+    def test_shouldNeverRun_2(self) -> None:
         raise Exception("Test should skip and never reach here")
 
 
@@ -32,10 +32,10 @@ class SkipDecoratorUsedOnClassWithEmptyReason(TestCase):
     this class, even if the reason is an empty string
     """
 
-    def test_shouldNeverRun_1(self):
+    def test_shouldNeverRun_1(self) -> None:
         raise Exception("Test should skip and never reach here")
 
-    def test_shouldNeverRun_2(self):
+    def test_shouldNeverRun_2(self) -> None:
         raise Exception("Test should skip and never reach here")
 
 
@@ -45,11 +45,11 @@ class SkipDecoratorUsedOnMethods(TestCase):
     """
 
     @skipIf(True, "skipIf decorator used so skip test")
-    def test_shouldNeverRun(self):
+    def test_shouldNeverRun(self) -> None:
         raise Exception("Test should skip and never reach here")
 
     @skipIf(True, "")
-    def test_shouldNeverRunWithEmptyReason(self):
+    def test_shouldNeverRunWithEmptyReason(self) -> None:
         raise Exception("Test should skip and never reach here")
 
     def test_shouldShouldRun(self) -> None:
@@ -72,10 +72,10 @@ class SkipAttributeOnClass(TestCase):
 
     skip = "'skip' attribute set on this class, so skip all tests"
 
-    def test_one(self):
+    def test_one(self) -> None:
         raise Exception("Test should skip and never reach here")
 
-    def test_two(self):
+    def test_two(self) -> None:
         raise Exception("Test should skip and never reach here")
 
 
@@ -84,7 +84,7 @@ class SkipAttributeOnMethods(TestCase):
     Only methods where @skipIf decorator is used should be skipped.
     """
 
-    def test_one(self):
+    def test_one(self) -> None:
         raise Exception("Should never reach here")
 
     test_one.skip = "skip test, skip attribute set on method"  # type: ignore[attr-defined]
diff --git a/src/twisted/web/test/_util.py b/src/twisted/web/test/_util.py
--- a/src/twisted/web/test/_util.py
+++ b/src/twisted/web/test/_util.py
@@ -4,7 +4,7 @@
 """
 General helpers for L{twisted.web} unit tests.
 """
-
+from __future__ import annotations
 
 from typing import Type
 
@@ -13,10 +13,13 @@
 from twisted.web import server
 from twisted.web._flatten import flattenString
 from twisted.web.error import FlattenerError
+from twisted.web.http import Request
+from twisted.web.resource import IResource
 from twisted.web.template import Flattenable
+from .requesthelper import DummyRequest
 
 
-def _render(resource, request):
+def _render(resource: IResource, request: Request | DummyRequest) -> Deferred[None]:
     result = resource.render(request)
     if isinstance(result, bytes):
         request.write(result)
diff --git a/src/twisted/web/test/test_client.py b/src/twisted/web/test/test_client.py
--- a/src/twisted/web/test/test_client.py
+++ b/src/twisted/web/test/test_client.py
@@ -4,6 +4,8 @@
 """
 Tests for various parts of L{twisted.web}.
 """
+from __future__ import annotations
+
 from zope.interface import implementer, verify
 
 from twisted.internet import defer, interfaces
@@ -16,13 +18,15 @@ class DummyEndPoint:
 
     """An endpoint that does not connect anywhere"""
 
-    def __init__(self, someString):
+    def __init__(self, someString: str) -> None:
         self.someString = someString
 
     def __repr__(self) -> str:
         return f"DummyEndPoint({self.someString})"
 
-    def connect(self, factory):
+    def connect(  # type: ignore[override]
+        self, factory: interfaces.IProtocolFactory
+    ) -> defer.Deferred[dict[str, interfaces.IProtocolFactory]]:
         return defer.succeed(dict(factory=factory))
 
 
@@ -31,12 +35,12 @@ class HTTPConnectionPoolTests(unittest.TestCase):
     Unit tests for L{client.HTTPConnectionPoolTest}.
     """
 
-    def test_implements(self):
+    def test_implements(self) -> None:
         """L{DummyEndPoint}s implements L{interfaces.IStreamClientEndpoint}"""
         ep = DummyEndPoint("something")
         verify.verifyObject(interfaces.IStreamClientEndpoint, ep)
 
-    def test_repr(self):
+    def test_repr(self) -> None:
         """connection L{repr()} includes endpoint's L{repr()}"""
         pool = client.HTTPConnectionPool(reactor=None)
         ep = DummyEndPoint("this_is_probably_unique")
diff --git a/src/twisted/web/test/test_error.py b/src/twisted/web/test/test_error.py
--- a/src/twisted/web/test/test_error.py
+++ b/src/twisted/web/test/test_error.py
@@ -5,6 +5,7 @@
 HTTP errors.
 """
 
+from __future__ import annotations
 
 import re
 import sys
@@ -21,15 +22,15 @@ class CodeToMessageTests(unittest.TestCase):
     L{_codeToMessages} inverts L{_responses.RESPONSES}
     """
 
-    def test_validCode(self):
+    def test_validCode(self) -> None:
         m = error._codeToMessage(b"302")
         self.assertEqual(m, b"Found")
 
-    def test_invalidCode(self):
+    def test_invalidCode(self) -> None:
         m = error._codeToMessage(b"987")
         self.assertEqual(m, None)
 
-    def test_nonintegerCode(self):
+    def test_nonintegerCode(self) -> None:
         m = error._codeToMessage(b"InvalidCode")
         self.assertEqual(m, None)
 
@@ -39,7 +40,7 @@ class ErrorTests(unittest.TestCase):
     Tests for how L{Error} attributes are initialized.
     """
 
-    def test_noMessageValidStatus(self):
+    def test_noMessageValidStatus(self) -> None:
         """
         If no C{message} argument is passed to the L{Error} constructor and the
         C{code} argument is a valid HTTP status code, C{message} is set to the
@@ -49,7 +50,7 @@ def test_noMessageValidStatus(self):
         self.assertEqual(e.message, b"OK")
         self.assertEqual(str(e), "200 OK")
 
-    def test_noMessageForStatus(self):
+    def test_noMessageForStatus(self) -> None:
         """
         If no C{message} argument is passed to the L{Error} constructor and
         C{code} isn't a known HTTP status code, C{message} stays L{None}.
@@ -58,7 +59,7 @@ def test_noMessageForStatus(self):
         self.assertEqual(e.message, None)
         self.assertEqual(str(e), "999")
 
-    def test_invalidStatus(self):
+    def test_invalidStatus(self) -> None:
         """
         If C{code} isn't plausibly an HTTP status code (i.e., composed of
         digits) it is rejected with L{ValueError}.
@@ -66,7 +67,7 @@ def test_invalidStatus(self):
         with self.assertRaises(ValueError):
             error.Error(b"InvalidStatus")
 
-    def test_messageExists(self):
+    def test_messageExists(self) -> None:
         """
         If a C{message} argument is passed to the L{Error} constructor, the
         C{message} isn't affected by the value of C{status}.
@@ -75,7 +76,7 @@ def test_messageExists(self):
         self.assertEqual(e.message, b"My own message")
         self.assertEqual(str(e), "200 My own message")
 
-    def test_str(self):
+    def test_str(self) -> None:
         """
         C{str()} on an L{Error} returns the code and message it was
         instantiated with.
@@ -94,7 +95,7 @@ class PageRedirectTests(unittest.TestCase):
     Tests for how L{PageRedirect} attributes are initialized.
     """
 
-    def test_noMessageValidStatus(self):
+    def test_noMessageValidStatus(self) -> None:
         """
         If no C{message} argument is passed to the L{PageRedirect} constructor
         and the C{code} argument is a valid HTTP status code, C{code} is mapped
@@ -103,7 +104,7 @@ def test_noMessageValidStatus(self):
         e = error.PageRedirect(b"200", location=b"/foo")
         self.assertEqual(e.message, b"OK to /foo")
 
-    def test_noMessageValidStatusNoLocation(self):
+    def test_noMessageValidStatusNoLocation(self) -> None:
         """
         If no C{message} argument is passed to the L{PageRedirect} constructor
         and C{location} is also empty and the C{code} argument is a valid HTTP
@@ -113,7 +114,7 @@ def test_noMessageValidStatusNoLocation(self):
         e = error.PageRedirect(b"200")
         self.assertEqual(e.message, b"OK")
 
-    def test_noMessageInvalidStatusLocationExists(self):
+    def test_noMessageInvalidStatusLocationExists(self) -> None:
         """
         If no C{message} argument is passed to the L{PageRedirect} constructor
         and C{code} isn't a valid HTTP status code, C{message} stays L{None}.
@@ -121,7 +122,7 @@ def test_noMessageInvalidStatusLocationExists(self):
         e = error.PageRedirect(b"999", location=b"/foo")
         self.assertEqual(e.message, None)
 
-    def test_messageExistsLocationExists(self):
+    def test_messageExistsLocationExists(self) -> None:
         """
         If a C{message} argument is passed to the L{PageRedirect} constructor,
         the C{message} isn't affected by the value of C{status}.
@@ -129,7 +130,7 @@ def test_messageExistsLocationExists(self):
         e = error.PageRedirect(b"200", b"My own message", location=b"/foo")
         self.assertEqual(e.message, b"My own message to /foo")
 
-    def test_messageExistsNoLocation(self):
+    def test_messageExistsNoLocation(self) -> None:
         """
         If a C{message} argument is passed to the L{PageRedirect} constructor
         and no location is provided, C{message} doesn't try to include the
@@ -144,7 +145,7 @@ class InfiniteRedirectionTests(unittest.TestCase):
     Tests for how L{InfiniteRedirection} attributes are initialized.
     """
 
-    def test_noMessageValidStatus(self):
+    def test_noMessageValidStatus(self) -> None:
         """
         If no C{message} argument is passed to the L{InfiniteRedirection}
         constructor and the C{code} argument is a valid HTTP status code,
@@ -154,7 +155,7 @@ def test_noMessageValidStatus(self):
         e = error.InfiniteRedirection(b"200", location=b"/foo")
         self.assertEqual(e.message, b"OK to /foo")
 
-    def test_noMessageValidStatusNoLocation(self):
+    def test_noMessageValidStatusNoLocation(self) -> None:
         """
         If no C{message} argument is passed to the L{InfiniteRedirection}
         constructor and C{location} is also empty and the C{code} argument is a
@@ -165,7 +166,7 @@ def test_noMessageValidStatusNoLocation(self):
         e = error.InfiniteRedirection(b"200")
         self.assertEqual(e.message, b"OK")
 
-    def test_noMessageInvalidStatusLocationExists(self):
+    def test_noMessageInvalidStatusLocationExists(self) -> None:
         """
         If no C{message} argument is passed to the L{InfiniteRedirection}
         constructor and C{code} isn't a valid HTTP status code, C{message} stays
@@ -175,7 +176,7 @@ def test_noMessageInvalidStatusLocationExists(self):
         self.assertEqual(e.message, None)
         self.assertEqual(str(e), "999")
 
-    def test_messageExistsLocationExists(self):
+    def test_messageExistsLocationExists(self) -> None:
         """
         If a C{message} argument is passed to the L{InfiniteRedirection}
         constructor, the C{message} isn't affected by the value of C{status}.
@@ -183,7 +184,7 @@ def test_messageExistsLocationExists(self):
         e = error.InfiniteRedirection(b"200", b"My own message", location=b"/foo")
         self.assertEqual(e.message, b"My own message to /foo")
 
-    def test_messageExistsNoLocation(self):
+    def test_messageExistsNoLocation(self) -> None:
         """
         If a C{message} argument is passed to the L{InfiniteRedirection}
         constructor and no location is provided, C{message} doesn't try to
@@ -199,7 +200,7 @@ class RedirectWithNoLocationTests(unittest.TestCase):
     a custom message in the constructor.
     """
 
-    def test_validMessage(self):
+    def test_validMessage(self) -> None:
         """
         When C{code}, C{message}, and C{uri} are passed to the
         L{RedirectWithNoLocation} constructor, the C{message} and C{uri}
@@ -216,7 +217,7 @@ class MissingRenderMethodTests(unittest.TestCase):
     displayed.
     """
 
-    def test_constructor(self):
+    def test_constructor(self) -> None:
         """
         Given C{element} and C{renderName} arguments, the
         L{MissingRenderMethod} constructor assigns the values to the
@@ -227,7 +228,7 @@ def test_constructor(self):
         self.assertIs(e.element, elt)
         self.assertIs(e.renderName, "renderThing")
 
-    def test_repr(self):
+    def test_repr(self) -> None:
         """
         A L{MissingRenderMethod} is represented using a custom string
         containing the element's representation and the method name.
@@ -247,7 +248,7 @@ class MissingTemplateLoaderTests(unittest.TestCase):
     displayed.
     """
 
-    def test_constructor(self):
+    def test_constructor(self) -> None:
         """
         Given an C{element} argument, the L{MissingTemplateLoader} constructor
         assigns the value to the corresponding attribute.
@@ -256,7 +257,7 @@ def test_constructor(self):
         e = error.MissingTemplateLoader(elt)
         self.assertIs(e.element, elt)
 
-    def test_repr(self):
+    def test_repr(self) -> None:
         """
         A L{MissingTemplateLoader} is represented using a custom string
         containing the element's representation and the method name.
@@ -271,17 +272,17 @@ class FlattenerErrorTests(unittest.TestCase):
     Tests for L{FlattenerError}.
     """
 
-    def makeFlattenerError(self, roots=[]):
+    def makeFlattenerError(self, roots: list[object] = []) -> error.FlattenerError:
         try:
             raise RuntimeError("oh noes")
         except Exception as e:
             tb = traceback.extract_tb(sys.exc_info()[2])
             return error.FlattenerError(e, roots, tb)
 
-    def fakeFormatRoot(self, obj):
+    def fakeFormatRoot(self, obj: object) -> str:
         return "R(%s)" % obj
 
-    def test_constructor(self):
+    def test_constructor(self) -> None:
         """
         Given C{exception}, C{roots}, and C{traceback} arguments, the
         L{FlattenerError} constructor assigns the roots to the C{_roots}
@@ -290,7 +291,7 @@ def test_constructor(self):
         e = self.makeFlattenerError(roots=["a", "b"])
         self.assertEqual(e._roots, ["a", "b"])
 
-    def test_str(self):
+    def test_str(self) -> None:
         """
         The string form of a L{FlattenerError} is identical to its
         representation.
@@ -298,14 +299,14 @@ def test_str(self):
         e = self.makeFlattenerError()
         self.assertEqual(str(e), repr(e))
 
-    def test_reprWithRootsAndWithTraceback(self):
+    def test_reprWithRootsAndWithTraceback(self) -> None:
         """
         The representation of a L{FlattenerError} initialized with roots and a
         traceback contains a formatted representation of those roots (using
         C{_formatRoot}) and a formatted traceback.
         """
         e = self.makeFlattenerError(["a", "b"])
-        e._formatRoot = self.fakeFormatRoot
+        e._formatRoot = self.fakeFormatRoot  # type: ignore[method-assign]
         self.assertTrue(
             re.match(
                 "Exception while flattening:\n"
@@ -320,7 +321,7 @@ def test_reprWithRootsAndWithTraceback(self):
             repr(e),
         )
 
-    def test_reprWithoutRootsAndWithTraceback(self):
+    def test_reprWithoutRootsAndWithTraceback(self) -> None:
         """
         The representation of a L{FlattenerError} initialized without roots but
         with a traceback contains a formatted traceback but no roots.
@@ -338,7 +339,7 @@ def test_reprWithoutRootsAndWithTraceback(self):
             repr(e),
         )
 
-    def test_reprWithoutRootsAndWithoutTraceback(self):
+    def test_reprWithoutRootsAndWithoutTraceback(self) -> None:
         """
         The representation of a L{FlattenerError} initialized without roots but
         with a traceback contains a formatted traceback but no roots.
@@ -353,7 +354,7 @@ def test_reprWithoutRootsAndWithoutTraceback(self):
             repr(e),
         )
 
-    def test_formatRootShortUnicodeString(self):
+    def test_formatRootShortUnicodeString(self) -> None:
         """
         The C{_formatRoot} method formats a short unicode string using the
         built-in repr.
@@ -361,7 +362,7 @@ def test_formatRootShortUnicodeString(self):
         e = self.makeFlattenerError()
         self.assertEqual(e._formatRoot(nativeString("abcd")), repr("abcd"))
 
-    def test_formatRootLongUnicodeString(self):
+    def test_formatRootLongUnicodeString(self) -> None:
         """
         The C{_formatRoot} method formats a long unicode string using the
         built-in repr with an ellipsis.
@@ -373,7 +374,7 @@ def test_formatRootLongUnicodeString(self):
             repr("abcde-abcde-abcde-ab<...>e-abcde-abcde-abcde-"),
         )
 
-    def test_formatRootShortByteString(self):
+    def test_formatRootShortByteString(self) -> None:
         """
         The C{_formatRoot} method formats a short byte string using the
         built-in repr.
@@ -381,7 +382,7 @@ def test_formatRootShortByteString(self):
         e = self.makeFlattenerError()
         self.assertEqual(e._formatRoot(b"abcd"), repr(b"abcd"))
 
-    def test_formatRootLongByteString(self):
+    def test_formatRootLongByteString(self) -> None:
         """
         The C{_formatRoot} method formats a long byte string using the
         built-in repr with an ellipsis.
@@ -393,7 +394,7 @@ def test_formatRootLongByteString(self):
             repr(b"abcde-abcde-abcde-ab<...>e-abcde-abcde-abcde-"),
         )
 
-    def test_formatRootTagNoFilename(self):
+    def test_formatRootTagNoFilename(self) -> None:
         """
         The C{_formatRoot} method formats a C{Tag} with no filename information
         as 'Tag <tagName>'.
@@ -401,7 +402,7 @@ def test_formatRootTagNoFilename(self):
         e = self.makeFlattenerError()
         self.assertEqual(e._formatRoot(Tag("a-tag")), "Tag <a-tag>")
 
-    def test_formatRootTagWithFilename(self):
+    def test_formatRootTagWithFilename(self) -> None:
         """
         The C{_formatRoot} method formats a C{Tag} with filename information
         using the filename, line, column, and tag information
@@ -412,7 +413,7 @@ def test_formatRootTagWithFilename(self):
             e._formatRoot(t), 'File "tpl.py", line 10, column 20, in "a-tag"'
         )
 
-    def test_string(self):
+    def test_string(self) -> None:
         """
         If a L{FlattenerError} is created with a string root, up to around 40
         bytes from that string are included in the string representation of the
@@ -430,7 +431,7 @@ def test_string(self):
             "RuntimeError: reason\n",
         )
 
-    def test_unicode(self):
+    def test_unicode(self) -> None:
         """
         If a L{FlattenerError} is created with a unicode root, up to around 40
         characters from that string are included in the string representation
@@ -463,7 +464,7 @@ class UnsupportedMethodTests(unittest.SynchronousTestCase):
     Tests for L{UnsupportedMethod}.
     """
 
-    def test_str(self):
+    def test_str(self) -> None:
         """
         The C{__str__} for L{UnsupportedMethod} makes it clear that what it
         shows is a list of the supported methods, not the method that was
diff --git a/src/twisted/web/test/test_html.py b/src/twisted/web/test/test_html.py
--- a/src/twisted/web/test/test_html.py
+++ b/src/twisted/web/test/test_html.py
@@ -10,12 +10,12 @@ class WebHtmlTests(unittest.TestCase):
     Unit tests for L{twisted.web.html}.
     """
 
-    def test_deprecation(self):
+    def test_deprecation(self) -> None:
         """
         Calls to L{twisted.web.html} members emit a deprecation warning.
         """
 
-        def assertDeprecationWarningOf(method):
+        def assertDeprecationWarningOf(method: str) -> None:
             """
             Check that a deprecation warning is present.
             """
diff --git a/src/twisted/web/test/test_http_headers.py b/src/twisted/web/test/test_http_headers.py
--- a/src/twisted/web/test/test_http_headers.py
+++ b/src/twisted/web/test/test_http_headers.py
@@ -4,7 +4,9 @@
 """
 Tests for L{twisted.web.http_headers}.
 """
+from __future__ import annotations
 
+from typing import Sequence
 
 from twisted.trial.unittest import TestCase
 from twisted.web.http_headers import Headers
@@ -15,7 +17,9 @@
 )
 
 
-def assertSanitized(testCase, components, expected):
+def assertSanitized(
+    testCase: TestCase, components: Sequence[bytes] | Sequence[str], expected: bytes
+) -> None:
     """
     Assert that the components are sanitized to the expected value as
     both a header name and value, across all of L{Header}'s setters
@@ -33,7 +37,7 @@ def assertSanitized(testCase, components, expected):
     """
     for component in components:
         headers = []
-        headers.append(Headers({component: [component]}))
+        headers.append(Headers({component: [component]}))  # type: ignore[type-var]
 
         added = Headers()
         added.addRawHeader(component, component)
@@ -55,14 +59,14 @@ class BytesHeadersTests(TestCase):
     Tests for L{Headers}, using L{bytes} arguments for methods.
     """
 
-    def test_sanitizeLinearWhitespace(self):
+    def test_sanitizeLinearWhitespace(self) -> None:
         """
         Linear whitespace in header names or values is replaced with a
         single space.
         """
         assertSanitized(self, bytesLinearWhitespaceComponents, sanitizedBytes)
 
-    def test_initializer(self):
+    def test_initializer(self) -> None:
         """
         The header values passed to L{Headers.__init__} can be retrieved via
         L{Headers.getRawHeaders}.
@@ -70,7 +74,7 @@ def test_initializer(self):
         h = Headers({b"Foo": [b"bar"]})
         self.assertEqual(h.getRawHeaders(b"foo"), [b"bar"])
 
-    def test_setRawHeaders(self):
+    def test_setRawHeaders(self) -> None:
         """
         L{Headers.setRawHeaders} sets the header values for the given
         header name to the sequence of byte string values.
@@ -82,14 +86,14 @@ def test_setRawHeaders(self):
         self.assertTrue(h.hasHeader(b"Test"))
         self.assertEqual(h.getRawHeaders(b"test"), rawValue)
 
-    def test_rawHeadersTypeCheckingValuesIterable(self):
+    def test_rawHeadersTypeCheckingValuesIterable(self) -> None:
         """
         L{Headers.setRawHeaders} requires values to be of type list.
         """
         h = Headers()
         self.assertRaises(TypeError, h.setRawHeaders, b"key", {b"Foo": b"bar"})
 
-    def test_rawHeadersTypeCheckingName(self):
+    def test_rawHeadersTypeCheckingName(self) -> None:
         """
         L{Headers.setRawHeaders} requires C{name} to be a L{bytes} or
         L{str} string.
@@ -101,7 +105,7 @@ def test_rawHeadersTypeCheckingName(self):
             "Header name is an instance of <class 'NoneType'>, " "not bytes or str",
         )
 
-    def test_rawHeadersTypeCheckingValuesAreString(self):
+    def test_rawHeadersTypeCheckingValuesAreString(self) -> None:
         """
         L{Headers.setRawHeaders} requires values to a L{list} of L{bytes} or
         L{str} strings.
@@ -114,7 +118,7 @@ def test_rawHeadersTypeCheckingValuesAreString(self):
             "not bytes or str",
         )
 
-    def test_addRawHeader(self):
+    def test_addRawHeader(self) -> None:
         """
         L{Headers.addRawHeader} adds a new value for a given header.
         """
@@ -124,7 +128,7 @@ def test_addRawHeader(self):
         h.addRawHeader(b"test", b"panda")
         self.assertEqual(h.getRawHeaders(b"test"), [b"lemur", b"panda"])
 
-    def test_addRawHeaderTypeCheckName(self):
+    def test_addRawHeaderTypeCheckName(self) -> None:
         """
         L{Headers.addRawHeader} requires C{name} to be a L{bytes} or L{str}
         string.
@@ -136,7 +140,7 @@ def test_addRawHeaderTypeCheckName(self):
             "Header name is an instance of <class 'NoneType'>, " "not bytes or str",
         )
 
-    def test_addRawHeaderTypeCheckValue(self):
+    def test_addRawHeaderTypeCheckValue(self) -> None:
         """
         L{Headers.addRawHeader} requires value to be a L{bytes} or L{str}
         string.
@@ -148,14 +152,14 @@ def test_addRawHeaderTypeCheckValue(self):
             "Header value is an instance of <class 'NoneType'>, " "not bytes or str",
         )
 
-    def test_getRawHeadersNoDefault(self):
+    def test_getRawHeadersNoDefault(self) -> None:
         """
         L{Headers.getRawHeaders} returns L{None} if the header is not found and
         no default is specified.
         """
         self.assertIsNone(Headers().getRawHeaders(b"test"))
 
-    def test_getRawHeadersDefaultValue(self):
+    def test_getRawHeadersDefaultValue(self) -> None:
         """
         L{Headers.getRawHeaders} returns the specified default value when no
         header is found.
@@ -164,7 +168,7 @@ def test_getRawHeadersDefaultValue(self):
         default = object()
         self.assertIdentical(h.getRawHeaders(b"test", default), default)
 
-    def test_getRawHeadersWithDefaultMatchingValue(self):
+    def test_getRawHeadersWithDefaultMatchingValue(self) -> None:
         """
         If the object passed as the value list to L{Headers.setRawHeaders}
         is later passed as a default to L{Headers.getRawHeaders}, the
@@ -176,7 +180,7 @@ def test_getRawHeadersWithDefaultMatchingValue(self):
         self.assertIsInstance(h.getRawHeaders(b"key", default)[0], bytes)
         self.assertEqual(h.getRawHeaders(b"key", default), [b"value"])
 
-    def test_getRawHeaders(self):
+    def test_getRawHeaders(self) -> None:
         """
         L{Headers.getRawHeaders} returns the values which have been set for a
         given header.
@@ -186,7 +190,7 @@ def test_getRawHeaders(self):
         self.assertEqual(h.getRawHeaders(b"test"), [b"lemur"])
         self.assertEqual(h.getRawHeaders(b"Test"), [b"lemur"])
 
-    def test_hasHeaderTrue(self):
+    def test_hasHeaderTrue(self) -> None:
         """
         Check that L{Headers.hasHeader} returns C{True} when the given header
         is found.
@@ -196,14 +200,14 @@ def test_hasHeaderTrue(self):
         self.assertTrue(h.hasHeader(b"test"))
         self.assertTrue(h.hasHeader(b"Test"))
 
-    def test_hasHeaderFalse(self):
+    def test_hasHeaderFalse(self) -> None:
         """
         L{Headers.hasHeader} returns C{False} when the given header is not
         found.
         """
         self.assertFalse(Headers().hasHeader(b"test"))
 
-    def test_removeHeader(self):
+    def test_removeHeader(self) -> None:
         """
         Check that L{Headers.removeHeader} removes the given header.
         """
@@ -219,7 +223,7 @@ def test_removeHeader(self):
         h.removeHeader(b"Bar")
         self.assertFalse(h.hasHeader(b"bar"))
 
-    def test_removeHeaderDoesntExist(self):
+    def test_removeHeaderDoesntExist(self) -> None:
         """
         L{Headers.removeHeader} is a no-operation when the specified header is
         not found.
@@ -228,7 +232,7 @@ def test_removeHeaderDoesntExist(self):
         h.removeHeader(b"test")
         self.assertEqual(list(h.getAllRawHeaders()), [])
 
-    def test_canonicalNameCaps(self):
+    def test_canonicalNameCaps(self) -> None:
         """
         L{Headers._canonicalNameCaps} returns the canonical capitalization for
         the given header.
@@ -244,7 +248,7 @@ def test_canonicalNameCaps(self):
         self.assertEqual(h._canonicalNameCaps(b"www-authenticate"), b"WWW-Authenticate")
         self.assertEqual(h._canonicalNameCaps(b"x-xss-protection"), b"X-XSS-Protection")
 
-    def test_getAllRawHeaders(self):
+    def test_getAllRawHeaders(self) -> None:
         """
         L{Headers.getAllRawHeaders} returns an iterable of (k, v) pairs, where
         C{k} is the canonicalized representation of the header name, and C{v}
@@ -261,7 +265,7 @@ def test_getAllRawHeaders(self):
             {(b"WWW-Authenticate", (b"basic aksljdlk=",)), (b"Test", (b"lemurs",))},
         )
 
-    def test_headersComparison(self):
+    def test_headersComparison(self) -> None:
         """
         A L{Headers} instance compares equal to itself and to another
         L{Headers} instance with the same values.
@@ -276,7 +280,7 @@ def test_headersComparison(self):
         self.assertEqual(first, second)
         self.assertNotEqual(first, third)
 
-    def test_otherComparison(self):
+    def test_otherComparison(self) -> None:
         """
         An instance of L{Headers} does not compare equal to other unrelated
         objects.
@@ -286,7 +290,7 @@ def test_otherComparison(self):
         self.assertNotEqual(h, object())
         self.assertNotEqual(h, b"foo")
 
-    def test_repr(self):
+    def test_repr(self) -> None:
         """
         The L{repr} of a L{Headers} instance shows the names and values of all
         the headers it contains.
@@ -299,7 +303,7 @@ def test_repr(self):
             f"Headers({{{foo!r}: [{bar!r}, {baz!r}]}})",
         )
 
-    def test_reprWithRawBytes(self):
+    def test_reprWithRawBytes(self) -> None:
         """
         The L{repr} of a L{Headers} instance shows the names and values of all
         the headers it contains, not attempting to decode any raw bytes.
@@ -316,7 +320,7 @@ def test_reprWithRawBytes(self):
             f"Headers({{{foo!r}: [{bar!r}, {baz!r}]}})",
         )
 
-    def test_subclassRepr(self):
+    def test_subclassRepr(self) -> None:
         """
         The L{repr} of an instance of a subclass of L{Headers} uses the name
         of the subclass instead of the string C{"Headers"}.
@@ -333,7 +337,7 @@ class FunnyHeaders(Headers):
             f"FunnyHeaders({{{foo!r}: [{bar!r}, {baz!r}]}})",
         )
 
-    def test_copy(self):
+    def test_copy(self) -> None:
         """
         L{Headers.copy} creates a new independent copy of an existing
         L{Headers} instance, allowing future modifications without impacts
@@ -354,14 +358,14 @@ class UnicodeHeadersTests(TestCase):
     Tests for L{Headers}, using L{str} arguments for methods.
     """
 
-    def test_sanitizeLinearWhitespace(self):
+    def test_sanitizeLinearWhitespace(self) -> None:
         """
         Linear whitespace in header names or values is replaced with a
         single space.
         """
         assertSanitized(self, textLinearWhitespaceComponents, sanitizedBytes)
 
-    def test_initializer(self):
+    def test_initializer(self) -> None:
         """
         The header values passed to L{Headers.__init__} can be retrieved via
         L{Headers.getRawHeaders}. If a L{bytes} argument is given, it returns
@@ -373,7 +377,7 @@ def test_initializer(self):
         self.assertEqual(h.getRawHeaders(b"foo"), [b"bar"])
         self.assertEqual(h.getRawHeaders("foo"), ["bar"])
 
-    def test_setRawHeaders(self):
+    def test_setRawHeaders(self) -> None:
         """
         L{Headers.setRawHeaders} sets the header values for the given
         header name to the sequence of strings, encoded.
@@ -389,7 +393,7 @@ def test_setRawHeaders(self):
         self.assertEqual(h.getRawHeaders("test"), rawValue)
         self.assertEqual(h.getRawHeaders(b"test"), rawEncodedValue)
 
-    def test_nameNotEncodable(self):
+    def test_nameNotEncodable(self) -> None:
         """
         Passing L{str} to any function that takes a header name will encode
         said header name as ISO-8859-1, and if it cannot be encoded, it will
@@ -404,7 +408,7 @@ def test_nameNotEncodable(self):
         with self.assertRaises(UnicodeEncodeError):
             h.hasHeader("\u2603")
 
-    def test_nameEncoding(self):
+    def test_nameEncoding(self) -> None:
         """
         Passing L{str} to any function that takes a header name will encode
         said header name as ISO-8859-1.
@@ -421,7 +425,7 @@ def test_nameEncoding(self):
         # We can still access it using the Unicode string..
         self.assertTrue(h.hasHeader("\u00E1"))
 
-    def test_rawHeadersValueEncoding(self):
+    def test_rawHeadersValueEncoding(self) -> None:
         """
         Passing L{str} to L{Headers.setRawHeaders} will encode the name as
         ISO-8859-1 and values as UTF-8.
@@ -431,14 +435,14 @@ def test_rawHeadersValueEncoding(self):
         self.assertTrue(h.hasHeader(b"\xe1"))
         self.assertEqual(h.getRawHeaders(b"\xe1"), [b"\xe2\x98\x83", b"foo"])
 
-    def test_rawHeadersTypeChecking(self):
+    def test_rawHeadersTypeChecking(self) -> None:
         """
         L{Headers.setRawHeaders} requires values to be of type sequence
         """
         h = Headers()
         self.assertRaises(TypeError, h.setRawHeaders, "key", {"Foo": "bar"})
 
-    def test_addRawHeader(self):
+    def test_addRawHeader(self) -> None:
         """
         L{Headers.addRawHeader} adds a new value for a given header.
         """
@@ -449,14 +453,14 @@ def test_addRawHeader(self):
         self.assertEqual(h.getRawHeaders("test"), ["lemur", "panda"])
         self.assertEqual(h.getRawHeaders(b"test"), [b"lemur", b"panda"])
 
-    def test_getRawHeadersNoDefault(self):
+    def test_getRawHeadersNoDefault(self) -> None:
         """
         L{Headers.getRawHeaders} returns L{None} if the header is not found and
         no default is specified.
         """
         self.assertIsNone(Headers().getRawHeaders("test"))
 
-    def test_getRawHeadersDefaultValue(self):
+    def test_getRawHeadersDefaultValue(self) -> None:
         """
         L{Headers.getRawHeaders} returns the specified default value when no
         header is found.
@@ -471,7 +475,7 @@ def test_getRawHeadersDefaultValue(self):
             ["\N{SNOWMAN}"],
         )
 
-    def test_getRawHeadersWithDefaultMatchingValue(self):
+    def test_getRawHeadersWithDefaultMatchingValue(self) -> None:
         """
         If the object passed as the value list to L{Headers.setRawHeaders}
         is later passed as a default to L{Headers.getRawHeaders}, the
@@ -483,7 +487,7 @@ def test_getRawHeadersWithDefaultMatchingValue(self):
         self.assertIsInstance(h.getRawHeaders("key", default)[0], str)
         self.assertEqual(h.getRawHeaders("key", default), ["value"])
 
-    def test_getRawHeaders(self):
+    def test_getRawHeaders(self) -> None:
         """
         L{Headers.getRawHeaders} returns the values which have been set for a
         given header.
@@ -495,7 +499,7 @@ def test_getRawHeaders(self):
         self.assertEqual(h.getRawHeaders(b"test\xe1"), [b"lemur"])
         self.assertEqual(h.getRawHeaders(b"Test\xe1"), [b"lemur"])
 
-    def test_hasHeaderTrue(self):
+    def test_hasHeaderTrue(self) -> None:
         """
         Check that L{Headers.hasHeader} returns C{True} when the given header
         is found.
@@ -507,14 +511,14 @@ def test_hasHeaderTrue(self):
         self.assertTrue(h.hasHeader(b"test\xe1"))
         self.assertTrue(h.hasHeader(b"Test\xe1"))
 
-    def test_hasHeaderFalse(self):
+    def test_hasHeaderFalse(self) -> None:
         """
         L{Headers.hasHeader} returns C{False} when the given header is not
         found.
         """
         self.assertFalse(Headers().hasHeader("test\u00E1"))
 
-    def test_removeHeader(self):
+    def test_removeHeader(self) -> None:
         """
         Check that L{Headers.removeHeader} removes the given header.
         """
@@ -532,7 +536,7 @@ def test_removeHeader(self):
         self.assertFalse(h.hasHeader("bar"))
         self.assertFalse(h.hasHeader(b"bar"))
 
-    def test_removeHeaderDoesntExist(self):
+    def test_removeHeaderDoesntExist(self) -> None:
         """
         L{Headers.removeHeader} is a no-operation when the specified header is
         not found.
@@ -541,7 +545,7 @@ def test_removeHeaderDoesntExist(self):
         h.removeHeader("test")
         self.assertEqual(list(h.getAllRawHeaders()), [])
 
-    def test_getAllRawHeaders(self):
+    def test_getAllRawHeaders(self) -> None:
         """
         L{Headers.getAllRawHeaders} returns an iterable of (k, v) pairs, where
         C{k} is the canonicalized representation of the header name, and C{v}
@@ -563,7 +567,7 @@ def test_getAllRawHeaders(self):
             },
         )
 
-    def test_headersComparison(self):
+    def test_headersComparison(self) -> None:
         """
         A L{Headers} instance compares equal to itself and to another
         L{Headers} instance with the same values.
@@ -591,7 +595,7 @@ def test_headersComparison(self):
         self.assertEqual(second, secondBytes)
         self.assertEqual(third, thirdBytes)
 
-    def test_otherComparison(self):
+    def test_otherComparison(self) -> None:
         """
         An instance of L{Headers} does not compare equal to other unrelated
         objects.
@@ -601,7 +605,7 @@ def test_otherComparison(self):
         self.assertNotEqual(h, object())
         self.assertNotEqual(h, "foo")
 
-    def test_repr(self):
+    def test_repr(self) -> None:
         """
         The L{repr} of a L{Headers} instance shows the names and values of all
         the headers it contains. This shows only reprs of bytes values, as
@@ -621,7 +625,7 @@ def test_repr(self):
             ),
         )
 
-    def test_subclassRepr(self):
+    def test_subclassRepr(self) -> None:
         """
         The L{repr} of an instance of a subclass of L{Headers} uses the name
         of the subclass instead of the string C{"Headers"}.
@@ -641,7 +645,7 @@ class FunnyHeaders(Headers):
             % (fooEncoded, barEncoded, baz.encode("utf8")),
         )
 
-    def test_copy(self):
+    def test_copy(self) -> None:
         """
         L{Headers.copy} creates a new independent copy of an existing
         L{Headers} instance, allowing future modifications without impacts
diff --git a/src/twisted/web/test/test_script.py b/src/twisted/web/test/test_script.py
--- a/src/twisted/web/test/test_script.py
+++ b/src/twisted/web/test/test_script.py
@@ -7,6 +7,7 @@
 
 import os
 
+from twisted.internet import defer
 from twisted.python.filepath import FilePath
 from twisted.trial.unittest import TestCase
 from twisted.web.http import NOT_FOUND
@@ -20,7 +21,7 @@ class ResourceScriptDirectoryTests(TestCase):
     Tests for L{ResourceScriptDirectory}.
     """
 
-    def test_renderNotFound(self):
+    def test_renderNotFound(self) -> defer.Deferred[None]:
         """
         L{ResourceScriptDirectory.render} sets the HTTP response code to I{NOT
         FOUND}.
@@ -29,13 +30,12 @@ def test_renderNotFound(self):
         request = DummyRequest([b""])
         d = _render(resource, request)
 
-        def cbRendered(ignored):
+        def cbRendered(ignored: object) -> None:
             self.assertEqual(request.responseCode, NOT_FOUND)
 
-        d.addCallback(cbRendered)
-        return d
+        return d.addCallback(cbRendered)
 
-    def test_notFoundChild(self):
+    def test_notFoundChild(self) -> defer.Deferred[None]:
         """
         L{ResourceScriptDirectory.getChild} returns a resource which renders an
         response with the HTTP I{NOT FOUND} status code if the indicated child
@@ -49,13 +49,12 @@ def test_notFoundChild(self):
         child = resource.getChild("foo", request)
         d = _render(child, request)
 
-        def cbRendered(ignored):
+        def cbRendered(ignored: object) -> None:
             self.assertEqual(request.responseCode, NOT_FOUND)
 
-        d.addCallback(cbRendered)
-        return d
+        return d.addCallback(cbRendered)
 
-    def test_render(self):
+    def test_render(self) -> defer.Deferred[None]:
         """
         L{ResourceScriptDirectory.getChild} returns a resource which renders a
         response with the HTTP 200 status code and the content of the rpy's
@@ -77,11 +76,10 @@ def render_GET(self, request):
         child = resource.getChild(b"test.rpy", request)
         d = _render(child, request)
 
-        def cbRendered(ignored):
+        def cbRendered(ignored: object) -> None:
             self.assertEqual(b"".join(request.written), b"ok")
 
-        d.addCallback(cbRendered)
-        return d
+        return d.addCallback(cbRendered)
 
 
 class PythonScriptTests(TestCase):
@@ -89,7 +87,7 @@ class PythonScriptTests(TestCase):
     Tests for L{PythonScript}.
     """
 
-    def test_notFoundRender(self):
+    def test_notFoundRender(self) -> defer.Deferred[None]:
         """
         If the source file a L{PythonScript} is initialized with doesn't exist,
         L{PythonScript.render} sets the HTTP response code to I{NOT FOUND}.
@@ -98,13 +96,12 @@ def test_notFoundRender(self):
         request = DummyRequest([b""])
         d = _render(resource, request)
 
-        def cbRendered(ignored):
+        def cbRendered(ignored: object) -> None:
             self.assertEqual(request.responseCode, NOT_FOUND)
 
-        d.addCallback(cbRendered)
-        return d
+        return d.addCallback(cbRendered)
 
-    def test_renderException(self):
+    def test_renderException(self) -> defer.Deferred[None]:
         """
         L{ResourceScriptDirectory.getChild} returns a resource which renders a
         response with the HTTP 200 status code and the content of the rpy's
@@ -118,8 +115,7 @@ def test_renderException(self):
         request = DummyRequest([b""])
         d = _render(resource, request)
 
-        def cbRendered(ignored):
+        def cbRendered(ignored: object) -> None:
             self.assertIn(b"nooo", b"".join(request.written))
 
-        d.addCallback(cbRendered)
-        return d
+        return d.addCallback(cbRendered)
diff --git a/src/twisted/words/test/test_ircsupport.py b/src/twisted/words/test/test_ircsupport.py
--- a/src/twisted/words/test/test_ircsupport.py
+++ b/src/twisted/words/test/test_ircsupport.py
@@ -48,14 +48,14 @@ class IRCProtoTests(IRCTestCase):
     Tests for L{IRCProto}.
     """
 
-    def setUp(self):
+    def setUp(self) -> None:
         self.account = IRCAccount(
             "Some account", False, "alice", None, "example.com", 6667
         )
         self.proto = IRCProto(self.account, StubChatUI(), None)
         self.transport = StringTransport()
 
-    def test_login(self):
+    def test_login(self) -> None:
         """
         When L{IRCProto} is connected to a transport, it sends I{NICK} and
         I{USER} commands with the username from the account object.
@@ -66,7 +66,7 @@ def test_login(self):
             "NICK alice\r\n" "USER alice foo bar :Twisted-IM user\r\n",
         )
 
-    def test_authenticate(self):
+    def test_authenticate(self) -> None:
         """
         If created with an account with a password, L{IRCProto} sends a
         I{PASS} command before the I{NICK} and I{USER} commands.
@@ -80,7 +80,7 @@ def test_authenticate(self):
             "USER alice foo bar :Twisted-IM user\r\n",
         )
 
-    def test_channels(self):
+    def test_channels(self) -> None:
         """
         If created with an account with a list of channels, L{IRCProto}
         joins each of those channels after registering.
@@ -95,7 +95,7 @@ def test_channels(self):
             "JOIN #bar\r\n",
         )
 
-    def test_isupport(self):
+    def test_isupport(self) -> None:
         """
         L{IRCProto} can interpret I{ISUPPORT} (I{005}) messages from the server
         and reflect their information in its C{supported} attribute.
@@ -104,7 +104,7 @@ def test_isupport(self):
         self.proto.dataReceived(":irc.example.com 005 alice MODES=4 CHANLIMIT=#:20\r\n")
         self.assertEqual(4, self.proto.supported.getFeature("MODES"))
 
-    def test_nick(self):
+    def test_nick(self) -> None:
         """
         IRC NICK command changes the nickname of a user.
         """
@@ -116,7 +116,7 @@ def test_nick(self):
         self.assertIn("newnick", self.proto._ingroups)
         self.assertNotIn("alice1", self.proto._ingroups)
 
-    def test_part(self):
+    def test_part(self) -> None:
         """
         IRC PART command removes a user from an IRC channel.
         """
@@ -130,7 +130,7 @@ def test_part(self):
         self.assertNotIn("group1", self.proto._ingroups["alice1"])
         self.assertNotIn("group2", self.proto._ingroups["alice1"])
 
-    def test_quit(self):
+    def test_quit(self) -> None:
         """
         IRC QUIT command removes a user from all IRC channels.
         """
@@ -144,7 +144,7 @@ def test_quit(self):
         self.assertTrue(len(self.proto._ingroups["alice1"]) == 0)
         self.proto.dataReceived(":alice3 QUIT\r\n")
 
-    def test_topic(self):
+    def test_topic(self) -> None:
         """
         IRC TOPIC command changes the topic of an IRC channel.
         """
@@ -155,7 +155,7 @@ def test_topic(self):
         self.assertEqual(groupConversation.topic, "newtopic")
         self.assertEqual(groupConversation.topicSetBy, "alice1")
 
-    def test_privmsg(self):
+    def test_privmsg(self) -> None:
         """
         PRIVMSG sends a private message to a user or channel.
         """
@@ -175,7 +175,7 @@ def test_privmsg(self):
         conversation = self.proto.chat.getConversation(self.proto.getPerson("alice"))
         self.assertFalse(hasattr(conversation, "message"))
 
-    def test_action(self):
+    def test_action(self) -> None:
         """
         CTCP ACTION to a user or channel.
         """
@@ -195,7 +195,7 @@ def test_action(self):
         conversation = self.proto.chat.getConversation(self.proto.getPerson("alice"))
         self.assertFalse(hasattr(conversation, "message"))
 
-    def test_rplNamreply(self):
+    def test_rplNamreply(self) -> None:
         """
         RPL_NAMREPLY server response (353) lists all the users in a channel.
         RPL_ENDOFNAMES server response (363) is sent at the end of RPL_NAMREPLY
@@ -221,7 +221,7 @@ def test_rplNamreply(self):
         groupConversation = self.proto.getGroupConversation("bnl")
         self.assertEqual(expectedNamReplies["bnl"], groupConversation.members)
 
-    def test_rplTopic(self):
+    def test_rplTopic(self) -> None:
         """
         RPL_TOPIC server response (332) is sent when a channel's topic is changed
         """
@@ -229,7 +229,7 @@ def test_rplTopic(self):
         self.proto.dataReceived(":example.com 332 alice, #foo :Some random topic\r\n")
         self.assertEqual("Some random topic", self.proto._topics["foo"])
 
-    def test_sendMessage(self):
+    def test_sendMessage(self) -> None:
         """
         L{IRCPerson.sendMessage}
         """
@@ -250,7 +250,7 @@ def test_sendMessage(self):
             self.transport.io.getvalue(), b"PRIVMSG alice :\x01ACTION smiles\x01\r\n"
         )
 
-    def test_sendGroupMessage(self):
+    def test_sendGroupMessage(self) -> None:
         """
         L{IRCGroup.sendGroupMessage}
         """
diff --git a/src/twisted/words/test/test_tap.py b/src/twisted/words/test/test_tap.py
--- a/src/twisted/words/test/test_tap.py
+++ b/src/twisted/words/test/test_tap.py
@@ -1,7 +1,11 @@
 # Copyright (c) Twisted Matrix Laboratories.
 # See LICENSE for details.
 
+from __future__ import annotations
+
 from twisted.cred import credentials, error
+from twisted.cred.checkers import FilePasswordDB
+from twisted.internet import defer
 from twisted.trial import unittest
 from twisted.words import tap
 
@@ -15,7 +19,7 @@ class WordsTapTests(unittest.TestCase):
     admin = credentials.UsernamePassword(b"admin", b"admin")
     joeWrong = credentials.UsernamePassword(b"joe", b"bar")
 
-    def setUp(self):
+    def setUp(self) -> None:
         """
         Create a file with two users.
         """
@@ -24,13 +28,13 @@ def setUp(self):
         self.file.write(self.PASSWD_TEXT)
         self.file.flush()
 
-    def tearDown(self):
+    def tearDown(self) -> None:
         """
         Close the dummy user database.
         """
         self.file.close()
 
-    def test_hostname(self):
+    def test_hostname(self) -> None:
         """
         Tests that the --hostname parameter gets passed to Options.
         """
@@ -38,7 +42,7 @@ def test_hostname(self):
         opt.parseOptions(["--hostname", "myhost"])
         self.assertEqual(opt["hostname"], "myhost")
 
-    def test_passwd(self):
+    def test_passwd(self) -> None:
         """
         Tests the --passwd command for backwards-compatibility.
         """
@@ -46,7 +50,7 @@ def test_passwd(self):
         opt.parseOptions(["--passwd", self.file.name])
         self._loginTest(opt)
 
-    def test_auth(self):
+    def test_auth(self) -> None:
         """
         Tests that the --auth command generates a checker.
         """
@@ -54,7 +58,7 @@ def test_auth(self):
         opt.parseOptions(["--auth", "file:" + self.file.name])
         self._loginTest(opt)
 
-    def _loginTest(self, opt):
+    def _loginTest(self, opt: tap.Options) -> defer.Deferred[None]:
         """
         This method executes both positive and negative authentication
         tests against whatever credentials checker has been stored in
@@ -63,12 +67,12 @@ def _loginTest(self, opt):
         @param opt: An instance of L{tap.Options}.
         """
         self.assertEqual(len(opt["credCheckers"]), 1)
-        checker = opt["credCheckers"][0]
+        checker: FilePasswordDB = opt["credCheckers"][0]
         self.assertFailure(
             checker.requestAvatarId(self.joeWrong), error.UnauthorizedLogin
         )
 
-        def _gotAvatar(username):
+        def _gotAvatar(username: bytes | tuple[()]) -> None:
             self.assertEqual(username, self.admin.username)
 
         return checker.requestAvatarId(self.admin).addCallback(_gotAvatar)