Failed Conditions
Pull Request — master (#1371)
by Abdeali
01:38
created

bears.tests.prepare()   F

Complexity

Conditions 10

Size

Total Lines 32

Duplication

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

How to fix   Complexity   

Complexity

Complex classes like bears.tests.prepare() 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, closing
0 ignored issues
show
Unused Code introduced by
Unused closing imported from contextlib
Loading history...
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(lines, filename, prepare_lines, prepare_file):
15
    """
16
    Creates a temporary file (if filename is None) and saves the
17
    lines to it. Also adds a trailing newline to each line if needed.
18
19
    :param lines:         The lines to be prepared.
20
    :param filename:      The filename to be prepared.
21
                           - If it is None, A new tempfile will be created
22
                             (if prepare_file allows it).
23
                           - If it is a string, that is used as the filename.
24
                           - If it is a dictionary, it is passed as kwargs
25
                             to NamedTemporaryFile.
26
    :param prepare_lines: Whether to append newlines at each line if needed.
27
    :param prepare_file:  Whether to save lines in tempfile if needed.
28
    """
29
    if prepare_lines:
30
        for i, line in enumerate(lines):
31
            lines[i] = line if line.endswith("\n") else line + "\n"
32
33
    if not prepare_file and filename is None:
34
        filename = "dummy_file_name"
35
36
    if not isinstance(filename, str) and prepare_file:
37
        temp_file_kwargs = {}
38
        if isinstance(filename, dict):
39
            temp_file_kwargs = filename
40
        with NamedTemporaryFile(**temp_file_kwargs) as file:
41
            file.write(bytes("".join(lines), 'UTF-8'))
42
            yield lines, file.name
43
    else:
44
        yield lines, filename
45
46
47
class LocalBearTestHelper(unittest.TestCase):  # pragma: no cover
48
    """
49
    This is a helper class for simplification of testing of local bears.
50
51
    Please note that all abstraction will prepare the lines so you don't need
52
    to do that if you use them.
53
54
    If you miss some methods, get in contact with us, we'll be happy to help!
55
    """
56
    def check_valid(self,
57
                    local_bear,
58
                    lines,
59
                    filename,
60
                    valid=True,
61
                    prepare_lines=True,
62
                    prepare_file=True):
63
        """
64
        Asserts that a check of the given lines with the given local bear does
65
        not yield any results.
66
67
        :param local_bear:    The local bear to check with.
68
        :param lines:         The lines to check. (string or List of strings)
69
        :param filename:      The filename, if it matters.
70
        :param valid:         Whether the lines are valid or not.
71
        :param prepare_lines: Whether to append newlines at each line if
72
                              needed. Use this with caution when disabling,
73
                              since bears expect to have a \n at the end of
74
                              each line.
75
        :param prepare_file:  Whether to create tempfile is filename is None.
76
                              Use this with caution when disabling, since
77
                              some bears read the filename directly.
78
        """
79
        if isinstance(lines, str):
80
            lines = [lines]
81
82
        assert isinstance(self, unittest.TestCase)
83
        self.assertIsInstance(local_bear,
84
                              LocalBear,
85
                              msg="The given bear is not a local bear.")
86
        self.assertIsInstance(lines,
87
                              list,
88
                              msg="The given lines are not a list.")
89
90
        with prepare(lines, filename, prepare_lines, prepare_file) \
91
             as (lines, filename):
92
            if valid:
93
                self.assertEqual(
94
                    list(local_bear.execute(filename, lines)),
95
                    [],
96
                    msg="The local bear '{}' yields a result although it "
97
                        "shouldn't.".format(local_bear.__class__.__name__))
98
            else:
99
                self.assertNotEqual(
100
                    len(list(local_bear.execute(filename, lines))),
101
                    0,
102
                    msg="The local bear '{}' yields no result although it "
103
                        "should.".format(local_bear.__class__.__name__))
104
105
    def check_results(self,
106
                      local_bear,
107
                      lines,
108
                      filename,
109
                      results=[],
110
                      check_order=False,
111
                      prepare_lines=True,
112
                      prepare_file=True):
113
        """
114
        Asserts that a check of the given line with the given local bear does
115
        yield exactly the given results.
116
117
        :param local_bear:    The local bear to check with.
118
        :param lines:         The lines to check. (string or List of strings)
119
        :param filename:      The filename, if it matters.
120
        :param results:       The expected results.
121
        :param check_order:   Assert also that the results are in the same
122
                              order (defaults to False)
123
        :param prepare_lines: Whether to append newlines at each line if
124
                              needed. Use this with caution when disabling,
125
                              since bears expect to have a \n at the end of
126
                              each line.
127
        :param prepare_file:  Whether to create tempfile is filename is None.
128
                              Use this with caution when disabling, since
129
                              some bears read the filename directly.
130
        """
131
        if isinstance(lines, str):
132
            lines = [lines]
133
        if isinstance(results, Result):
134
            results = [results]
135
136
        assert isinstance(self, unittest.TestCase)
137
        self.assertIsInstance(local_bear,
138
                              LocalBear,
139
                              msg="The given bear is not a local bear.")
140
        self.assertIsInstance(lines,
141
                              list,
142
                              msg="The given lines are not a list.")
143
        self.assertIsInstance(results,
144
                              list,
145
                              msg="The given results are not a list.")
146
147
        msg = ("The local bear '{}' doesn't yield the right results or the "
148
               "order may be wrong.".format(local_bear.__class__.__name__))
149
        with prepare(lines, filename, prepare_lines, prepare_file) \
150
             as (lines, filename):
151
            if not check_order:
152
                self.assertEqual(sorted(local_bear.execute(filename, lines)),
153
                                 sorted(results),
154
                                 msg=msg)
155
            else:
156
                self.assertEqual(list(local_bear.execute(filename, lines)),
157
                                 results,
158
                                 msg=msg)
159
160
161
def verify_local_bear(bear,
162
                      valid_files=(),
163
                      invalid_files=(),
164
                      filename=None,
165
                      settings={}):
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
                           - If it is None, A new tempfile will be created
180
                             (if prepare_file allows it).
181
                           - If it is a string, that is used as the filename.
182
                           - If it is a dictionary, it is passed as kwargs
183
                             to NamedTemporaryFile.
184
    :param settings:      A dictionary of keys and values (both string) from
185
                          which settings will be created that will be made
186
                          available for the tested bear.
187
    :return:              A unittest.TestCase object.
188
    """
189
    @generate_skip_decorator(bear)
190
    class LocalBearTest(LocalBearTestHelper):
191
192
        def setUp(self):
193
            self.section = Section('name')
194
            self.uut = bear(self.section, Queue())
195
            for name, value in settings.items():
196
                self.section.append(Setting(name, value))
197
198
        def test_valid_files(self):
199
            for file in valid_files:
200
                self.check_valid(self.uut, file, filename, valid=True)
201
202
        def test_invalid_files(self):
203
            for file in invalid_files:
204
                self.check_valid(self.uut, file, filename, valid=False)
205
206
    return LocalBearTest
207