blob: e6c84154fe1f089c3a6606038eb882f24f458948 [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001# Copyright 2007 Google, Inc. All Rights Reserved.
2# Licensed to PSF under a Contributor Agreement.
3
4"""Unit tests for abc.py."""
5
6import sys
7import unittest
8from test import test_support
9
10import abc
11
12
13class TestABC(unittest.TestCase):
14
15 def test_abstractmethod_basics(self):
16 @abc.abstractmethod
17 def foo(self): pass
18 self.assertEqual(foo.__isabstractmethod__, True)
19 def bar(self): pass
20 self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
21
Guido van Rossum70d2b892007-08-01 17:52:23 +000022 def test_abstractproperty_basics(self):
23 @abc.abstractproperty
24 def foo(self): pass
25 self.assertEqual(foo.__isabstractmethod__, True)
26 def bar(self): pass
27 self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
28
Guido van Rossumcd16bf62007-06-13 18:07:49 +000029 class C(metaclass=abc.ABCMeta):
Guido van Rossum70d2b892007-08-01 17:52:23 +000030 @abc.abstractproperty
31 def foo(self): return 3
Guido van Rossumcd16bf62007-06-13 18:07:49 +000032 class D(C):
Guido van Rossum70d2b892007-08-01 17:52:23 +000033 @property
34 def foo(self): return super().foo
35 self.assertEqual(D().foo, 3)
36
37 def test_abstractmethod_integration(self):
38 for abstractthing in [abc.abstractmethod, abc.abstractproperty]:
39 class C(metaclass=abc.ABCMeta):
40 @abstractthing
41 def foo(self): pass # abstract
42 def bar(self): pass # concrete
43 self.assertEqual(C.__abstractmethods__, {"foo"})
44 self.assertRaises(TypeError, C) # because foo is abstract
45 class D(C):
46 def bar(self): pass # concrete override of concrete
47 self.assertEqual(D.__abstractmethods__, {"foo"})
48 self.assertRaises(TypeError, D) # because foo is still abstract
49 class E(D):
50 def foo(self): pass
51 self.assertEqual(E.__abstractmethods__, set())
52 E() # now foo is concrete, too
53 class F(E):
54 @abstractthing
55 def bar(self): pass # abstract override of concrete
56 self.assertEqual(F.__abstractmethods__, {"bar"})
57 self.assertRaises(TypeError, F) # because bar is abstract now
Guido van Rossumcd16bf62007-06-13 18:07:49 +000058
59 def test_registration_basics(self):
60 class A(metaclass=abc.ABCMeta):
61 pass
62 class B:
63 pass
64 b = B()
65 self.assertEqual(issubclass(B, A), False)
66 self.assertEqual(isinstance(b, A), False)
67 A.register(B)
68 self.assertEqual(issubclass(B, A), True)
69 self.assertEqual(isinstance(b, A), True)
70 class C(B):
71 pass
72 c = C()
73 self.assertEqual(issubclass(C, A), True)
74 self.assertEqual(isinstance(c, A), True)
75
76 def test_registration_builtins(self):
77 class A(metaclass=abc.ABCMeta):
78 pass
79 A.register(int)
80 self.assertEqual(isinstance(42, A), True)
81 self.assertEqual(issubclass(int, A), True)
82 class B(A):
83 pass
Guido van Rossum3172c5d2007-10-16 18:12:55 +000084 B.register(str)
85 class C(str): pass
Guido van Rossumcd16bf62007-06-13 18:07:49 +000086 self.assertEqual(isinstance("", A), True)
87 self.assertEqual(issubclass(str, A), True)
Guido van Rossum3172c5d2007-10-16 18:12:55 +000088 self.assertEqual(issubclass(C, A), True)
Guido van Rossumcd16bf62007-06-13 18:07:49 +000089
90 def test_registration_edge_cases(self):
91 class A(metaclass=abc.ABCMeta):
92 pass
93 A.register(A) # should pass silently
94 class A1(A):
95 pass
96 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
97 class B:
98 pass
99 A1.register(B) # ok
100 A1.register(B) # should pass silently
101 class C(A):
102 pass
103 A.register(C) # should pass silently
104 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
105 C.register(B) # ok
106
107 def test_registration_transitiveness(self):
108 class A(metaclass=abc.ABCMeta):
109 pass
110 self.failUnless(issubclass(A, A))
111 class B(metaclass=abc.ABCMeta):
112 pass
113 self.failIf(issubclass(A, B))
114 self.failIf(issubclass(B, A))
115 class C(metaclass=abc.ABCMeta):
116 pass
117 A.register(B)
118 class B1(B):
119 pass
120 self.failUnless(issubclass(B1, A))
121 class C1(C):
122 pass
123 B1.register(C1)
124 self.failIf(issubclass(C, B))
125 self.failIf(issubclass(C, B1))
126 self.failUnless(issubclass(C1, A))
127 self.failUnless(issubclass(C1, B))
128 self.failUnless(issubclass(C1, B1))
129 C1.register(int)
130 class MyInt(int):
131 pass
132 self.failUnless(issubclass(MyInt, A))
133 self.failUnless(isinstance(42, A))
134
Guido van Rossum894d35e2007-09-11 20:42:30 +0000135 def test_all_new_methods_are_called(self):
136 class A(metaclass=abc.ABCMeta):
137 pass
138 class B:
139 counter = 0
140 def __new__(cls):
141 B.counter += 1
142 return super().__new__(cls)
143 class C(A, B):
144 pass
145 self.assertEqual(B.counter, 0)
146 C()
147 self.assertEqual(B.counter, 1)
148
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000149
150def test_main():
151 test_support.run_unittest(TestABC)
152
153
154if __name__ == "__main__":
155 unittest.main()