TestCLI   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 139
rs 10
wmc 18

13 Methods

Rating   Name   Duplication   Size   Complexity  
A test_launch_gui() 0 8 1
A test_recommend_download_no_log() 0 15 1
A set_downloads() 0 10 3
A cat() 0 5 2
B test_recommend_download() 0 30 1
A setUp() 0 5 1
A test_duplicate_users() 0 7 1
A log() 0 8 1
A test_interrupt_daemon() 0 8 1
A test_deleting_users() 0 7 1
A dtb() 0 5 1
A tearDown() 0 4 1
A ls() 0 10 3
1
#!/usr/bin/env python
2
3
"""Tests for the dtb.cli module."""
4
5
import unittest
6
from unittest.mock import patch, Mock
7
8
import os
9
import tempfile
10
import shutil
11
import logging
12
13
import yaml
0 ignored issues
show
Configuration introduced by
The import yaml could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
14
15
from dtb.cli import main
16
17
from dtb.tests import ENV, REASON, FAKESONG
18
19
if __name__ == '__main__':
20
    os.environ[ENV] = '1'
21
22
23
@unittest.skipUnless(os.getenv(ENV), REASON)  # pylint: disable=R0904
24
class TestCLI(unittest.TestCase):  # pylint: disable=R0904
25
    """Integration tests for the 'dtb' command-line interface."""
26
27
    def setUp(self):
28
        self.cwd = os.getcwd()
29
        self.root = tempfile.mkdtemp()
30
        self.downloads = tempfile.mkdtemp()
31
        os.chdir(self.root)
32
33
    def tearDown(self):
34
        os.chdir(self.cwd)
35
        shutil.rmtree(self.downloads)
36
        shutil.rmtree(self.root)
37
38
    @staticmethod
39
    def log(msg):
40
        """Header for logging."""
41
        text = '\n\n'
42
        text += '#' * 79 + '\n'
43
        text += '# ' + msg + '\n'
44
        text += '#' * 79 + '\n'
45
        logging.info(text)
46
47
    def set_downloads(self, name):
48
        """Change the downloads directory for the user."""
49
        path = os.path.join(self.root, name, '.dtb', 'info.yml')
50
        with open(path, 'r') as infile:
51
            text = infile.read()
52
        data = yaml.load(text)
53
        data[0]['downloads'] = self.downloads
54
        text = yaml.dump(data)
55
        with open(path, 'w') as outfile:
56
            outfile.write(text)
57
58
    def dtb(self, *args):
59
        """Run the CLI with string arguments."""
60
        args += ('--root', self.root, '-v')
61
        logging.info("$ {}".format(' '.join(args)))
62
        main(args)
63
64
    def ls(self, path, filename, expected=True):  # pylint:disable=C0103
65
        """Display files in a directory and assert a filename exists."""
66
        logging.info("$ ls {}".format(path))
67
        filenames = os.listdir(path)
68
        for fname in filenames:
69
            logging.info(fname)
70
        if expected:
71
            self.assertIn(filename, filenames)
72
        else:
73
            self.assertNotIn(filename, filenames)
74
75
    def cat(self, path, expected):
76
        """Assert the contents of a file."""
77
        with open(path, 'r') as infile:
78
            actual = infile.read()
79
        self.assertEqual(expected, actual)
80
81
    def test_recommend_download(self):
82
        """Verify a song can be shared and downloaded."""
83
        self.log("downloading a shared song")
84
        # Create users
85
        self.dtb('--new', 'JaneDoe')
86
        self.dtb('--new', 'JohnDoe')
87
        self.dtb('--new', 'JaceBrowning')
88
        # Modify their download directory
89
        self.set_downloads('JaneDoe')
90
        self.set_downloads('JohnDoe')
91
        self.set_downloads('JaceBrowning')
92
        # Share a song
93
        self.dtb('--share', FAKESONG, '--test', 'JaceBrowning')
94
        # Show the shared song
95
        self.dtb('--outgoing', '--test', 'JaceBrowning')
96
        # Download the shared song (1)
97
        self.dtb('--incoming', '--test', 'JaneDoe')
98
        self.dtb('--test', 'JaneDoe')
99
        self.ls(self.downloads, 'FakeSong.mp3')
100
        os.remove(os.path.join(self.downloads, 'FakeSong.mp3'))
101
        # Download the shared song (2)
102
        self.dtb('--incoming', '--test', 'JohnDoe')
103
        self.dtb('--test', 'JohnDoe')
104
        self.ls(self.downloads, 'FakeSong.mp3')
105
        # Show that no more songs are shared
106
        self.dtb('--outgoing', '--test', 'JaceBrowning')
107
        # Check the log
108
        self.ls(self.downloads, 'dtb.log')
109
        self.cat(os.path.join(self.downloads, 'dtb.log'),
110
                 "FakeSong.mp3 from JaceBrowning\n"
111
                 "FakeSong.mp3 from JaceBrowning\n")
112
113
    def test_recommend_download_no_log(self):
114
        """Verify a song can be shared and downloaded."""
115
        self.log("downloading a shared song without a log")
116
        # Create users
117
        self.dtb('--new', 'JaneDoe')
118
        self.dtb('--new', 'JohnDoe')
119
        # Modify their download directory
120
        self.set_downloads('JaneDoe')
121
        self.set_downloads('JohnDoe')
122
        # Share a song
123
        self.dtb('--share', FAKESONG, '--test', 'JaneDoe')
124
        # Download the shared song
125
        self.dtb('--no-log', '--test', 'JohnDoe')
126
        # Check for no long
127
        self.ls(self.downloads, 'dtb.log', expected=False)
128
129
    @patch('time.sleep', Mock(side_effect=KeyboardInterrupt))
130
    def test_interrupt_daemon(self):
131
        """Verify the daemon can be interrupted."""
132
        self.log("interrupting the daemon")
133
        # Create user
134
        self.dtb('--new', 'JaceBrowning')
135
        # Run the daemon
136
        self.assertIs(None, self.dtb('--daemon'))
137
138
    def test_duplicate_users(self):
139
        """Verify duplicate users cannot be created."""
140
        self.log("creating a duplicate user")
141
        # Create user
142
        self.dtb('--new', 'JaceBrowning')
143
        # Create user again
144
        self.assertRaises(SystemExit, self.dtb, '--new', 'JaceBrowning')
145
146
    def test_deleting_users(self):
147
        """Verify users can be deleted."""
148
        self.log("deleting a user")
149
        # Create user
150
        self.dtb('--new', 'JaceBrowning')
151
        # Delete user
152
        self.dtb('--delete')
153
154
    @patch('dtb.gui._LAUNCH', False)
155
    def test_launch_gui(self):
156
        """Verify the GUI can be launched."""
157
        self.log("launching the GUI")
158
        # Create user
159
        self.dtb('--new', 'JaceBrowning')
160
        # Launch the GUI
161
        self.dtb('--gui')
162
163
164
@patch('dtb.cli._run', Mock(return_value=True))  # pylint: disable=R0904
165
class TestLogging(unittest.TestCase):  # pylint: disable=R0904
166
    """Integration tests for logging levels."""
167
168
    def test_verbose_0(self):
169
        """Verify verbose level 0 can be set."""
170
        self.assertIs(None, main([]))
171
172
    def test_verbose_1(self):
173
        """Verify verbose level 1 can be set."""
174
        self.assertIs(None, main(['-v']))
175
176
    def test_verbose_2(self):
177
        """Verify verbose level 2 can be set."""
178
        self.assertIs(None, main(['-v', '-v']))
179
180
    def test_verbose_3(self):
181
        """Verify verbose level 3 can be set."""
182
        self.assertIs(None, main(['-v', '-v', '-v']))
183
184
185
if __name__ == '__main__':
186
    logging.basicConfig(format="%(message)s", level=logging.INFO)
187
    unittest.main()
188