forked from guillermooo/Vintageous
-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_runner.py
128 lines (99 loc) · 4.49 KB
/
test_runner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import sublime
import sublime_plugin
import os
import unittest
import contextlib
from threading import Thread
class __vi_tests_write_buffer(sublime_plugin.TextCommand):
"""Replaces the buffer's content with the specified `text`.
`text`: Text to be written to the buffer.
"""
def run(self, edit, text=''):
self.view.replace(edit, sublime.Region(0, self.view.size()), text)
class __vi_tests_erase_all(sublime_plugin.TextCommand):
"""Replaces the buffer's content with the specified `text`.
"""
def run(self, edit):
self.view.erase(edit, sublime.Region(0, self.view.size()))
class OutputPanel(object):
def __init__(self, name, file_regex='', line_regex='', base_dir=None,
word_wrap=False, line_numbers=False, gutter=False,
scroll_past_end=False,
syntax='Packages/Text/Plain text.tmLanguage',
):
self.name = name
self.window = sublime.active_window()
if not hasattr(self, 'output_view'):
# Try not to call get_output_panel until the regexes are assigned
self.output_view = self.window.create_output_panel(self.name)
# Default to the current file directory
if (not base_dir and self.window.active_view() and
self.window.active_view().file_name()):
base_dir = os.path.dirname(
self.window.active_view().file_name()
)
self.output_view.settings().set('result_file_regex', file_regex)
self.output_view.settings().set('result_line_regex', line_regex)
self.output_view.settings().set('result_base_dir', base_dir)
self.output_view.settings().set('word_wrap', word_wrap)
self.output_view.settings().set('line_numbers', line_numbers)
self.output_view.settings().set('gutter', gutter)
self.output_view.settings().set('scroll_past_end', scroll_past_end)
self.output_view.settings().set('syntax', syntax)
# Call create_output_panel a second time after assigning the above
# settings, so that it'll be picked up as a result buffer
self.window.create_output_panel(self.name)
def write(self, s):
f = lambda: self.output_view.run_command('append', {'characters': s})
sublime.set_timeout(f, 0)
def flush(self):
pass
def show(self):
self.window.run_command(
'show_panel', {'panel': 'output.' + self.name}
)
def close(self):
pass
class RunVintageousTests(sublime_plugin.WindowCommand):
'''Runs tests and displays the result.
- Do not use ST while tests are running.
@working_dir
Required. Should be the parent of the top-level directory for `tests`.
@loader_pattern
Optional. Only run tests matching this glob.
@active_file_only
Optional. Only run tests in the active file in ST. Shadows
@loader_pattern.
To use this runner conveniently, open the command palette and select one
of the `Build: Vintageous - Test *` commands.
'''
@contextlib.contextmanager
def chdir(self, path=None):
old_path = os.getcwd()
if path is not None:
assert os.path.exists(path), "'path' is invalid {}".format(path)
os.chdir(path)
yield
if path is not None:
os.chdir(old_path)
def run(self, **kwargs):
with self.chdir(kwargs.get('working_dir')):
p = os.path.join(os.getcwd(), 'tests')
patt = kwargs.get('loader_pattern', 'test*.py',)
# TODO(guillermooo): I can't get $file to expand in the build
# system. It should be possible to make the following code simpler
# with it.
if kwargs.get('active_file_only') is True:
patt = os.path.basename(self.window.active_view().file_name())
suite = unittest.TestLoader().discover(p, pattern=patt)
file_regex = r'^\s*File\s*"([^.].*?)",\s*line\s*(\d+),.*$'
display = OutputPanel('vintageous.tests', file_regex=file_regex)
display.show()
runner = unittest.TextTestRunner(stream=display, verbosity=1)
def run_and_display():
runner.run(suite)
display.show()
# If we don't do this, custom mappings won't be available
# after running the test suite.
self.window.run_command('reset_vintageous')
Thread(target=run_and_display).start()