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

bears.tests.LocalBearTestHelper.assertLinesValid()   B

Complexity

Conditions 3

Size

Total Lines 33

Duplication

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