Failed Conditions
Pull Request — master (#1431)
by Abdeali
01:34
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
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 = self._execute_bear(local_bear, filename, lines)
90
            if valid:
91
                msg = ("The local bear '{}' yields a result although it "
92
                       "shouldn't.".format(local_bear.__class__.__name__))
93
                self.assertEqual(bear_output, [], msg=msg)
94
            else:
95
                msg = ("The local bear '{}' yields no result although it "
96
                       "should.".format(local_bear.__class__.__name__))
97
                self.assertNotEqual(len(bear_output), 0, msg=msg)
98
99
    def check_results(self,
100
                      local_bear,
101
                      lines,
102
                      results,
103
                      filename="default",
104
                      check_order=False,
105
                      force_linebreaks=True,
106
                      create_tempfile=True):
107
        """
108
        Asserts that a check of the given lines with the given local bear does
109
        yield exactly the given results.
110
111
        :param local_bear:       The local bear to check with.
112
        :param lines:            The lines to check. (string if single line
113
                                                      or List of strings)
114
        :param results:          The expected result or list of results.
115
        :param filename:         The filename, if it matters.
116
        :param force_linebreaks: Whether to append newlines at each line
117
                                 if needed. (Bears expect a \\n for every line)
118
        :param create_tempfile:  Whether to save lines in tempfile if needed.
119
        """
120
        if isinstance(lines, str):
121
            lines = [lines]
122
        if isinstance(results, Result):
123
            results = [results]
124
125
        assert isinstance(self, unittest.TestCase)
126
        self.assertIsInstance(local_bear,
127
                              LocalBear,
128
                              msg="The given bear is not a local bear.")
129
        self.assertIsInstance(lines,
130
                              list,
131
                              msg="The given lines are not a list.")
132
        self.assertIsInstance(results,
133
                              list,
134
                              msg="The given results are not a list.")
135
136
        with prepare_file(lines, filename, force_linebreaks, create_tempfile) \
137
                as (lines, filename):
138
139
            bear_output = self._execute_bear(local_bear, filename, lines)
140
            msg = ("The local bear '{}' doesn't yield the right results. Or the"
141
                   " order may be wrong.".format(local_bear.__class__.__name__))
142
            if not check_order:
143
                self.assertEqual(sorted(bear_output), sorted(results), msg=msg)
144
            else:
145
                self.assertEqual(bear_output, results, msg=msg)
146
147
    def _execute_bear(self, bear, *args, **kwargs):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
148
        try:
149
            bear_output_generator = bear.execute(*args, **kwargs)
150
            assert bear_output_generator is not None
151
        except AssertionError:
152
            msg = []
153
            while not bear.message_queue.empty():
154
                msg.append(bear.message_queue.get().message)
155
            raise AssertionError("Bear returned None on execution \n" +
156
                                 "\n".join(msg))
157
        return list(bear_output_generator)
158
159
def verify_local_bear(bear,
160
                      valid_files,
161
                      invalid_files,
162
                      filename='default',
163
                      settings={},
164
                      force_linebreaks=True,
165
                      create_tempfile=True):
166
    """
167
    Generates a test for a local bear by checking the given valid and invalid
168
    file contents. Simply use it on your module level like:
169
170
    YourTestName = verify_local_bear(YourBear, (['valid line'],),
171
                                     (['invalid line'],))
172
173
    :param bear:             The Bear class to test.
174
    :param valid_files:      An iterable of files as a string list that won't
175
                             yield results.
176
    :param invalid_files:    An iterable of files as a string list that must
177
                             yield results.
178
    :param filename:         The filename to use for valid and invalid files.
179
    :param settings:         A dictionary of keys and values (both string) from
180
                             which settings will be created that will be made
181
                             available for the tested bear.
182
    :param force_linebreaks: Whether to append newlines at each line
183
                             if needed. (Bears expect a \\n for every line)
184
    :param create_tempfile:  Whether to save lines in tempfile if needed.
185
    :return:                 A unittest.TestCase object.
186
    """
187
    @generate_skip_decorator(bear)
188
    class LocalBearTest(LocalBearTestHelper):
189
190
        def setUp(self):
191
            self.section = Section('name')
192
            self.uut = bear(self.section,
193
                            queue.Queue())
194
            for name, value in settings.items():
195
                self.section.append(Setting(name, value))
196
197
        def test_valid_files(self):
198
            for file in valid_files:
199
                self.check_validity(self.uut,
200
                                    file,
201
                                    filename,
202
                                    valid=True,
203
                                    force_linebreaks=force_linebreaks,
204
                                    create_tempfile=create_tempfile)
205
206
        def test_invalid_files(self):
207
            for file in invalid_files:
208
                self.check_validity(self.uut,
209
                                    file,
210
                                    filename,
211
                                    valid=False,
212
                                    force_linebreaks=force_linebreaks,
213
                                    create_tempfile=create_tempfile)
214
215
    return LocalBearTest
216