Browse Source

Improve performance by multithreading test calls

This change:
1) rewrites the runner to spawn a thread pool for each template
   and assigns a worker for each test case
2) makes the output colorized by default
3) makes minor changes to the output

Change-Id: I49906f5daaa339ca9429913680203c762a0ad9fe
tags/0.4.0^0
Michael Dong 1 year ago
parent
commit
c4586a374b

+ 2
- 1
syntribos/clients/http/base_http_client.py View File

@@ -80,4 +80,5 @@ class HTTPClient(object):
80 80
              'data': data}, **requestslib_kwargs)
81 81
 
82 82
         # Make the request
83
-        return requests.request(method, url, **requestslib_kwargs)
83
+        return requests.request(method, url, allow_redirects=False,
84
+                                **requestslib_kwargs)

+ 1
- 1
syntribos/clients/http/client.py View File

@@ -53,7 +53,7 @@ class SynHTTPClient(HTTPClient):
53 53
         return (response, signals)
54 54
 
55 55
     def send_request(self, request_obj):
56
-        """This sends a request based on a RequestOjbect.
56
+        """This sends a request based on a RequestObject.
57 57
 
58 58
         RequestObjects are generated by a parser (e.g.
59 59
         :class:`syntribos.clients.http.parser.RequestCreator`) from request

+ 23
- 20
syntribos/clients/http/debug_logger.py View File

@@ -17,6 +17,7 @@
17 17
 # limitations under the License.
18 18
 from copy import deepcopy
19 19
 import logging
20
+import threading
20 21
 from time import time
21 22
 
22 23
 import requests
@@ -27,6 +28,8 @@ import syntribos.checks.http as http_checks
27 28
 import syntribos.signal
28 29
 from syntribos.utils import string_utils
29 30
 
31
+lock = threading.Lock()
32
+
30 33
 
31 34
 def log_http_transaction(log, level=logging.DEBUG):
32 35
     """Decorator used for logging requests/response in clients.
@@ -59,20 +62,13 @@ def log_http_transaction(log, level=logging.DEBUG):
59 62
             sent to the request() method, to the provided log at the provided
60 63
             log level.
61 64
             """
65
+
62 66
             kwargs_copy = deepcopy(kwargs)
63 67
             if kwargs_copy.get("sanitize"):
64 68
                 kwargs_copy = string_utils.sanitize_secrets(kwargs_copy)
65
-            logline = '{0} {1}'.format(args, string_utils.compress(
69
+            logline_obj = '{0} {1}'.format(args, string_utils.compress(
66 70
                 kwargs_copy))
67 71
 
68
-            try:
69
-                log.debug(_safe_decode(logline))
70
-            except Exception as exception:
71
-                # Ignore all exceptions that happen in logging, then log them
72
-                log.info('Exception occurred while logging signature of '
73
-                         'calling method in http client')
74
-                log.exception(exception)
75
-
76 72
             # Make the request and time its execution
77 73
             response = None
78 74
             no_resp_time = None
@@ -132,7 +128,7 @@ def log_http_transaction(log, level=logging.DEBUG):
132 128
                 request_headers = string_utils.sanitize_secrets(
133 129
                     request_headers)
134 130
                 request_body = string_utils.sanitize_secrets(request_body)
135
-            logline = ''.join([
131
+            logline_req = ''.join([
136 132
                 '\n{0}\nREQUEST SENT\n{0}\n'.format('-' * 12),
137 133
                 'request method.......: {0}\n'.format(response.request.method),
138 134
                 'request url..........: {0}\n'.format(string_utils.compress(
@@ -145,15 +141,7 @@ def log_http_transaction(log, level=logging.DEBUG):
145 141
                 'request body size....: {0}\n'.format(req_body_len),
146 142
                 'request body.........: {0}\n'.format(string_utils.compress
147 143
                                                       (request_body))])
148
-
149
-            try:
150
-                log.log(level, _safe_decode(logline))
151
-            except Exception as exception:
152
-                # Ignore all exceptions that happen in logging, then log them
153
-                log.log(level, '\n{0}\nREQUEST INFO\n{0}\n'.format('-' * 12))
154
-                log.exception(exception)
155
-
156
-            logline = ''.join([
144
+            logline_rsp = ''.join([
157 145
                 '\n{0}\nRESPONSE RECEIVED\n{0}\n'.format('-' * 17),
158 146
                 'response status..: {0}\n'.format(response),
159 147
                 'response headers.: {0}\n'.format(response.headers),
@@ -162,12 +150,27 @@ def log_http_transaction(log, level=logging.DEBUG):
162 150
                 'response size....: {0}\n'.format(len(response.content)),
163 151
                 'response body....: {0}\n'.format(response_content),
164 152
                 '-' * 79])
153
+            lock.acquire()
154
+            try:
155
+                log.log(level, _safe_decode(logline_req))
156
+            except Exception as exception:
157
+                # Ignore all exceptions that happen in logging, then log them
158
+                log.log(level, '\n{0}\nREQUEST INFO\n{0}\n'.format('-' * 12))
159
+                log.exception(exception)
165 160
             try:
166
-                log.log(level, _safe_decode(logline))
161
+                log.log(level, _safe_decode(logline_rsp))
167 162
             except Exception as exception:
168 163
                 # Ignore all exceptions that happen in logging, then log them
169 164
                 log.log(level, '\n{0}\nRESPONSE INFO\n{0}\n'.format('-' * 13))
170 165
                 log.exception(exception)
166
+            try:
167
+                log.debug(_safe_decode(logline_obj))
168
+            except Exception as exception:
169
+                # Ignore all exceptions that happen in logging, then log them
170
+                log.info('Exception occurred while logging signature of '
171
+                         'calling method in http client')
172
+                log.exception(exception)
173
+            lock.release()
171 174
             return (response, signals)
172 175
         return _wrapper
173 176
     return _decorator

+ 6
- 1
syntribos/config.py View File

@@ -157,7 +157,8 @@ def list_cli_opts():
157 157
                         default=[""], sample_default=["SQL", "XSS"],
158 158
                         help=_("Test types to be excluded from "
159 159
                                "current run against the target API")),
160
-        cfg.BoolOpt("colorize", dest="colorize", short="cl", default=False,
160
+        cfg.BoolOpt("no_colorize", dest="no_colorize", short="ncl",
161
+                    default=False,
161 162
                     help=_("Enable color in syntribos terminal output")),
162 163
         cfg.StrOpt("outfile", short="o",
163 164
                    sample_default="out.json", help=_("File to print "
@@ -194,6 +195,10 @@ def list_syntribos_opts():
194 195
         cfg.StrOpt("endpoint", default="",
195 196
                    sample_default="http://localhost/app",
196 197
                    help=_("The target host to be tested")),
198
+        cfg.IntOpt("threads", default=16,
199
+                   sample_default="16",
200
+                   help=_("Maximum number of threads syntribos spawns "
201
+                          "(experimental)")),
197 202
         cfg.Opt("templates", type=ContentType("r", 0),
198 203
                 default="",
199 204
                 sample_default="~/.syntribos/templates",

+ 29
- 15
syntribos/result.py View File

@@ -11,6 +11,7 @@
11 11
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 12
 # See the License for the specific language governing permissions and
13 13
 # limitations under the License.
14
+import threading
14 15
 import time
15 16
 import unittest
16 17
 
@@ -23,6 +24,7 @@ from syntribos.runner import Runner
23 24
 import syntribos.utils.remotes
24 25
 
25 26
 CONF = cfg.CONF
27
+lock = threading.Lock()
26 28
 
27 29
 
28 30
 class IssueTestResult(unittest.TextTestResult):
@@ -38,7 +40,7 @@ class IssueTestResult(unittest.TextTestResult):
38 40
         "MEDIUM": 0,
39 41
         "HIGH": 0
40 42
     }
41
-    stats = {"errors": 0, "failures": 0, "successes": 0}
43
+    stats = {"errors": 0, "unique_failures": 0, "successes": 0}
42 44
     severity_counter_dict = {}
43 45
     testsRunSinceLastPrint = 0
44 46
     failure_id = 0
@@ -84,6 +86,7 @@ class IssueTestResult(unittest.TextTestResult):
84 86
         :type test: :class:`syntribos.tests.base.BaseTestCase`
85 87
         :param tuple err: Tuple of format ``(type, value, traceback)``
86 88
         """
89
+        lock.acquire()
87 90
         for issue in test.failures:
88 91
             defect_type = issue.defect_type
89 92
             if any([
@@ -174,7 +177,7 @@ class IssueTestResult(unittest.TextTestResult):
174 177
                         "signals": signals
175 178
                     }
176 179
                     failure_obj["instances"].append(instance_obj)
177
-                    self.stats["failures"] += 1
180
+                    self.stats["unique_failures"] += 1
178 181
                     self.output["stats"]["severity"][sev_rating] += 1
179 182
             else:
180 183
                 instance_obj = None
@@ -196,8 +199,9 @@ class IssueTestResult(unittest.TextTestResult):
196 199
                         "signals": signals
197 200
                     }
198 201
                     failure_obj["instances"].append(instance_obj)
199
-                    self.stats["failures"] += 1
202
+                    self.stats["unique_failures"] += 1
200 203
                     self.output["stats"]["severity"][sev_rating] += 1
204
+        lock.release()
201 205
 
202 206
     def addError(self, test, err):
203 207
         """Duplicates parent class addError functionality.
@@ -207,11 +211,19 @@ class IssueTestResult(unittest.TextTestResult):
207 211
         :param err:
208 212
         :type tuple: Tuple of format ``(type, value, traceback)``
209 213
         """
210
-        self.errors.append({
211
-            "test": self.getDescription(test),
212
-            "error": self._exc_info_to_string(err, test)
213
-        })
214
-        self.stats["errors"] += 1
214
+        with lock:
215
+            for e in self.errors:
216
+                if e['error'] == self._exc_info_to_string(err, test):
217
+                    if self.getDescription(test) in e['test']:
218
+                        return
219
+                    e['test'].append(self.getDescription(test))
220
+                    self.stats["errors"] += 1
221
+                    return
222
+            self.errors.append({
223
+                "test": [self.getDescription(test)],
224
+                "error": self._exc_info_to_string(err, test)
225
+            })
226
+            self.stats["errors"] += 1
215 227
 
216 228
     def addSuccess(self, test):
217 229
         """Duplicates parent class addSuccess functionality.
@@ -219,7 +231,8 @@ class IssueTestResult(unittest.TextTestResult):
219 231
         :param test: The test that was run
220 232
         :type test: :class:`syntribos.tests.base.BaseTestCase`
221 233
         """
222
-        self.stats["successes"] += 1
234
+        with lock:
235
+            self.stats["successes"] += 1
223 236
 
224 237
     def printErrors(self, output_format):
225 238
         """Print out each :class:`syntribos.issue.Issue` that was encountered
@@ -241,18 +254,19 @@ class IssueTestResult(unittest.TextTestResult):
241 254
         """Print the path to the log folder for this run."""
242 255
         test_log = Runner.log_path
243 256
         run_time = time.time() - start_time
244
-        num_fail = self.stats["failures"]
257
+        num_fail = self.stats["unique_failures"]
245 258
         num_err = self.stats["errors"]
246 259
         print("\n{sep}\nTotal: Ran {num} test{suff} in {time:.3f}s".format(
247 260
             sep=syntribos.SEP,
248 261
             num=self.testsRun,
249 262
             suff="s" * bool(self.testsRun - 1),
250 263
             time=run_time))
251
-        print("Total: {f} failure{fsuff} and {e} error{esuff}".format(
252
-            f=num_fail,
253
-            e=num_err,
254
-            fsuff="s" * bool(num_fail - 1),
255
-            esuff="s" * bool(num_err - 1)))
264
+        print("Total: {f} unique failure{fsuff} "
265
+              "and {e} unique error{esuff}".format(
266
+                  f=num_fail,
267
+                  e=num_err,
268
+                  fsuff="s" * bool(num_fail - 1),
269
+                  esuff="s" * bool(num_err - 1)))
256 270
         if test_log:
257 271
             print(syntribos.SEP)
258 272
             print(_("LOG PATH...: %s") % test_log)

+ 45
- 41
syntribos/runner.py View File

@@ -13,9 +13,11 @@
13 13
 # limitations under the License.
14 14
 import json
15 15
 import logging
16
+from multiprocessing.dummy import Pool as ThreadPool
16 17
 import os
17 18
 import pkgutil
18 19
 import sys
20
+import threading
19 21
 import time
20 22
 import traceback
21 23
 import unittest
@@ -39,6 +41,7 @@ result = None
39 41
 user_base_dir = None
40 42
 CONF = cfg.CONF
41 43
 LOG = logging.getLogger(__name__)
44
+lock = threading.Lock()
42 45
 
43 46
 
44 47
 class Runner(object):
@@ -125,6 +128,7 @@ class Runner(object):
125 128
         LOG = logging.getLogger()
126 129
         LOG.handlers = [log_handle]
127 130
         LOG.setLevel(logging.DEBUG)
131
+        logging.getLogger("urllib3").setLevel(logging.WARNING)
128 132
         return LOG
129 133
 
130 134
     @classmethod
@@ -258,7 +262,6 @@ class Runner(object):
258 262
                     cls.meta_dir_dict[meta_path] = json.loads(file_content)
259 263
                 except Exception:
260 264
                     print("Unable to parse %s, skipping..." % file_path)
261
-
262 265
         for file_path, req_str in templates_dir:
263 266
             if "meta.json" in file_path:
264 267
                 continue
@@ -331,7 +334,7 @@ class Runner(object):
331 334
             if len(test_cases) > 0:
332 335
                 for test in test_cases:
333 336
                     if test:
334
-                        cls.run_test(test, result)
337
+                        cls.run_test(test)
335 338
 
336 339
     @classmethod
337 340
     def dry_run_report(cls, output):
@@ -359,6 +362,7 @@ class Runner(object):
359 362
 
360 363
         :return: None
361 364
         """
365
+        pool = ThreadPool(CONF.syntribos.threads)
362 366
         try:
363 367
             template_start_time = time.time()
364 368
             failures = 0
@@ -367,19 +371,18 @@ class Runner(object):
367 371
             for test_name, test_class in list_of_tests:
368 372
                 test_class.test_id = cls.current_test_id
369 373
                 cls.current_test_id += 5
370
-                log_string = "[{test_id}]  :  {name}".format(
371
-                    test_id=test_class.test_id, name=test_name)
374
+
372 375
                 result_string = "[{test_id}]  :  {name}".format(
373 376
                     test_id=cli.colorize(
374 377
                         test_class.test_id, color="green"),
375 378
                     name=test_name.replace("_", " ").capitalize())
376
-                if not CONF.colorize:
379
+                if CONF.no_colorize:
377 380
                     result_string = result_string.ljust(55)
378 381
                 else:
379 382
                     result_string = result_string.ljust(60)
380
-                LOG.debug(log_string)
381 383
                 try:
382
-                    test_class.send_init_request(file_path, req_str, meta_vars)
384
+                    test_class.create_init_request(file_path, req_str,
385
+                                                   meta_vars)
383 386
                 except Exception:
384 387
                     print(_(
385 388
                         "Error in parsing template:\n %s\n"
@@ -388,40 +391,33 @@ class Runner(object):
388 391
                     break
389 392
                 test_cases = list(
390 393
                     test_class.get_test_cases(file_path, req_str))
391
-                if len(test_cases) > 0:
394
+                total_tests = len(test_cases)
395
+                if total_tests > 0:
396
+                    log_string = "[{test_id}]  :  {name}".format(
397
+                        test_id=test_class.test_id, name=test_name)
398
+                    LOG.debug(log_string)
399
+                    last_failures = result.stats['unique_failures']
400
+                    last_errors = result.stats['errors']
392 401
                     p_bar = cli.ProgressBar(
393
-                        message=result_string, total_len=len(test_cases))
394
-                    last_failures = result.stats["failures"]
395
-                    last_errors = result.stats["errors"]
396
-                    for test in test_cases:
397
-                        if test:
398
-                            cls.run_test(test, result)
399
-                            p_bar.increment(1)
400
-                        p_bar.print_bar()
401
-                        failures = result.stats["failures"] - last_failures
402
-                        errors = result.stats["errors"] - last_errors
403
-                        total_tests = len(test_cases)
404
-                        if failures > total_tests * 0.90:
405
-                            # More than 90 percent failure
406
-                            failures = cli.colorize(failures, "red")
407
-                        elif failures > total_tests * 0.45:
408
-                            # More than 45 percent failure
409
-                            failures = cli.colorize(failures, "yellow")
410
-                        elif failures > total_tests * 0.15:
411
-                            # More than 15 percent failure
412
-                            failures = cli.colorize(failures, "blue")
402
+                        message=result_string, total_len=total_tests)
403
+                    test_class.send_init_request(file_path, req_str, meta_vars)
404
+
405
+                    # This line runs the tests
406
+                    pool.map(lambda t: cls.run_test(t, p_bar), test_cases)
407
+
408
+                    failures = result.stats['unique_failures'] - last_failures
409
+                    errors = result.stats['errors'] - last_errors
410
+                    failures_str = cli.colorize_by_percent(
411
+                        failures, total_tests, "red")
412
+
413 413
                     if errors:
414
-                        last_failures = result.stats["failures"]
415
-                        last_errors = result.stats["errors"]
416
-                        errors = cli.colorize(errors, "red")
414
+                        errors_str = cli.colorize(errors, "red")
417 415
                         print(_(
418 416
                             "  :  %(fail)s Failure(s), %(err)s Error(s)\r") % {
419
-                                "fail": failures, "err": errors})
417
+                                "fail": failures_str, "err": errors_str})
420 418
                     else:
421
-                        last_failures = result.stats["failures"]
422
-                        print(
423
-                            _(
424
-                                "  : %s Failure(s), 0 Error(s)\r") % failures)
419
+                        print(_(
420
+                            "  : %s Failure(s), 0 Error(s)\r") % failures_str)
425 421
 
426 422
             run_time = time.time() - template_start_time
427 423
             LOG.info(_("Run time: %s sec."), run_time)
@@ -440,26 +436,34 @@ class Runner(object):
440 436
                     result.print_result(cls.start_time)
441 437
                     cleanup.delete_temps()
442 438
                     print(_("Exiting..."))
439
+                    pool.close()
440
+                    pool.join()
443 441
                     exit(0)
444 442
                 print(_('Resuming...'))
445 443
             except KeyboardInterrupt:
446 444
                 result.print_result(cls.start_time)
447 445
                 cleanup.delete_temps()
448 446
                 print(_("Exiting..."))
447
+                pool.close()
448
+                pool.join()
449 449
                 exit(0)
450 450
 
451 451
     @classmethod
452
-    def run_test(cls, test, result):
452
+    def run_test(cls, test, p_bar=None):
453 453
         """Create a new test suite, add a test, and run it
454 454
 
455 455
         :param test: The test to add to the suite
456 456
         :param result: The result object to append to
457 457
         :type result: :class:`syntribos.result.IssueTestResult`
458
-        :param bool dry_run: (OPTIONAL) Only print out test names
459 458
         """
460
-        suite = unittest.TestSuite()
461
-        suite.addTest(test("run_test_case"))
462
-        suite.run(result)
459
+        if test:
460
+            suite = unittest.TestSuite()
461
+            suite.addTest(test("run_test_case"))
462
+            suite.run(result)
463
+            if p_bar:
464
+                with lock:
465
+                    p_bar.increment(1)
466
+                    p_bar.print_bar()
463 467
 
464 468
 
465 469
 def entry_point():

+ 4
- 3
syntribos/tests/base.py View File

@@ -148,10 +148,11 @@ class BaseTestCase(unittest.TestCase):
148 148
         :param str filename: name of template file
149 149
         :param str file_content: content of template file as string
150 150
         """
151
-        cls.init_req = parser.create_request(
152
-            file_content, CONF.syntribos.endpoint, meta_vars)
153
-
151
+        if not cls.init_req:
152
+            cls.init_req = parser.create_request(
153
+                file_content, CONF.syntribos.endpoint, meta_vars)
154 154
         prepared_copy = cls.init_req.get_prepared_copy()
155
+        cls.prepared_init_req = prepared_copy
155 156
         cls.init_resp, cls.init_signals = cls.client.send_request(
156 157
             prepared_copy)
157 158
         if cls.init_resp is not None:

+ 4
- 6
syntribos/tests/fuzz/base_fuzz.py View File

@@ -67,6 +67,9 @@ class BaseFuzzTestCase(base.BaseTestCase):
67 67
             headers=cls.request.headers,
68 68
             params=cls.request.params,
69 69
             data=cls.request.data)
70
+
71
+        if not hasattr(cls.request, 'body'):
72
+            cls.request.body = cls.request.data
70 73
         cls.test_req = cls.request
71 74
 
72 75
         if cls.test_resp is None or "EXCEPTION_RAISED" in cls.test_signals:
@@ -88,7 +91,6 @@ class BaseFuzzTestCase(base.BaseTestCase):
88 91
         self.run_default_checks() in order to test for the Issues
89 92
         defined here
90 93
         """
91
-
92 94
         if "HTTP_STATUS_CODE_5XX" in self.test_signals:
93 95
             self.register_issue(
94 96
                 defect_type="500_errors",
@@ -125,9 +127,6 @@ class BaseFuzzTestCase(base.BaseTestCase):
125 127
     def get_test_cases(cls, filename, file_content):
126 128
         """Generates new TestCases for each fuzz string
127 129
 
128
-        First, sends a baseline (non-fuzzed) request, storing it in
129
-        cls.init_resp.
130
-
131 130
         For each string returned by cls._get_strings(), yield a TestCase class
132 131
         for the string as an extension to the current TestCase class. Every
133 132
         string used as a fuzz test payload entails the generation of a new
@@ -197,8 +196,7 @@ class BaseFuzzTestCase(base.BaseTestCase):
197 196
         issue.request = self.test_req
198 197
         issue.response = self.test_resp
199 198
         issue.test_type = self.test_name
200
-        prepared_copy = self.init_req.get_prepared_copy()
201
-        url_components = urlparse(prepared_copy.url)
199
+        url_components = urlparse(self.prepared_init_req.url)
202 200
         issue.target = url_components.netloc
203 201
         issue.path = url_components.path
204 202
         issue.init_signals = self.init_signals

+ 0
- 1
syntribos/tests/fuzz/buffer_overflow.py View File

@@ -34,7 +34,6 @@ class BufferOverflowBody(base_fuzz.BaseFuzzTestCase):
34 34
         return [
35 35
             "A" * (2 ** 16 + 1),
36 36
             "a" * 10 ** 5,
37
-            "a" * 10 ** 6,
38 37
             '\x00' * (2 ** 16 + 1),
39 38
             "%%s" * 513,
40 39
         ]

+ 11
- 18
syntribos/utils/cli.py View File

@@ -26,22 +26,6 @@ CONF = cfg.CONF
26 26
 def print_symbol():
27 27
     """Syntribos radiation symbol."""
28 28
     symbol = """               Syntribos
29
-                xxxxxxx
30
-           x xxxxxxxxxxxxx x
31
-        x     xxxxxxxxxxx     x
32
-               xxxxxxxxx
33
-     x          xxxxxxx          x
34
-                 xxxxx
35
-    x             xxx             x
36
-                   x
37
-   xxxxxxxxxxxxxxx   xxxxxxxxxxxxxxx
38
-    xxxxxxxxxxxxx     xxxxxxxxxxxxx
39
-     xxxxxxxxxxx       xxxxxxxxxxx
40
-      xxxxxxxxx         xxxxxxxxx
41
-        xxxxxx           xxxxxx
42
-          xxx             xxx
43
-              x         x
44
-                   x
45 29
       === Automated API Scanning  ==="""
46 30
     print(syntribos.SEP)
47 31
     print(symbol)
@@ -55,15 +39,24 @@ def colorize(string, color="nocolor"):
55 39
     colors = dict(list(zip(color_names, list(range(31, 35)))))
56 40
     colors["nocolor"] = 0  # No Color
57 41
 
58
-    if not CONF.colorize:
42
+    if CONF.no_colorize:
59 43
         return string
60 44
     return "\033[0;{color}m{string}\033[0;m".format(string=string,
61 45
                                                     color=colors.setdefault(
62 46
                                                         color, 0))
63 47
 
64 48
 
49
+def colorize_by_percent(amount, total, high=0.5, medium=0):
50
+    if amount > total * high:
51
+        return colorize(amount, "red")
52
+    elif amount > total * medium:
53
+        return colorize(amount, "yellow")
54
+    else:
55
+        return str(amount)
56
+
57
+
65 58
 class ProgressBar(object):
66
-    """A simple progressBar.
59
+    """A simple progressBar. Written as a singleton.
67 60
 
68 61
     A simple generic progress bar like many others.
69 62
     :param int total_len: total_len value, when progress is 100 %

+ 1
- 1
syntribos/utils/config_fixture.py View File

@@ -64,7 +64,7 @@ class ConfFixture(config_fixture.Config):
64 64
         """config values for CLI options(default group)."""
65 65
         # TODO(unrahul): Add mock file path for outfile
66 66
         self.conf.set_default("test_types", [""])
67
-        self.conf.set_default("colorize", False)
67
+        self.conf.set_default("no_colorize", True)
68 68
         self.conf.set_default("output_format", "json")
69 69
         self.conf.set_default("min_severity", "LOW")
70 70
         self.conf.set_default("min_confidence", "LOW")

+ 2
- 2
tests/unit/test_ascii_colors.py View File

@@ -20,7 +20,7 @@ from syntribos.utils.cli import CONF
20 20
 class TestColorize(testtools.TestCase):
21 21
 
22 22
     def test_colorize(self):
23
-        CONF.colorize = True
23
+        CONF.no_colorize = False
24 24
         string = "color this string"
25 25
         colors = {"red": 31,
26 26
                   "green": 32,
@@ -34,6 +34,6 @@ class TestColorize(testtools.TestCase):
34 34
                 colorize(string, color))
35 35
 
36 36
     def test_no_colorize(self):
37
-        CONF.colorize = False
37
+        CONF.no_colorize = True
38 38
         string = "No color"
39 39
         self.assertEqual(string, colorize(string))

+ 1
- 1
tests/unit/test_results.py View File

@@ -52,7 +52,7 @@ class TestIssueTestResult(testtools.TestCase):
52 52
     def test_addFailure(self):
53 53
         test = FakeTest("failure")
54 54
         self.issue_result.addFailure(test, ())
55
-        self.assertEqual(self.issue_result.stats["failures"], 2)
55
+        self.assertEqual(self.issue_result.stats["unique_failures"], 2)
56 56
 
57 57
     def test_addSuccess(self):
58 58
         test = FakeTest("success")

Loading…
Cancel
Save