Hello,
when writing unit tests for my plugins, I am able to write fully reliable tests by using yield / from
statements. yield / from
let me asynchronously “wait” until a certain condition occurs before proceeding with code execution. This is particularly useful when running external commands (window.run_command(...)
). Because the caller doesn’t know when a command completes, I can use yield from
to implement logic which infer whether a command completed:
import unittesting # https://github.com/SublimeText/UnitTesting
def read_view(view):
region = sublime.Region(0, view.size())
return view.substr(region)
class MyTestCase(unittesting.DeferrableTestCase)
def await_content_in_view(self, view, content):
yield lambda: read_view(view) == content
def await_open_file(self, path):
window = sublime.active_window()
init_view = window.active_view()
new_view = window.open_file(path)
yield lambda: window.active_view() != new_view
return new_view
def test_write_in_view(self):
view = yield from self.await_open_file("/foo/bar.py")
view.run_command("write_view", {"content", "hello world"})
yield from self.await_content_in_view(view, "hello world")
Unfortunately I cannot use the same strategy when writing ST plugins. E.g. I have this piece of code which sometimes does not work before the sub-command did not complete fast enough:
class MyCommand(sublime_plugin.WindowCommand):
def run(self):
self.window.run_command(
"carry_file_to_pane",
{"direction": direction, "create_new_if_necessary": True},
)
new_view = self.window.active_view()
new_view.run_command("show_at_center")
To make it work I have to add some delay, like this:
class MyCommand(sublime_plugin.WindowCommand):
def run(self):
self.window.run_command(
"carry_file_to_pane",
{"direction": direction, "create_new_if_necessary": True},
)
sublime_plugin.set_timeout(self.on_open, 100)
def on_open(self):
new_view = self.window.active_view()
new_view.run_command("show_at_center")
…but this is sub-optimal though and unorthodox. E.g., on a slower computer I may need a bigger timeout, and on a faster computer I unnecessarily wait 100 ms. Therefore I ask:
- What is the “standard” way, for a sublime text plugin to wait until a (sub) command completes? ST doc provides no direction about this.
- Are there frameworks similar to
unittesting.DeferrableTestCase
that lets you useyield / from
from within a ST plugin? -
unittesting
does a nice job in providing theyield / from
abstraction, and it could probably do even better by addingasync / await
support (tulip / asyncio followed a similar evolution). I wonder if this sort of research/discussion ever occurred within the ST ecosystem.