Completed
Push — develop ( 1caf91...40f9fa )
by Jace
9s
created

TestText.test_dump_yaml_space()   A

Complexity

Conditions 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
"""Unit tests for the doorstop.core.types module."""
2
3
import unittest
4
import yaml
5
6
from doorstop.common import DoorstopError
7
from doorstop.core.types import Prefix, UID, Text, Level, Stamp, Reference
8
9
10
class TestPrefix(unittest.TestCase):
11
    """Unit tests for the Prefix class."""  # pylint: disable=W0212
12
13
    def setUp(self):
14
        self.prefix1 = Prefix('REQ')
15
        self.prefix2 = Prefix('TST (@/tst)')
16
17
    def test_init_empty(self):
18
        """Verify prefixes are parsed correctly (empty)."""
19
        self.assertEqual(Prefix(''), Prefix())
20
        self.assertEqual(Prefix(''), Prefix(None))
21
22
    def test_init_instance(self):
23
        """Verify prefixes are parsed correctly (instance)."""
24
        self.assertIs(self.prefix1, Prefix(self.prefix1))
25
        self.assertEqual(Prefix(''), Prefix(None))
26
        self.assertEqual(Prefix(''), Prefix(''))
27
28
    def test_init_reseved(self):
29
        """Verify an exception is raised for a reserved word."""
30
        self.assertRaises(DoorstopError, Prefix, 'ALL')
31
32
    def test_repr(self):
33
        """Verify prefixes can be represented."""
34
        self.assertEqual("Prefix('REQ')", repr(self.prefix1))
35
        self.assertEqual("Prefix('TST')", repr(self.prefix2))
36
37
    def test_str(self):
38
        """Verify prefixes can be converted to strings."""
39
        self.assertEqual('REQ', str(self.prefix1))
40
        self.assertEqual('TST', str(self.prefix2))
41
42
    def test_eq(self):
43
        """Verify prefixes can be equated."""
44
        self.assertEqual(Prefix('REQ'), self.prefix1)
45
        self.assertNotEqual(self.prefix1, self.prefix2)
46
        self.assertEqual(Prefix('req'), self.prefix1)
47
        self.assertEqual('Req', self.prefix1)
48
        self.assertNotEqual(None, self.prefix1)
49
        self.assertNotEqual('all', self.prefix1)
50
51
    def test_sort(self):
52
        """Verify prefixes can be sorted."""
53
        prefixes = [Prefix('a'), Prefix('B'), Prefix('c')]
54
        self.assertListEqual(prefixes, sorted(prefixes))
55
56
    def test_short(self):
57
        """Verify the short representation of prefixes is correct."""
58
        self.assertEqual('req', self.prefix1.short)
59
        self.assertEqual('tst', self.prefix2.short)
60
61
62
class TestUID(unittest.TestCase):
63
    """Unit tests for the UID class."""  # pylint: disable=W0212
64
65
    def setUp(self):
66
        self.uid1 = UID('REQ001')
67
        self.uid2 = UID('TST-02')
68
        self.uid3 = UID('SYS', '-', 3, 5)
69
        self.uid4 = UID('REQ001', stamp='abc123')
70
71
    def test_init_str(self):
72
        """Verify UIDs are parsed correctly (string)."""
73
        uid = UID('REQ')
74
        self.assertRaises(DoorstopError, getattr, uid, 'prefix')
75
        uid = UID('REQ-?')
76
        self.assertRaises(DoorstopError, getattr, uid, 'number')
77
78
    def test_init_dict(self):
79
        """Verify UIDs are parsed correctly (dictionary)."""
80
        uid = UID({'REQ001': 'abc123'})
81
        self.assertEqual('REQ', uid.prefix)
82
        self.assertEqual(1, uid.number)
83
        self.assertEqual('abc123', uid.stamp)
84
85
    def test_init_values(self):
86
        """Verify UIDs are parsed correctly (values)."""
87
        self.assertRaises(TypeError, UID, 'REQ', '-')
88
        self.assertRaises(TypeError, UID, 'REQ', '-', 42)
89
        self.assertRaises(TypeError, UID, 'REQ', '-', 42, 3, 'extra')
90
91
    def test_init_empty(self):
92
        """Verify UIDs are parsed correctly (empty)."""
93
        self.assertEqual(UID(''), UID())
94
        self.assertEqual(UID(''), UID(None))
95
96
    def test_init_instance(self):
97
        """Verify UIDs are parsed correctly (instance)."""
98
        self.assertIs(self.uid1, UID(self.uid1))
99
        self.assertIs(self.uid4, UID(self.uid4))
100
101
    def test_repr(self):
102
        """Verify UIDs can be represented."""
103
        self.assertEqual("UID('REQ001')", repr(self.uid1))
104
        self.assertEqual("UID('TST-02')", repr(self.uid2))
105
        self.assertEqual("UID('SYS-00003')", repr(self.uid3))
106
        self.assertEqual("UID('REQ001', stamp='abc123')", repr(self.uid4))
107
108
    def test_str(self):
109
        """Verify UIDs can be converted to strings."""
110
        self.assertEqual('REQ001', str(self.uid1))
111
        self.assertEqual('TST-02', str(self.uid2))
112
        self.assertEqual('SYS-00003', str(self.uid3))
113
114
    def test_eq(self):
115
        """Verify UIDs can be equated."""
116
        self.assertEqual(UID('REQ.001'), UID('req', '', 1, 3))
117
        self.assertEqual(UID('REQ1'), UID('REQ', '', 1, 3))
118
        self.assertNotEqual(UID('REQ.2'), UID('REQ', '-', 1, 3))
119
        self.assertEqual(UID('REQ1'), UID('REQ001 (@/req1.yml)'))
120
        self.assertEqual('req1', UID('REQ001'))
121
        self.assertNotEqual(None, UID('REQ001'))
122
        self.assertEqual(self.uid1, self.uid4)
123
124
    def test_sort(self):
125
        """Verify UIDs can be sorted."""
126
        uids = [UID('a'), UID('a1'), UID('a2'), UID('b')]
127
        self.assertListEqual(uids, sorted(uids))
128
129
    def test_prefix(self):
130
        """Verify UIDs have prefixes."""
131
        self.assertEqual('REQ', self.uid1.prefix)
132
        self.assertEqual('TST', self.uid2.prefix)
133
        self.assertEqual('SYS', self.uid3.prefix)
134
135
    def test_number(self):
136
        """Verify UIDs have numbers."""
137
        self.assertEqual(1, self.uid1.number)
138
        self.assertEqual(2, self.uid2.number)
139
        self.assertEqual(3, self.uid3.number)
140
141
    def test_short(self):
142
        """Verify the short representation of IDs is correct."""
143
        self.assertEqual('req1', self.uid1.short)
144
        self.assertEqual('tst2', self.uid2.short)
145
        self.assertEqual('sys3', self.uid3.short)
146
147
    def test_string(self):
148
        """Verify UIDs can be converted to string including stamps."""
149
        self.assertEqual("REQ001", self.uid1.string)
150
        self.assertEqual("REQ001:abc123", self.uid4.string)
151
152
    def test_stamp(self):
153
        """Verify stamps are stored correctly."""
154
        self.assertEqual('abc123', self.uid4.stamp)
155
        self.assertEqual('abc123', UID(self.uid4).stamp)
156
        self.assertEqual('def456', UID(self.uid4, stamp='def456').stamp)
157
        self.assertEqual(True, UID({'REQ001': 1}).stamp)
158
        self.assertEqual(True, UID("REQ001:1").stamp)
159
160
161
class TestText(unittest.TestCase):
162
    """Unit tests for the Text class."""  # pylint: disable=W0212
163
164
    def setUp(self):
165
        self.text = Text("Hello, \nworld! ")
166
167
    def test_init(self):
168
        """Verify Text is parsed correctly."""
169
        self.assertEqual(Text(""), Text())
170
        self.assertEqual(Text(""), Text(None))
171
        self.assertEqual(Text(""), Text(""))
172
173
    def test_repr(self):
174
        """Verify text can be represented."""
175
        self.assertEqual("'Hello, \\nworld!'", repr(self.text))
176
177
    def test_str(self):
178
        """Verify text can be converted to strings."""
179
        self.assertEqual("Hello, \nworld!", str(self.text))
180
181
    def test_eq(self):
182
        """Verify text can be equated."""
183
        self.assertEqual(Text("Hello, \nworld!"), self.text)
184
185
    def test_yaml(self):
186
        """Verify levels can be converted to their YAML representation."""
187
        self.assertEqual('Hello, \nworld!\n', self.text.yaml)
188
189
    def test_dump_yaml(self):
190
        """Verify levels can be converted to their YAML representation."""
191
        text = Text('Hello,\n World!\n')
192
        self.assertEqual('|\n  Hello,\n   World!\n', yaml.dump(text.yaml))
193
194
    def test_dump_yaml_space(self):
195
        """Text starting with a space is encoded to a yaml literal string
196
        with a hint as to the indent."""
197
        text = Text(' abc ')
198
        self.assertEqual('|2\n   abc\n', yaml.dump(text.yaml))
199
200
201
class TestLevel(unittest.TestCase):
202
    """Unit tests for the Level class."""  # pylint: disable=W0212
203
204
    def setUp(self):
205
        self.level_1 = Level('1')
206
        self.level_1_2 = Level('1.2')
207
        self.level_1_2_heading = Level('1.2.0')
208
        self.level_1_2_3 = Level('1.2.3')
209
210
    def test_init(self):
211
        """Verify levels can be parsed."""
212
        self.assertEqual((1, 0), Level((1, 0)).value)
213
        self.assertEqual((1,), Level((1)).value)
214
        self.assertEqual((1, 0), Level(Level('1.0')).value)
215
        self.assertEqual((1, 0), Level(1, heading=True).value)
216
        self.assertEqual((1,), Level((1, 0), heading=False).value)
217
        self.assertEqual((1,), Level())
218
        self.assertEqual((1,), Level(None))
219
        self.assertEqual((1,), Level(()).value)
220
        self.assertEqual((1,), Level(0).value)
221
        self.assertEqual((1,), Level('').value)
222
        self.assertEqual((0,), Level((0,)).value)
223
        self.assertEqual((0,), Level('0').value)
224
        self.assertEqual((0,), Level('0.0').value)
225
226
    def test_repr(self):
227
        """Verify levels can be represented."""
228
        self.assertEqual("Level('1')", repr(self.level_1))
229
        self.assertEqual("Level('1.2')", repr(self.level_1_2))
230
        self.assertEqual("Level('1.2', heading=True)",
231
                         repr(self.level_1_2_heading))
232
        self.assertEqual("Level('1.2.3')", repr(self.level_1_2_3))
233
234
    def test_str(self):
235
        """Verify levels can be converted to strings."""
236
        self.assertEqual('1', str(self.level_1))
237
        self.assertEqual('1.2', str(self.level_1_2))
238
        self.assertEqual('1.2.0', str(self.level_1_2_heading))
239
        self.assertEqual('1.2.3', str(self.level_1_2_3))
240
241
    def test_len(self):
242
        """Verify a level length is equal to number of non-heading parts."""
243
        self.assertEqual(1, len(self.level_1))
244
        self.assertEqual(2, len(self.level_1_2))
245
        self.assertEqual(2, len(self.level_1_2_heading))
246
        self.assertEqual(3, len(self.level_1_2_3))
247
248
    def test_eq(self):
249
        """Verify levels can be equated."""
250
        self.assertNotEqual(self.level_1, self.level_1_2)
251
        self.assertEqual(self.level_1_2, Level([1, 2]))
252
        self.assertEqual(self.level_1_2, (1, 2))
253
        self.assertEqual(self.level_1_2, self.level_1_2_heading)
254
255
    def test_eq_other(self):
256
        """Verify levels can be equated with non-levels."""
257
        self.assertNotEqual(self.level_1, None)
258
        self.assertEqual((1, 2, 0), self.level_1_2_heading)
259
        self.assertEqual((1, 2), self.level_1_2_heading)
260
261
    def test_compare(self):
262
        """Verify levels can be compared."""
263
        self.assertLess(self.level_1, self.level_1_2)
264
        self.assertLessEqual(self.level_1, self.level_1)
265
        self.assertLessEqual(self.level_1, self.level_1_2)
266
        self.assertLess(self.level_1_2, [1, 3])
267
        self.assertGreater(self.level_1_2_3, self.level_1_2)
268
        self.assertGreaterEqual(self.level_1_2_3, self.level_1_2)
269
        self.assertGreaterEqual(self.level_1_2_3, self.level_1_2_3)
270
271
    def test_hash(self):
272
        """Verify level's can be hashed."""
273
        levels = {Level('1.2'): 1, Level('1.2.3'): 2}
274
        self.assertIn(self.level_1_2, levels)
275
        self.assertNotIn(self.level_1_2_heading, levels)
276
277
    def test_add(self):
278
        """Verify levels can be incremented."""
279
        level = self.level_1_2
280
        level += 1
281
        self.assertEqual(Level('1.3'), level)
282
        self.assertEqual(Level('1.5'), level + 2)
283
284
    def test_add_heading(self):
285
        """Verify (heading) levels can be incremented."""
286
        level = self.level_1_2_heading
287
        level += 2
288
        self.assertEqual(Level('1.4.0'), level)
289
290
    def test_sub(self):
291
        """Verify levels can be decremented."""
292
        level = self.level_1_2_3
293
        level -= 1
294
        self.assertEqual(Level('1.2.2'), level)
295
        self.assertEqual(Level('1.2.1'), level - 1)
296
297
    def test_sub_heading(self):
298
        """Verify (heading) levels can be decremented."""
299
        level = self.level_1_2_heading
300
        level -= 1
301
        self.assertEqual(Level('1.1.0'), level)
302
303
    def test_sub_zero(self):
304
        """Verify levels cannot be decremented to zero."""
305
        level = self.level_1_2
306
        level -= 2
307
        self.assertEqual(Level('1.1'), level)
308
309
    def test_rshift(self):
310
        """Verify levels can be indented."""
311
        level = self.level_1_2
312
        level >>= 1
313
        self.assertEqual(Level('1.2.1'), level)
314
        self.assertEqual(Level('1.2.1.1'), level >> 1)
315
316
    def test_rshift_heading(self):
317
        """Verify (heading) levels can be indented."""
318
        level = self.level_1_2_heading
319
        level >>= 2
320
        self.assertEqual(Level('1.2.1.1.0'), level)
321
322
    def test_rshift_negative(self):
323
        """Verify levels can be indented negatively."""
324
        level = self.level_1_2_3
325
        level >>= -1
326
        self.assertEqual(Level('1.2'), level)
327
        self.assertEqual(Level('1'), level >> -1)
328
329
    def test_lshift(self):
330
        """Verify levels can be dedented."""
331
        level = self.level_1_2_3
332
        level <<= 1
333
        self.assertEqual(Level('1.2'), level)
334
        self.assertEqual(Level('1'), level << 1)
335
336
    def test_lshift_heading(self):
337
        """Verify (heading) levels can be dedented."""
338
        level = self.level_1_2_heading
339
        level <<= 1
340
        self.assertEqual(Level('1.0'), level)
341
342
    def test_lshift_negative(self):
343
        """Verify levels can be dedented negatively."""
344
        level = self.level_1_2_3
345
        level <<= -1
346
        self.assertEqual(Level('1.2.3.1'), level)
347
        self.assertEqual(Level('1.2.3.1.1'), level << -1)
348
349
    def test_lshift_empty(self):
350
        """Verify levels can be dedented."""
351
        level = self.level_1_2_3
352
        level <<= 4
353
        self.assertEqual(Level('1'), level)
354
355
    def test_lshift_zero(self):
356
        """Verify detenting levels by zero has no effect.."""
357
        level = self.level_1_2_3
358
        level <<= 0
359
        self.assertEqual(Level('1.2.3'), level)
360
361
    def test_value(self):
362
        """Verify levels can be converted to their values."""
363
        self.assertEqual((1,), self.level_1.value)
364
        self.assertEqual((1, 2), self.level_1_2.value)
365
        self.assertEqual((1, 2, 0), self.level_1_2_heading.value)
366
        self.assertEqual((1, 2, 3), self.level_1_2_3.value)
367
368
    def test_yaml(self):
369
        """Verify levels can be converted to their YAML representation."""
370
        self.assertEqual(1, self.level_1.yaml)
371
        self.assertEqual(1.2, self.level_1_2.yaml)
372
        self.assertEqual('1.2.0', self.level_1_2_heading.yaml)
373
        self.assertEqual('1.2.3', self.level_1_2_3.yaml)
374
375
    def test_copy(self):
376
        """Verify levels can be copied."""
377
        level = self.level_1_2.copy()
378
        self.assertEqual(level, self.level_1_2)
379
        level += 1
380
        self.assertNotEqual(level, self.level_1_2)
381
382
383
class TestStamp(unittest.TestCase):
384
    """Unit tests for the Stamp class."""  # pylint: disable=W0212
385
386
    def setUp(self):
387
        self.stamp1 = Stamp('abc123')
388
        self.stamp2 = Stamp("Hello, world!", 42, False)
389
        self.stamp3 = Stamp(True)
390
        self.stamp4 = Stamp(False)
391
        self.stamp5 = Stamp()
392
393
    def test_repr(self):
394
        """Verify stamps can be represented."""
395
        self.assertEqual("Stamp('abc123')", repr(self.stamp1))
396
        self.assertEqual("Stamp('2645439971b8090da05c7403320afcfa')",
397
                         repr(self.stamp2))
398
        self.assertEqual("Stamp(True)", repr(self.stamp3))
399
        self.assertEqual("Stamp(None)", repr(self.stamp4))
400
        self.assertEqual("Stamp(None)", repr(self.stamp5))
401
402
    def test_str(self):
403
        """Verify stamps can be converted to strings."""
404
        self.assertEqual('abc123', str(self.stamp1))
405
        self.assertEqual('2645439971b8090da05c7403320afcfa', str(self.stamp2))
406
        self.assertEqual('', str(self.stamp3))
407
        self.assertEqual('', str(self.stamp4))
408
        self.assertEqual('', str(self.stamp5))
409
410
    def test_bool(self):
411
        """Verify stamps can be converted to boolean."""
412
        self.assertTrue(self.stamp1)
413
        self.assertTrue(self.stamp2)
414
        self.assertTrue(self.stamp3)
415
        self.assertFalse(self.stamp4)
416
        self.assertFalse(self.stamp5)
417
418
    def test_eq(self):
419
        """Verify stamps can be equated."""
420
        self.assertEqual('abc123', self.stamp1)
421
        self.assertEqual('2645439971b8090da05c7403320afcfa', self.stamp2)
422
        self.assertEqual(True, self.stamp3)
423
        self.assertEqual(None, self.stamp4)
424
        self.assertNotEqual(self.stamp1, self.stamp2)
425
        self.assertNotEqual(self.stamp3, self.stamp4)
426
        self.assertEqual(self.stamp4, self.stamp5)
427
428
    def test_yaml(self):
429
        """Verify stamps can be converted to their YAML dump format."""
430
        self.assertEqual('abc123', self.stamp1.yaml)
431
        self.assertEqual('2645439971b8090da05c7403320afcfa', self.stamp2.yaml)
432
        self.assertEqual(True, self.stamp3.yaml)
433
        self.assertEqual(None, self.stamp4.yaml)
434
        self.assertEqual(None, self.stamp5.yaml)
435
436
437
class TestReference(unittest.TestCase):
438
    """Unit tests for the Reference class."""
439
440
    def setUp(self):
441
        self.ref1 = Reference('abc123')
442
        self.ref2 = Reference('path/to/external.txt', 5, 10)
443
        self.ref2 = Reference('path/to/external.dat', None, None)
444
        self.ref3 = Reference()
445