Coverage for tests/test_000_accretive/test_200_objects.py: 100%

126 statements  

« prev     ^ index     » next       coverage.py v7.5.4, created at 2024-07-06 17:17 +0000

1# vim: set filetype=python fileencoding=utf-8: 

2# -*- coding: utf-8 -*- 

3 

4#============================================================================# 

5# # 

6# Licensed under the Apache License, Version 2.0 (the "License"); # 

7# you may not use this file except in compliance with the License. # 

8# You may obtain a copy of the License at # 

9# # 

10# http://www.apache.org/licenses/LICENSE-2.0 # 

11# # 

12# Unless required by applicable law or agreed to in writing, software # 

13# distributed under the License is distributed on an "AS IS" BASIS, # 

14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

15# See the License for the specific language governing permissions and # 

16# limitations under the License. # 

17# # 

18#============================================================================# 

19 

20 

21''' Assert correct function of objects. ''' 

22 

23# mypy: ignore-errors 

24# pylint: disable=attribute-defined-outside-init 

25# pylint: disable=invalid-name,magic-value-comparison,protected-access 

26 

27 

28import pytest 

29 

30from itertools import product 

31 

32from . import ( 

33 CONCEALMENT_PACKAGES_NAMES, 

34 MODULES_QNAMES, 

35 PACKAGE_NAME, 

36 PROTECTION_PACKAGES_NAMES, 

37 cache_import_module, 

38) 

39 

40 

41THESE_MODULE_QNAMES = tuple( 

42 name for name in MODULES_QNAMES if name.endswith( '.objects' ) ) 

43THESE_CONCEALMENT_MODULE_QNAMES = tuple( 

44 name for name in THESE_MODULE_QNAMES 

45 if name.startswith( CONCEALMENT_PACKAGES_NAMES ) ) 

46THESE_NONCONCEALMENT_MODULE_QNAMES = tuple( 

47 name for name in THESE_MODULE_QNAMES 

48 if not name.startswith( CONCEALMENT_PACKAGES_NAMES ) ) 

49THESE_PROTECTION_MODULE_QNAMES = tuple( 

50 name for name in THESE_MODULE_QNAMES 

51 if name.startswith( PROTECTION_PACKAGES_NAMES ) ) 

52THESE_NONPROTECTION_MODULE_QNAMES = tuple( 

53 name for name in THESE_MODULE_QNAMES 

54 if not name.startswith( PROTECTION_PACKAGES_NAMES ) ) 

55THESE_CLASSES_NAMES = ( 'Object', ) 

56 

57base = cache_import_module( f"{PACKAGE_NAME}.__" ) 

58exceptions = cache_import_module( f"{PACKAGE_NAME}.exceptions" ) 

59 

60 

61@pytest.mark.parametrize( 

62 'module_qname, class_name', 

63 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

64) 

65def test_100_instantiation( module_qname, class_name ): 

66 ''' Class instantiates. ''' 

67 module = cache_import_module( module_qname ) 

68 Object = getattr( module, class_name ) 

69 obj = Object( ) 

70 assert isinstance( obj, Object ) 

71 

72 

73@pytest.mark.parametrize( 

74 'module_qname, class_name', 

75 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

76) 

77def test_101_accretion( module_qname, class_name ): 

78 ''' Object accretes attributes. ''' 

79 module = cache_import_module( module_qname ) 

80 Object = getattr( module, class_name ) 

81 obj = Object( ) 

82 obj.attr = 42 

83 with pytest.raises( exceptions.IndelibleAttributeError ): 

84 obj.attr = -1 

85 assert 42 == obj.attr 

86 with pytest.raises( exceptions.IndelibleAttributeError ): 

87 del obj.attr 

88 assert 42 == obj.attr 

89 

90 

91@pytest.mark.parametrize( 

92 'module_qname, class_name', 

93 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

94) 

95def test_102_string_representation( module_qname, class_name ): 

96 ''' Object has expected string representations. ''' 

97 module = cache_import_module( module_qname ) 

98 factory = getattr( module, class_name ) 

99 obj = factory( ) 

100 assert base.discover_fqname( obj ) in repr( obj ) 

101 

102 

103@pytest.mark.parametrize( 

104 'module_qname, class_name', 

105 product( THESE_CONCEALMENT_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

106) 

107def test_110_attribute_concealment( module_qname, class_name ): 

108 ''' Object conceals attributes. ''' 

109 module = cache_import_module( module_qname ) 

110 Object = getattr( module, class_name ) 

111 

112 class Concealer( Object ): 

113 ''' test ''' 

114 _attribute_visibility_includes_ = frozenset( ( '_private', ) ) 

115 

116 obj = Concealer( ) 

117 assert not dir( obj ) 

118 obj.public = 42 

119 assert 'public' in dir( obj ) 

120 obj._nonpublic = 3.1415926535 

121 assert '_nonpublic' not in dir( obj ) 

122 assert '_private' not in dir( obj ) 

123 obj._private = 'foo' 

124 assert '_private' in dir( obj ) 

125 

126 

127@pytest.mark.parametrize( 

128 'module_qname, class_name', 

129 product( THESE_NONCONCEALMENT_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

130) 

131def test_111_attribute_nonconcealment( module_qname, class_name ): 

132 ''' Object does not conceal attributes. ''' 

133 module = cache_import_module( module_qname ) 

134 Object = getattr( module, class_name ) 

135 

136 class Concealer( Object ): 

137 ''' test ''' 

138 _attribute_visibility_includes_ = frozenset( ( '_private', ) ) 

139 

140 obj = Concealer( ) 

141 assert '_attribute_visibility_includes_' in dir( obj ) 

142 obj.public = 42 

143 assert 'public' in dir( obj ) 

144 obj._nonpublic = 3.1415926535 

145 assert '_nonpublic' in dir( obj ) 

146 assert '_private' not in dir( obj ) 

147 obj._private = 'foo' 

148 assert '_private' in dir( obj ) 

149 

150 

151@pytest.mark.parametrize( 

152 'module_qname, class_name', 

153 product( THESE_PROTECTION_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

154) 

155def test_150_class_attribute_protection( module_qname, class_name ): 

156 ''' Class attributes are protected. ''' 

157 module = cache_import_module( module_qname ) 

158 Object = getattr( module, class_name ) 

159 with pytest.raises( exceptions.IndelibleAttributeError ): 

160 Object.__setattr__ = None 

161 with pytest.raises( exceptions.IndelibleAttributeError ): 

162 del Object.__setattr__ 

163 Object.foo = 42 

164 with pytest.raises( exceptions.IndelibleAttributeError ): 

165 Object.foo = -1 

166 with pytest.raises( exceptions.IndelibleAttributeError ): 

167 del Object.foo 

168 # Cleanup. 

169 type.__delattr__( Object, 'foo' ) 

170 

171 

172@pytest.mark.parametrize( 

173 'module_qname, class_name', 

174 product( THESE_NONPROTECTION_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

175) 

176def test_151_class_attribute_nonprotection( module_qname, class_name ): 

177 ''' Class attributes are not protected. ''' 

178 module = cache_import_module( module_qname ) 

179 Object = getattr( module, class_name ) 

180 Object.foo = 42 

181 assert 42 == Object.foo 

182 Object.foo = -1 

183 assert -1 == Object.foo 

184 del Object.foo 

185 assert not hasattr( Object, 'foo' ) 

186 

187 

188@pytest.mark.parametrize( 

189 'module_qname, class_name', 

190 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

191) 

192def test_900_docstring_sanity( module_qname, class_name ): 

193 ''' Class has valid docstring. ''' 

194 module = cache_import_module( module_qname ) 

195 Object = getattr( module, class_name ) 

196 assert hasattr( Object, '__doc__' ) 

197 assert isinstance( Object.__doc__, str ) 

198 assert Object.__doc__ 

199 

200 

201@pytest.mark.parametrize( 

202 'module_qname, class_name', 

203 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

204) 

205def test_902_docstring_mentions_accretion( module_qname, class_name ): 

206 ''' Class docstring mentions accretion. ''' 

207 module = cache_import_module( module_qname ) 

208 Object = getattr( module, class_name ) 

209 fragment = base.generate_docstring( 'instance attributes accretion' ) 

210 assert fragment in Object.__doc__ 

211 

212 

213@pytest.mark.parametrize( 

214 'module_qname, class_name', 

215 product( THESE_CONCEALMENT_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

216) 

217def test_910_docstring_mentions_concealment( module_qname, class_name ): 

218 ''' Class docstring mentions concealment. ''' 

219 module = cache_import_module( module_qname ) 

220 Object = getattr( module, class_name ) 

221 fragment = base.generate_docstring( 'instance attributes concealment' ) 

222 assert fragment in Object.__doc__ 

223 

224 

225@pytest.mark.parametrize( 

226 'module_qname, class_name', 

227 product( THESE_NONCONCEALMENT_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

228) 

229def test_911_docstring_not_mentions_concealment( module_qname, class_name ): 

230 ''' Class docstring does not mention concealment. ''' 

231 module = cache_import_module( module_qname ) 

232 Object = getattr( module, class_name ) 

233 fragment = base.generate_docstring( 'instance attributes concealment' ) 

234 assert fragment not in Object.__doc__ 

235 

236 

237@pytest.mark.parametrize( 

238 'module_qname, class_name', 

239 product( THESE_PROTECTION_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

240) 

241def test_930_docstring_mentions_protection( module_qname, class_name ): 

242 ''' Class docstring mentions protection. ''' 

243 module = cache_import_module( module_qname ) 

244 Object = getattr( module, class_name ) 

245 fragment = base.generate_docstring( 'protection of class' ) 

246 assert fragment in Object.__doc__ 

247 

248 

249@pytest.mark.parametrize( 

250 'module_qname, class_name', 

251 product( THESE_NONPROTECTION_MODULE_QNAMES, THESE_CLASSES_NAMES ) 

252) 

253def test_931_docstring_not_mentions_protection( module_qname, class_name ): 

254 ''' Class docstring does not mention protection. ''' 

255 module = cache_import_module( module_qname ) 

256 Object = getattr( module, class_name ) 

257 fragment = base.generate_docstring( 'protection of class' ) 

258 assert fragment not in Object.__doc__