Hello:
Recently, while solving some problems with an extension I
created when upgrading gnome shell, I realized there's no way to
actually perform tests on GSE code. I'm an agile advocate, so for
most of the work I do I always rely on tests (unit tests and
integration tests mostly). So, I spent the last couple of days
working on refactoring the code for the extension, and I
introduced unit testing using npm/karma/jasmine/firefox. You can
see the whole code in this github repository:
https://github.com/emerinohdz/power-alt-tab
There where a couple of issues I encounter:
- GS uses an "imports" mechanism, in order to include a script
into another. This was solved by using a really simple "class
finder" (defined under utils.js). The implementation is not
really pleasant, it requires so called "classes" to be manually
declared (and they should be declared according to order of
use). The idea is that you can use something like 'const MyClass
= Utils.use("gs.MyClass")' to include MyClass into your current
script. It would be wonderful if GS included this sort of
functionality out of the box, and maybe include something like
"autoloaders" which can be defined depending on the environment
where the code is being run (e.g. under firefox for unit testing
or under real GS enviroment). Or maybe implementing something
like AMD?
- For unit testing (with karma), all the code is read when tests
run, this presented a problem with the way GS loads scripts,
because using "const" globally presented problems when running
under karma, while it was needed for GS. What I did here
consisted on using self executing functions to provide a
narrower scope for each script, so now "const" could be declared
on every script without problems when running under karma.
- For unit testing to work fine, I had to include a GS polyfill
(test/polyfill_gs.js). This polyfill only covers what I needed,
the way I needed it, mostly mocking every global GS object
needed.
- I've worked on a really small GS API (which is by no means
complete), located under "src/gs". The idea here is to have a
higher level API to work with, which will handle most of the low
level stuff. This additional layer would help with changes made
to the lower level APIs, since extensions can be coded against
this higher level GS API which should not change often. I only
included a GS screen wrapper and a signal tracker (for tracking
signal connect/disconnect). Things like keybinding could be
included in the API too, and many other facilities I'm not using
with my extension too. This should be an additional effort, but
well worth it IMO.
- Integration testing was not possible, this would be a huge
step forward. Right now it is becoming harder to test the
extension on a real GS environment, you have to revert to some
sort of virtual environment, specially if using Wayland (where
restarting GS is not possible). Providing some type of test API
where things could be integrated and tested before moving to
production would mean faster delivery of new functionality IMO.
This is of course the greatest challenge.
- I had to use firefox, in order to use some of the ES6
features, but things can be worked out to include an ES5/5
polyfill to use PhantomJS (not tested).
NOTE: I used constructor functions instead of Lang.Class to
define so called "classes" for most of my code, but it's not a
problem to use Lang.Class, as you can see here
"src/nuevebit/workspace_switcher_popup.js".
I don't know if this is something the GSE devs are interested
in taking a look at, I would be more than glad to contribute to
this project if needed.
Regards.
Edgar Merino
|