Robust class hierarchy for applications in the test suite
Originally created by @anonym on #10767 (Redmine)
Here’s a quick brain dump of something I’ve been thinking about lately:
Currently we employ various “helper” functions for doing stuff in a robust manner for certain applications in the automated test suite. Sometimes these could benefit other applications too, or be generalized so they can. Imagine a class hierarchy like this, where the most robust of our tricks would be inherited downwards (and when they don’t work, overridden):
-
App
-
CLIApp
(which perhaps starts stuff withVM.spawn()
? I’m not sure if there’s much use for this, soXorgApp
would become the new root, but called justApp
.) -
XorgApp
-
QtApp
ElectrumApp
VidaliaApp
-
GtkApp
-
BrowserApp
TorBrowserApp
I2PBrowserApp
UnsafeBrowserApp
IcedoveApp
PidginApp
-
GnomeApp
GeditApp
GnomeTermialApp
FilesApp
-
-
-
Hopefully Gedit could be implemented as simply as this:
class GeditApp < GnomeApp
# Possibly we could have a @name that would derive the below ones, that would work in most cases
@app_menu_icon = 'GnomeApplicationGedit.png'
@exec_path = '/usr/bin/gedit'
# Another interesting idea would be to parse .desktop files, perhaps.
end
and then we could do stuff like:
gedit = GeditApp.new
# Since @app_menu_icon is set, it will start via the menu.
gedit.start
puts "#{gedit.name} (#{gedit.exec_path}) started with pid #{gedit.pid}"
gedit.focus
# Call Sikuli's type(), which probably should be auto-focusing (which makes
# the focus above unnecessary, but let's keep it for the demonstration)
gedit.type("typing some text " + Sikuli::Key.ENTER)
1000.times { gedit.type(Sikuli::Key.ENTER) }
# Will error out if there's no GNOME style scrollbar. Or just succeed since we
# could consider this as being at the top?
gedit.scroll_to_top
# This will click the X-button of Gedit's window.
gedit.close
# This may not work so well with GNOME applications since they seem to
# gravitate to ad-hoc, non-standardized menus, but you get the idea. Either
# we can use assistive tech to navigate, or we derive the images for sikuli to
# click on, e.g. "File" => "GnomeAppMenuFile.png".
gedit.open_menu(["File", "Save As"])
# children() fetches the list of child windows/prompts etc, and now we expect
# only one, the "Save changes before closing?" prompt.
gedit.children.first.click('GeditCloseWithoutSaving.png')
# I guess we could make children() implement Enumerable and have find() look for
# the window title so we could have done the above like this:
# gedit.children.find('Save As').click('GeditCloseWithoutSaving.png')
Focusing and so on would be automatic on “actions”, so we could run several instances of the same application in a robust way, without mixing up where stuff happens.
I guess one-off application instances could be started like this:
gedit_instance = GnomeApp.new(:exec_path => '/usr/bin/gedit', ...)
gedit_instance.start
or, simplified,
gedit_instance = GnomeApp.start(:exec_path => '/usr/bin/gedit', ...)
so in many cases we wouldn’t need to define a dedicated class.
Ideally #10721 (closed) would also play a big role in this somehow so we can depend less on Sikuli and images.