TestSong   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Importance

Changes 5
Bugs 1 Features 0
Metric Value
c 5
b 1
f 0
dl 0
loc 106
rs 10
wmc 22

18 Methods

Rating   Name   Duplication   Size   Complexity  
A test_source_file_bad() 0 3 1
A test_source_song() 0 3 1
A test_str() 0 3 1
A tearDown() 0 5 3
A test_download_song() 0 7 1
A test_download_broken() 0 6 1
A test_out_string() 0 4 1
A test_download_invalid_dest() 0 6 1
A setUp() 0 7 1
A test_link_missing_directory() 0 5 1
A test_source_file() 0 3 1
A test_download_error_uncaught() 0 4 1
A test_source_link() 0 3 1
A test_download_link() 0 7 1
A test_download_error_caught() 0 4 1
A test_in_string() 0 4 1
A test_ignore() 0 5 1
A test_link() 0 7 3
1
#!/usr/bin/env python
2
3
"""Unit tests for the dtb.song module."""
4
5
import unittest
6
from unittest.mock import patch, Mock
7
8
import os
9
import tempfile
10
import shutil
11
12
from dtb.song import Song
13
14
from dtb.tests import EMPTY
15
from dtb.tests import FAKESONG, FAKELINK, FAKEFILE, BADFAKEFILE, BROKENLINK
16
17
18
class TestSong(unittest.TestCase):  # pylint: disable=R0904
19
    """Unit tests for the Song class."""  # pylint: disable=C0103,W0212
20
21
    def setUp(self):
22
        self.temp = tempfile.mkdtemp()
23
        self.song = Song(FAKESONG, downloads=self.temp, friendname='Jace')
24
        self.link = Song(FAKELINK, downloads=self.temp, friendname='Jace')
25
        self.file = Song(FAKEFILE, downloads=self.temp, friendname='Jace')
26
        self.bad = Song(BADFAKEFILE, downloads=self.temp, friendname='Jace')
27
        self.broken = Song(BROKENLINK, downloads=self.temp, friendname='Jace')
28
29
    def tearDown(self):
30
        shutil.rmtree(self.temp)
31
        for name in os.listdir(EMPTY):
32
            if name != '.gitignore':
33
                os.remove(os.path.join(EMPTY, name))
34
35
    def test_str(self):
36
        """Verify a song can be converted to string."""
37
        self.assertEqual(FAKESONG, str(self.song))
38
39
    def test_in_string(self):
40
        """Verify an incoming song can be presented."""
41
        text = "FakeSong.mp3 (from Jace)"
42
        self.assertEqual(text, self.song.in_string)
43
44
    def test_out_string(self):
45
        """Verify an outgoing song can be presented."""
46
        text = "FakeSong.mp3 (to Jace)"
47
        self.assertEqual(text, self.song.out_string)
48
49
    def test_link(self):
50
        """Verify a link to a song can be created."""
51
        self.song.link(EMPTY)
52
        filename = [f for f in os.listdir(EMPTY) if f.endswith('.yml')][0]
53
        link = Song(os.path.join(EMPTY, filename))
54
        self.assertEqual(link.source, self.song.path)
55
        self.assertTrue(os.path.isfile(link.path))
56
57
    def test_link_missing_directory(self):
58
        """Verify a link can be created even when the directory is gone."""
59
        temp = tempfile.mkdtemp()
60
        shutil.rmtree(temp)
61
        self.song.link(temp)
62
63
    def test_source_song(self):
64
        """Verify a direct song can be followed."""
65
        self.assertEqual(self.song.path, self.link.source)
66
67
    def test_source_link(self):
68
        """Verify a link can be followed."""
69
        self.assertEqual(self.song.path, self.song.source)
70
71
    def test_source_file(self):
72
        """Verify a non-link YAML file can be followed."""
73
        self.assertEqual(self.file.path, self.file.source)
74
75
    def test_source_file_bad(self):
76
        """Verify a non-link invalid YAML is handled."""
77
        self.assertEqual(self.bad.path, self.bad.source)
78
79
    @patch('os.remove')
80
    def test_download_song(self, mock_remove):
81
        """Verify a song can be downloaded."""
82
        self.song.download()
83
        path = os.path.join(self.temp, 'FakeSong.mp3')
84
        self.assertTrue(os.path.isfile(path))
85
        mock_remove.assert_called_once_with(self.song.path)
86
87
    @patch('os.remove')
88
    def test_download_link(self, mock_remove):
89
        """Verify a linked song can be downloaded."""
90
        self.link.download()
91
        path = os.path.join(self.temp, 'FakeSong.mp3')
92
        self.assertTrue(os.path.isfile(path))
93
        mock_remove.assert_called_once_with(self.link.path)
94
95
    @patch('os.remove')
96
    def test_download_broken(self, mock_remove):
97
        """Verify a broken link cannot be downloaded."""
98
        self.broken.download()
99
        self.assertEqual(0, len(os.listdir(self.temp)))
100
        mock_remove.assert_called_once_with(self.broken.path)
101
102
    @patch('os.remove', Mock(side_effect=IOError))
103
    def test_download_error_caught(self):
104
        """Verify errors are caught while downloading."""
105
        self.song.download()
106
107
    @patch('os.remove', Mock(side_effect=IOError))
108
    def test_download_error_uncaught(self):
109
        """Verify errors are not caught while downloading if requested."""
110
        self.assertRaises(IOError, self.song.download, catch=False)
111
112
    @patch('os.remove')
113
    @patch('os.path.isdir', Mock(return_value=False))
114
    def test_download_invalid_dest(self, mock_remove):
115
        """Verify downloads are only attempted with a valid destination."""
116
        self.song.download()
117
        self.assertFalse(mock_remove.called)
118
119
    @patch('os.remove')
120
    def test_ignore(self, mock_remove):
121
        """Verify a song can be ignored."""
122
        self.song.ignore()
123
        mock_remove.assert_called_once_with(self.song.path)
124
125
126
if __name__ == '__main__':
127
    unittest.main()
128