| Total Complexity | 46 |
| Total Lines | 191 |
| Duplicated Lines | 51.31 % |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | """Integration tests for the package.""" |
||
| 154 | class TestStandard: |
||
| 155 | """Integration tests for standard attribute types.""" |
||
| 156 | |||
| 157 | @yorm.attr(status=yorm.types.Boolean) |
||
| 158 | class StatusDictionary(Dictionary): |
||
| 159 | pass |
||
| 160 | |||
| 161 | def test_decorator(self, tmpdir): |
||
| 162 | """Verify standard attribute types dump/load correctly (decorator).""" |
||
| 163 | tmpdir.chdir() |
||
| 164 | sample = SampleStandardDecorated('sample') |
||
| 165 | assert "path/to/default/sample.yml" == sample.__mapper__.path |
||
| 166 | |||
| 167 | log.info("Checking object default values...") |
||
| 168 | assert {} == sample.object |
||
| 169 | assert [] == sample.array |
||
| 170 | assert "" == sample.string |
||
| 171 | assert 0 == sample.number_int |
||
| 172 | assert 0.0 == sample.number_real |
||
| 173 | assert True is sample.truthy |
||
| 174 | assert False is sample.falsey |
||
| 175 | assert None is sample.null |
||
| 176 | |||
| 177 | log.info("Changing object values...") |
||
| 178 | sample.object = {'key2': 'value'} |
||
| 179 | sample.array = [0, 1, 2] |
||
| 180 | sample.string = "Hello, world!" |
||
| 181 | sample.number_int = 42 |
||
| 182 | sample.number_real = 4.2 |
||
| 183 | sample.truthy = False |
||
| 184 | sample.falsey = True |
||
| 185 | |||
| 186 | log.info("Checking file contents...") |
||
| 187 | assert strip(""" |
||
| 188 | array: |
||
| 189 | - 0 |
||
| 190 | - 1 |
||
| 191 | - 2 |
||
| 192 | falsey: true |
||
| 193 | number_int: 42 |
||
| 194 | number_real: 4.2 |
||
| 195 | object: {} |
||
| 196 | string: Hello, world! |
||
| 197 | truthy: false |
||
| 198 | """) == sample.__mapper__.text |
||
| 199 | |||
| 200 | log.info("Changing file contents...") |
||
| 201 | refresh_file_modification_times() |
||
| 202 | sample.__mapper__.text = strip(""" |
||
| 203 | array: [4, 5, 6] |
||
| 204 | falsey: null |
||
| 205 | number_int: 42 |
||
| 206 | number_real: '4.2' |
||
| 207 | object: {'status': false} |
||
| 208 | string: "abc" |
||
| 209 | truthy: null |
||
| 210 | """) |
||
| 211 | |||
| 212 | log.info("Checking object values...") |
||
| 213 | assert {'status': False} == sample.object |
||
| 214 | assert [4, 5, 6] == sample.array |
||
| 215 | assert "abc" == sample.string |
||
| 216 | assert 42 == sample.number_int |
||
| 217 | assert 4.2 == sample.number_real |
||
| 218 | assert False is sample.truthy |
||
| 219 | assert False is sample.falsey |
||
| 220 | |||
| 221 | View Code Duplication | def test_function(self, tmpdir): |
|
| 222 | """Verify standard attribute types dump/load correctly (function).""" |
||
| 223 | tmpdir.chdir() |
||
| 224 | _sample = SampleStandard() |
||
| 225 | attrs = {'object': self.StatusDictionary, |
||
| 226 | 'array': IntegerList, |
||
| 227 | 'string': String, |
||
| 228 | 'number_int': Integer, |
||
| 229 | 'number_real': Float, |
||
| 230 | 'truthy': Boolean, |
||
| 231 | 'falsey': Boolean} |
||
| 232 | sample = yorm.sync(_sample, "path/to/directory/sample.yml", attrs) |
||
| 233 | assert "path/to/directory/sample.yml" == sample.__mapper__.path |
||
| 234 | |||
| 235 | # check defaults |
||
| 236 | assert {'status': False} == sample.object |
||
| 237 | assert [] == sample.array |
||
| 238 | assert "" == sample.string |
||
| 239 | assert 0 == sample.number_int |
||
| 240 | assert 0.0 == sample.number_real |
||
| 241 | assert True is sample.truthy |
||
| 242 | assert False is sample.falsey |
||
| 243 | assert None is sample.null |
||
| 244 | |||
| 245 | # change object values |
||
| 246 | sample.object = {'key': 'value'} |
||
| 247 | sample.array = [1, 2, 3] |
||
| 248 | sample.string = "Hello, world!" |
||
| 249 | sample.number_int = 42 |
||
| 250 | sample.number_real = 4.2 |
||
| 251 | sample.truthy = None |
||
| 252 | sample.falsey = 1 |
||
| 253 | |||
| 254 | # check file values |
||
| 255 | assert strip(""" |
||
| 256 | array: |
||
| 257 | - 1 |
||
| 258 | - 2 |
||
| 259 | - 3 |
||
| 260 | falsey: true |
||
| 261 | number_int: 42 |
||
| 262 | number_real: 4.2 |
||
| 263 | object: |
||
| 264 | status: false |
||
| 265 | string: Hello, world! |
||
| 266 | truthy: false |
||
| 267 | """) == sample.__mapper__.text |
||
| 268 | |||
| 269 | View Code Duplication | def test_function_to_json(self, tmpdir): |
|
| 270 | """Verify standard attribute types dump/load correctly (function).""" |
||
| 271 | tmpdir.chdir() |
||
| 272 | _sample = SampleStandard() |
||
| 273 | attrs = {'object': self.StatusDictionary, |
||
| 274 | 'array': IntegerList, |
||
| 275 | 'string': String, |
||
| 276 | 'number_int': Integer, |
||
| 277 | 'number_real': Float, |
||
| 278 | 'truthy': Boolean, |
||
| 279 | 'falsey': Boolean} |
||
| 280 | sample = yorm.sync(_sample, "path/to/directory/sample.json", attrs) |
||
| 281 | assert "path/to/directory/sample.json" == sample.__mapper__.path |
||
| 282 | |||
| 283 | # check defaults |
||
| 284 | assert {'status': False} == sample.object |
||
| 285 | assert [] == sample.array |
||
| 286 | assert "" == sample.string |
||
| 287 | assert 0 == sample.number_int |
||
| 288 | assert 0.0 == sample.number_real |
||
| 289 | assert True is sample.truthy |
||
| 290 | assert False is sample.falsey |
||
| 291 | assert None is sample.null |
||
| 292 | |||
| 293 | # change object values |
||
| 294 | sample.object = {'key': 'value'} |
||
| 295 | sample.array = [1, 2, 3] |
||
| 296 | sample.string = "Hello, world!" |
||
| 297 | sample.number_int = 42 |
||
| 298 | sample.number_real = 4.2 |
||
| 299 | sample.truthy = None |
||
| 300 | sample.falsey = 1 |
||
| 301 | |||
| 302 | # check file values |
||
| 303 | assert strip(""" |
||
| 304 | { |
||
| 305 | "array": [ |
||
| 306 | 1, |
||
| 307 | 2, |
||
| 308 | 3 |
||
| 309 | ], |
||
| 310 | "falsey": true, |
||
| 311 | "number_int": 42, |
||
| 312 | "number_real": 4.2, |
||
| 313 | "object": { |
||
| 314 | "status": false |
||
| 315 | }, |
||
| 316 | "string": "Hello, world!", |
||
| 317 | "truthy": false |
||
| 318 | } |
||
| 319 | """, tabs=2, end='') == sample.__mapper__.text |
||
| 320 | |||
| 321 | def test_auto_off(self, tmpdir): |
||
| 322 | """Verify file updates are disabled with auto off.""" |
||
| 323 | tmpdir.chdir() |
||
| 324 | sample = SampleDecoratedAutoOff() |
||
| 325 | |||
| 326 | # ensure the file does not exist |
||
| 327 | assert False is sample.__mapper__.exists |
||
| 328 | assert "" == sample.__mapper__.text |
||
| 329 | |||
| 330 | # store value |
||
| 331 | sample.string = "hello" |
||
| 332 | |||
| 333 | # ensure the file still does not exist |
||
| 334 | assert False is sample.__mapper__.exists |
||
| 335 | assert "" == sample.__mapper__.text |
||
| 336 | |||
| 337 | # enable auto and store value |
||
| 338 | sample.__mapper__.auto = True |
||
| 339 | sample.string = "world" |
||
| 340 | |||
| 341 | # check for changed file values |
||
| 342 | assert strip(""" |
||
| 343 | string: world |
||
| 344 | """) == sample.__mapper__.text |
||
| 345 | |||
| 496 |