Completed
Pull Request — master (#1431)
by Abdeali
01:41
created

bears.tests.prepare_file()   F

Complexity

Conditions 10

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 10
dl 0
loc 30
rs 3.1304

How to fix   Complexity   

Complexity

Complex classes like bears.tests.prepare_file() 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
from contextlib import contextmanager
2
from queue import Queue
3
from tempfile import NamedTemporaryFile
4
import unittest
5
6
from coalib.bears.LocalBear import LocalBear
7
from coalib.results.Result import Result
8
from coalib.settings.Section import Section
9
from coalib.settings.Setting import Setting
10
from bears.tests.BearTestHelper import generate_skip_decorator
11
12
13
@contextmanager
14
def prepare_file(lines, filename, force_linebreaks, create_tempfile):
15
    """
16
    Can creates a temporary file (if filename is None) with the lines.
17
    Can also add a trailing newline to each line specified if needed.
18
19
    :param lines:            The lines from the file. (list of strings)
20
    :param filename:         The filename to be prepared.
21
                              - If it is None, A new tempfile will be created
22
                                (if create_tempfile is True).
23
                              - If it is a string, use it as the filename.
24
                              - If it is a dictionary, it is passed as kwargs
25
                                to NamedTemporaryFile.
26
    :param force_linebreaks: Whether to append newlines at each line if needed.
27
    :param create_tempfile:  Whether to save lines in tempfile if needed.
28
    """
29
    if force_linebreaks:
30
        for i, line in enumerate(lines):
31
            lines[i] = line if line.endswith("\n") else line + "\n"
32
33
    if not create_tempfile and filename is None:
34
        filename = "dummy_file_name"
35
36
    if not isinstance(filename, str) and create_tempfile:
37
        tempfile_kwargs = {} if filename is None else filename
38
        with NamedTemporaryFile(**tempfile_kwargs) as file:
39
            file.write(bytes("".join(lines), 'UTF-8'))
40
            yield lines, file.name
41
    else:
42
        yield lines, filename
43
44
45
class LocalBearTestHelper(unittest.TestCase):  # pragma: no cover
46
    """
47
    This is a helper class for simplification of testing of local bears.
48
49
    Please note that all abstraction will prepare the lines so you don't need
50
    to do that if you use them.
51
52
    If you miss some methods, get in contact with us, we'll be happy to help!
53
    """
54
55
    def check_validity(self,
56
                       local_bear,
57
                       lines,
58
                       filename="default",
59
                       valid=True,
60
                       force_linebreaks=True,
61
                       create_tempfile=True):
62
        """
63
        Asserts that a check of the given lines with the given local bear
64
        either yields or does not yield any results.
65
66
        :param local_bear:       The local bear to check with.
67
        :param lines:            The lines to check. (string if single line
68
                                                      or List of strings)
69
        :param filename:         The filename, if it matters.
70
        :param valid:            Whether the lines are valid or not.
71
        :param force_linebreaks: Whether to append newlines at each line
72
                                 if needed. (Bears expect a \\n for every line)
73
        :param create_tempfile:  Whether to save lines in tempfile if needed.
74
        """
75
        if isinstance(lines, str):
76
            lines = [lines]
77
78
        assert isinstance(self, unittest.TestCase)
79
        self.assertIsInstance(local_bear,
80
                              LocalBear,
81
                              msg="The given bear is not a local bear.")
82
        self.assertIsInstance(lines,
83
                              list,
84
                              msg="The given lines are not a list.")
85
86
        with prepare_file(lines, filename, force_linebreaks, create_tempfile) \
87
                as (lines, filename):
88
89
            bear_output = list(local_bear.execute(filename, lines))
90
91
            if valid:
92
                msg = ("The local bear '{}' yields a result although it "
93
                       "shouldn't.".format(local_bear.__class__.__name__))
94
                self.assertEqual(bear_output, [], msg=msg)
95
            else:
96
                msg = ("The local bear '{}' yields no result although it "
97
                       "should.".format(local_bear.__class__.__name__))
98
                self.assertNotEqual(len(bear_output), 0, msg=msg)
99
100
    def check_results(self,
101
                      local_bear,
102
                      lines,
103
                      results,
104
                      filename="default",
105
                      check_order=False,
106
                      force_linebreaks=True,
107
                      create_tempfile=True):
108
        """
109
        Asserts that a check of the given lines with the given local bear does
110
        yield exactly the given results.
111
112
        :param local_bear:       The local bear to check with.
113
        :param lines:            The lines to check. (string if single line
114
                                                      or List of strings)
115
        :param results:          The expected result or list of results.
116
        :param filename:         The filename, if it matters.
117
        :param force_linebreaks: Whether to append newlines at each line
118
                                 if needed. (Bears expect a \\n for every line)
119
        :param create_tempfile:  Whether to save lines in tempfile if needed.
120
        """
121
        if isinstance(lines, str):
122
            lines = [lines]
123
        if isinstance(results, Result):
124
            results = [results]
125
126
        assert isinstance(self, unittest.TestCase)
127
        self.assertIsInstance(local_bear,
128
                              LocalBear,
129
                              msg="The given bear is not a local bear.")
130
        self.assertIsInstance(lines,
131
                              list,
132
                              msg="The given lines are not a list.")
133
        self.assertIsInstance(results,
134
                              list,
135
                              msg="The given results are not a list.")
136
137
        with prepare_file(lines, filename, force_linebreaks, create_tempfile) \
138
                as (lines, filename):
139
140
            msg = ("The local bear '{}' doesn't yield the right results. Or the"
141
                   " order may be wrong.".format(local_bear.__class__.__name__))
142
            bear_output = list(local_bear.execute(filename, lines))
143
144
            if not check_order:
145
                self.assertEqual(sorted(bear_output), sorted(results), msg=msg)
146
            else:
147
                self.assertEqual(bear_output, results, msg=msg)
148
149
150
def verify_local_bear(bear,
151
                      valid_files,
152
                      invalid_files,
153
                      filename='default',
154
                      settings={},
155
                      force_linebreaks=True,
156
                      create_tempfile=True):
157
    """
158
    Generates a test for a local bear by checking the given valid and invalid
159
    file contents. Simply use it on your module level like:
160
161
    YourTestName = verify_local_bear(YourBear, (['valid line'],),
162
                                     (['invalid line'],))
163
164
    :param bear:             The Bear class to test.
165
    :param valid_files:      An iterable of files as a string list that won't
166
                             yield results.
167
    :param invalid_files:    An iterable of files as a string list that must
168
                             yield results.
169
    :param filename:         The filename to use for valid and invalid files.
170
    :param settings:         A dictionary of keys and values (both string) from
171
                             which settings will be created that will be made
172
                             available for the tested bear.
173
    :param force_linebreaks: Whether to append newlines at each line
174
                             if needed. (Bears expect a \\n for every line)
175
    :param create_tempfile:  Whether to save lines in tempfile if needed.
176
    :return:                 A unittest.TestCase object.
177
    """
178
    @generate_skip_decorator(bear)
179
    class LocalBearTest(LocalBearTestHelper):
180
181
        def setUp(self):
182
            self.section = Section('name')
183
            self.uut = bear(self.section, Queue())
184
            for name, value in settings.items():
185
                self.section.append(Setting(name, value))
186
187
        def test_valid_files(self):
188
            for file in valid_files:
189
                self.check_validity(self.uut,
190
                                    file,
191
                                    filename,
192
                                    valid=True,
193
                                    force_linebreaks=force_linebreaks,
194
                                    create_tempfile=create_tempfile)
195
196
        def test_invalid_files(self):
197
            for file in invalid_files:
198
                self.check_validity(self.uut,
199
                                    file,
200
                                    filename,
201
                                    valid=False,
202
                                    force_linebreaks=force_linebreaks,
203
                                    create_tempfile=create_tempfile)
204
205
    return LocalBearTest
206