I have been creating acceptance tests for my pyglet application.
I was using an approach where the test would start the application (by
calling the application's main() function) on a new thread, so that
the application could proceed and the test could assert various things
about it. I've used this approach successfully in an IronPython
Windows GUI application context, but here it didn't work *at all*. :-)
I now have a solution that doesn't use threads. It instead uses
pyglet's own clock.schedule() to make a callback into the test harness
every frame, giving the test code a chance to make asserts about, or
to provide input to, the program-under-test. It's early days thus far,
but this approach seems to work swimmingly thus far, so I thought I'd
share what little I have in case it helps someone else, or anyone can
suggest something beneficial that I've overlooked.
To write a new acceptance test, I inherit from my AcceptanceTest class
(shown below), that inherits from TestCase. I provide a list of
conditions that must be met as lambdas, and then simply start my
program-under-test by calling its main() function. (or, in this case,
it's run_sole_scion() function, to avoid conflicts/confusion with
unittest.main())
Does posting code here work very well? Only one way to find out...
Here's my first acceptance test, which merely checks that the pyglet
application under test produces a window, and that the window is
visible and fullscreen.
--a sample acceptance test----
class AT001_app_opens_a_fullscreen_window(AcceptanceTest):
def is_window_visible(self):
if len(self.get_windows()) != 1:
return False
return self.get_window().visible
def is_window_fullscreen(self):
win = self.get_window()
return win.fullscreen
def test_window(self):
conditions = [
self.is_window_visible,
self.is_window_fullscreen,
]
self.set_conditions(conditions)
run_sole_scion()
--END a sample acceptance test ----
Firstly, note that the AcceptanceTest provides some minor utility
functions such as get_windows() and get_window(), to give test code
easy access to the main pyglet window(s):
from pyglet import app
def get_windows(self):
return [w for w in app.windows]
def get_window(self):
windows = self.get_windows()
if len(windows) == 1:
return windows[0]
return None
Next, note that the test calls AcceptanceTest.set_conditions(), which
calls next_condition() to pluck the first condition off the list, and
then uses clock.schedule() to request regular callbacks to
AcceptanceTest,try_condition():
def set_conditions(self, conditions):
self.conditions = conditions
self.next_condition()
clock.schedule(lambda dt: self.try_condition(dt))
So every frame, pyglet will call my AcceptanceTest.try_condition()
function.
try_condition() will evaluate the first condition. If it is true, it
moves onto the next. If that was the final condition, then the test
has passed and it requests the application terminate (by setting
window.has_exit to true)
If a condition evaluates to false, then try_condition() will simply
return. Subsequent calls to try_condition() will evaluate the same
condition. Eventually, if the condition does not become true, then the
timeout for the condition will be exceeded, and try_condition() will
raise an AssertionError, causing a test failure.
def try_condition(self, dt):
if self.verbose:
print "try_condition"
if self.condition():
if self.verbose:
print " pass after %fs" % self.time
self.next_condition()
else:
self.time += dt
if self.time > self.timeout:
raise AssertionError("timeout on %s" % self.condition)
Conditions, as a lambda, can be more than simply an expression that
returns true or false. They could simulate input to the application
under test (by raising key or mouse events) and then simply return
True so that the test harness will move onto the next condition.
I'll doubtless blog about this too, at tartley.com, with downloadable
code.
Cheers,
Tartley
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"pyglet-users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/pyglet-users?hl=en
-~----------~----~----~----~------~----~------~--~---