Skip to content

Commit 412f377

Browse files
authored
Reload after coverage initialization (#270)
This commit reloads modules after initializing coverage racing, to include package imports into "tested" code results.
1 parent a2a776a commit 412f377

File tree

2 files changed

+105
-79
lines changed

2 files changed

+105
-79
lines changed

unittesting/reloader.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sublime
66
import sublime_plugin
77
import sys
8+
from time import sleep
89

910

1011
def path_contains(a, b):
@@ -55,6 +56,33 @@ def reload_package(pkg_name, on_done=None):
5556
sublime.set_timeout(on_done)
5657
return
5758

59+
dummy_name, dummy_py = _reload_package(pkg_name)
60+
61+
def check_loaded():
62+
if dummy_name not in sys.modules:
63+
sublime.set_timeout(check_loaded, 100)
64+
return
65+
66+
os.remove(dummy_py)
67+
if on_done:
68+
sublime.set_timeout(on_done, 200)
69+
70+
sublime.set_timeout(check_loaded, 100)
71+
72+
73+
def async_reload_package(pkg_name):
74+
if pkg_name not in sys.modules:
75+
return
76+
77+
dummy_name, dummy_py = _reload_package(pkg_name)
78+
79+
while dummy_name not in sys.modules:
80+
sleep(0.1)
81+
82+
os.remove(dummy_py)
83+
84+
85+
def _reload_package(pkg_name):
5886
all_modules = {
5987
module_name: module
6088
for module_name, module in get_package_modules(pkg_name).items()
@@ -92,13 +120,4 @@ def reload_package(pkg_name, on_done=None):
92120

93121
open(dummy_py, "a").close()
94122

95-
def check_loaded():
96-
if dummy_name not in sys.modules:
97-
sublime.set_timeout(check_loaded, 100)
98-
return
99-
100-
os.remove(dummy_py)
101-
if on_done:
102-
sublime.set_timeout(on_done, 200)
103-
104-
sublime.set_timeout(check_loaded, 100)
123+
return dummy_name, dummy_py

unittesting/unit.py

Lines changed: 76 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from .core import DeferrableTestCase
1515
from .core import DeferrableTestLoader
1616
from .core import DeferringTextTestRunner
17-
from .reloader import reload_package
17+
from .reloader import async_reload_package, reload_package
1818

1919
try:
2020
import coverage
@@ -97,91 +97,98 @@ def run(self, package=None, **kwargs):
9797

9898
stream = self.load_stream(package, settings)
9999

100-
def run_tests():
101-
if settings["async"]:
102-
threading.Thread(
103-
target=self.run_coverage, args=(package, stream, settings)
104-
).start()
105-
else:
106-
self.run_coverage(package, stream, settings)
107-
108-
if settings["reload_package_on_testing"]:
109-
reload_package(package, on_done=run_tests)
100+
if settings["async"]:
101+
threading.Thread(
102+
target=self.run_coverage, args=(package, stream, settings)
103+
).start()
110104
else:
111-
run_tests()
105+
self.run_coverage(package, stream, settings)
112106

113107
def run_coverage(self, package, stream, settings):
114-
if not coverage or not settings["coverage"]:
115-
if settings["coverage"]:
116-
stream.write("Warning: coverage cannot be loaded.\n\n")
108+
# prepare coverage
109+
cleanup_hooks = []
110+
if settings["coverage"] and not coverage:
111+
stream.write("Warning: coverage cannot be loaded.\n\n")
112+
113+
elif settings["coverage"]:
114+
packages_path = sublime.packages_path()
115+
package_path = os.path.join(packages_path, package)
116+
data_file_dir = os.path.join(packages_path, "User", "UnitTesting", package)
117+
os.makedirs(data_file_dir, exist_ok=True)
118+
data_file = os.path.join(data_file_dir, "coverage")
119+
if os.path.exists(data_file):
120+
os.unlink(data_file)
121+
config_file = os.path.join(package_path, ".coveragerc")
122+
include = "{}/*".format(package_path)
123+
omit = "{}/{}/*".format(package_path, settings["tests_dir"])
124+
if os.path.exists(config_file):
125+
with open(config_file, "r") as f:
126+
txt = f.read()
127+
if re.search("^include", txt, re.M):
128+
include = None
129+
if re.search("^omit", txt, re.M):
130+
omit = None
131+
else:
132+
config_file = False
117133

118-
self.run_tests(stream, package, settings, [])
119-
return
134+
cov = coverage.Coverage(
135+
data_file=data_file, config_file=config_file, include=include, omit=omit
136+
)
120137

121-
packages_path = sublime.packages_path()
122-
package_path = os.path.join(packages_path, package)
123-
data_file_dir = os.path.join(packages_path, "User", "UnitTesting", package)
124-
os.makedirs(data_file_dir, exist_ok=True)
125-
data_file = os.path.join(data_file_dir, "coverage")
126-
if os.path.exists(data_file):
127-
os.unlink(data_file)
128-
config_file = os.path.join(package_path, ".coveragerc")
129-
include = "{}/*".format(package_path)
130-
omit = "{}/{}/*".format(package_path, settings["tests_dir"])
131-
if os.path.exists(config_file):
132-
with open(config_file, "r") as f:
133-
txt = f.read()
134-
if re.search("^include", txt, re.M):
135-
include = None
136-
if re.search("^omit", txt, re.M):
137-
omit = None
138-
else:
139-
config_file = False
138+
cov.start()
140139

141-
cov = coverage.Coverage(
142-
data_file=data_file, config_file=config_file, include=include, omit=omit
143-
)
140+
if settings["coverage_on_worker_thread"]:
141+
original_set_timeout_async = sublime.set_timeout_async
144142

145-
cov.start()
143+
def set_timeout_async(callback, *args, **kwargs):
144+
def _():
145+
sys.settrace(threading._trace_hook)
146+
callback()
146147

147-
if settings["coverage_on_worker_thread"]:
148-
original_set_timeout_async = sublime.set_timeout_async
148+
original_set_timeout_async(_, *args, **kwargs)
149149

150-
def set_timeout_async(callback, *args, **kwargs):
151-
def _():
152-
sys.settrace(threading._trace_hook)
153-
callback()
150+
sublime.set_timeout_async = set_timeout_async
154151

155-
original_set_timeout_async(_, *args, **kwargs)
152+
def cleanup():
153+
if settings["coverage_on_worker_thread"]:
154+
sublime.set_timeout_async = original_set_timeout_async
155+
156+
stream.write("\n")
157+
cov.stop()
158+
coverage.files.RELATIVE_DIR = os.path.normcase(package_path + os.sep)
159+
ignore_errors = cov.get_option("report:ignore_errors")
160+
show_missing = cov.get_option("report:show_missing")
161+
cov.report(
162+
file=stream, ignore_errors=ignore_errors, show_missing=show_missing
163+
)
164+
165+
if settings["generate_xml_report"]:
166+
xml_report_file = os.path.join(package_path, "coverage.xml")
167+
cov.xml_report(outfile=xml_report_file, ignore_errors=ignore_errors)
168+
169+
if settings["generate_html_report"]:
170+
html_output_dir = os.path.join(package_path, "htmlcov")
171+
cov.html_report(
172+
directory=html_output_dir, ignore_errors=ignore_errors
173+
)
156174

157-
sublime.set_timeout_async = set_timeout_async
175+
cov.save()
158176

159-
def cleanup():
160-
if settings["coverage_on_worker_thread"]:
161-
sublime.set_timeout_async = original_set_timeout_async
162-
163-
stream.write("\n")
164-
cov.stop()
165-
coverage.files.RELATIVE_DIR = os.path.normcase(package_path + os.sep)
166-
ignore_errors = cov.get_option("report:ignore_errors")
167-
show_missing = cov.get_option("report:show_missing")
168-
cov.report(
169-
file=stream, ignore_errors=ignore_errors, show_missing=show_missing
170-
)
177+
cleanup_hooks = [cleanup]
171178

172-
if settings["generate_xml_report"]:
173-
xml_report_file = os.path.join(package_path, "coverage.xml")
174-
cov.xml_report(outfile=xml_report_file, ignore_errors=ignore_errors)
179+
def run_tests():
180+
self.run_tests(stream, package, settings, cleanup_hooks)
175181

176-
if settings["generate_html_report"]:
177-
html_output_dir = os.path.join(package_path, "htmlcov")
178-
cov.html_report(directory=html_output_dir, ignore_errors=ignore_errors)
182+
if settings["reload_package_on_testing"]:
183+
if not settings["async"]:
184+
reload_package(package, on_done=run_tests)
185+
return
179186

180-
cov.save()
187+
async_reload_package(package)
181188

182-
self.run_tests(stream, package, settings, [cleanup])
189+
run_tests()
183190

184-
def run_tests(self, stream, package, settings, cleanup_hooks=[]):
191+
def run_tests(self, stream, package, settings, cleanup_hooks):
185192
if settings["capture_console"]:
186193
stdout = sys.stdout
187194
stderr = sys.stderr

0 commit comments

Comments
 (0)