Sublime Forum

How do you refactor your plugins?

#1

Our plugin has grown up to 1500+ lines of code, and now I’m literally scared of performing any refactorings. When doing any non-trivial reshaping of the codebase I have a big chance to screw up, forget to rename something and introduce a regression.

How are you dealing with this folks? Manual testing is too time-consuming and quite error-prone, so the first reaction is to write unit tests. But how exactly do you write unit tests for a Sublime plugin?

0 Likes

#2

Testing plugins, while it can be a bit of a pita with the api being mostly
async, is definitely doable. If you are familiar with nose tests framework the
code excerpt below is a way you can use it to run unit tests on plugin
reload

[pre=#0C1021]# Nose
try: import nose
except ImportError: nose = None

################ ONLY LOAD TESTS WHEN DEVELOPING NOT ON START UP ###############

try: times_module_has_been_reloaded += 1
except NameError: times_module_has_been_reloaded = 0 #reloaded

RUN_TESTS = nose and times_module_has_been_reloaded

if RUN_TESTS:
target = name
nose.run(argv= ‘sys.executable’, target, ‘–with-doctest’, ‘-s’ ])
print ‘\nReloads: %s’ % times_module_has_been_reloaded

################################################################################[/pre]

You’ll sometimes find that you want file fixtures loaded into views for
functional testing. You can do this ‘manually’ via view.insert() which is one
way to make file loading synchronous.

[pre=#0C1021]fixtures = ]

def teardown():
while fixtures:
v = fixtures.pop()
v.window().focus_view(v)
v.window().cmd.close()

def load_fixture(f, syntax=u’Packages/Python/Python.tmLanguage’):
“”"

Create a View using `window.new_file` fixture and `manually` load the
fixture as window.open_file is asynchronous.

    v = window.open_file(f)
    assert v.is_loading()

It's impossible to do:

    while v.is_loading():
        time.sleep(0.01)

This would just cause S2 to block. You MUST use callbacks or co routines.

"""
view = sublime.active_window().new_file()
edit = view.begin_edit()
view.set_scratch(1)
view.set_syntax_file(syntax)

try:
    with codecs.open(f, 'r', 'utf8') as fh:
        view.insert(edit, 0, fh.read())
finally:
    view.end_edit(edit)

fixtures.append(view)
return view[/pre]

You can actually write a scheduler using sublime.set_timeout and python generator co-routines, using some kind of method to emulate keyboard input.

On windows, for testing Sublime Text 1 plugins, I used to use the SendKeys module.

0 Likes

#3

castles_made_of_sand: How did you get the nose module to be accessible from within sublime? I can’t figure out how to make it accessible to the sublime interpreter.

0 Likes