Skip to content

Commit

Permalink
Show stdout and stderr for linter bears
Browse files Browse the repository at this point in the history
Print the `stdout` and `stderr` from linter bears when tests
fail which is helpful for debugging.

Closes coala/coala-bears#455
  • Loading branch information
yash-nisar authored and Makman2 committed Jul 24, 2017
1 parent 4f8ee34 commit bbb99f9
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
29 changes: 27 additions & 2 deletions coalib/testing/LocalBearTestHelper.py
@@ -1,6 +1,7 @@
import queue import queue
import unittest import unittest
from contextlib import contextmanager from contextlib import contextmanager, ExitStack
from unittest.mock import patch


import pytest import pytest


Expand All @@ -14,14 +15,38 @@
@contextmanager @contextmanager
def execute_bear(bear, *args, **kwargs): def execute_bear(bear, *args, **kwargs):
try: try:
bear_output_generator = bear.execute(*args, **kwargs) console_output = []

# For linters provide additional information, such as
# stdout and stderr.
with ExitStack() as stack:
if hasattr(bear, 'process_output'):
console_output.append('The program yielded '
'the following output:\n')
old_process_output = bear.process_output

def new_process_output(output, filename=None, file=None):
if isinstance(output, tuple):
stdout, stderr = output
console_output.append('Stdout:\n' + stdout)
console_output.append('Stderr:\n' + stderr)
else:
console_output.append(output)
return old_process_output(output, filename, file)

stack.enter_context(patch.object(
bear, 'process_output', wraps=new_process_output))

bear_output_generator = bear.execute(*args, **kwargs)

assert bear_output_generator is not None, \ assert bear_output_generator is not None, \
'Bear returned None on execution\n' 'Bear returned None on execution\n'
yield bear_output_generator yield bear_output_generator
except Exception as err: except Exception as err:
msg = [] msg = []
while not bear.message_queue.empty(): while not bear.message_queue.empty():
msg.append(bear.message_queue.get().message) msg.append(bear.message_queue.get().message)
msg += console_output
raise AssertionError(str(err) + ''.join('\n' + m for m in msg)) raise AssertionError(str(err) + ''.join('\n' + m for m in msg))
return list(bear_output_generator) return list(bear_output_generator)


Expand Down
41 changes: 41 additions & 0 deletions tests/testing/LocalBearTestHelperTest.py
@@ -1,10 +1,12 @@
from queue import Queue from queue import Queue
import sys
import unittest import unittest


from tests.test_bears.TestBear import TestBear from tests.test_bears.TestBear import TestBear
from tests.test_bears.TestBearDep import (TestDepBearBDependsA, from tests.test_bears.TestBearDep import (TestDepBearBDependsA,
TestDepBearCDependsB, TestDepBearCDependsB,
TestDepBearDependsAAndAA) TestDepBearDependsAAndAA)
from coalib.bearlib.abstractions.Linter import linter
from coalib.settings.Section import Section from coalib.settings.Section import Section
from coalib.settings.Setting import Setting from coalib.settings.Setting import Setting
from coalib.testing.LocalBearTestHelper import verify_local_bear, execute_bear from coalib.testing.LocalBearTestHelper import verify_local_bear, execute_bear
Expand Down Expand Up @@ -101,6 +103,45 @@ def setUp(self):
section.append(Setting('exception', True)) section.append(Setting('exception', True))
self.uut = TestBear(section, Queue()) self.uut = TestBear(section, Queue())


def test_stdout_stderr_on_linter_test_fail(self):

class TestLinter:
@staticmethod
def process_output(output, filename, file):
pass

@staticmethod
def create_arguments(filename, file, config_file):
code = '\n'.join(['import sys',
"print('hello stdout')",
"print('hello stderr', file=sys.stderr)"])
return '-c', code

# Testing with both stdout and stderr enabled
uut = (linter(sys.executable, use_stdout=True, use_stderr=True)
(TestLinter)
(Section('TEST_SECTION'), Queue()))
try:
with execute_bear(uut, 'filename', ['file']) as result:
raise AssertionError
except AssertionError as ex:
self.assertIn('The program yielded the following output:', str(ex))
self.assertIn('Stdout:', str(ex))
self.assertIn('hello stdout', str(ex))
self.assertIn('Stderr:', str(ex))
self.assertIn('hello stderr', str(ex))

# Testing with only stdout enabled
uut = (linter(sys.executable, use_stdout=True)
(TestLinter)
(Section('TEST_SECTION'), Queue()))
try:
with execute_bear(uut, 'filename', ['file']) as result:
raise AssertionError
except AssertionError as ex:
self.assertIn('The program yielded the following output:', str(ex))
self.assertIn('hello stdout', str(ex))

def test_exception(self): def test_exception(self):


with self.assertRaises(AssertionError), execute_bear( with self.assertRaises(AssertionError), execute_bear(
Expand Down

0 comments on commit bbb99f9

Please sign in to comment.