mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
uitests: Add a basic details.py test
Checks all hw of test-many-devices and make sure an error isn't raised
This commit is contained in:
parent
cfd980611a
commit
01da21b93a
84
tests/uitests/details.py
Normal file
84
tests/uitests/details.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import time
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import tests
|
||||||
|
from tests.uitests import utils as uiutils
|
||||||
|
|
||||||
|
import dogtail.rawinput
|
||||||
|
import pyatspi
|
||||||
|
|
||||||
|
|
||||||
|
class Details(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
UI tests for virt-manager's VM details window
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
self.app = uiutils.DogtailApp(tests.utils.uri_test)
|
||||||
|
def tearDown(self):
|
||||||
|
self.app.kill()
|
||||||
|
|
||||||
|
|
||||||
|
###################
|
||||||
|
# Private helpers #
|
||||||
|
###################
|
||||||
|
|
||||||
|
def _open_details_window(self, vmname="test-many-devices"):
|
||||||
|
uiutils.find_fuzzy(
|
||||||
|
self.app.root, vmname, "table cell").doubleClick()
|
||||||
|
win = uiutils.find_pattern(self.app.root, "%s on" % vmname, "frame")
|
||||||
|
uiutils.find_pattern(win, "Details", "radio button").click()
|
||||||
|
return win
|
||||||
|
|
||||||
|
|
||||||
|
##############
|
||||||
|
# Test cases #
|
||||||
|
##############
|
||||||
|
|
||||||
|
def testDetailsHardwareSmokeTest(self):
|
||||||
|
"""
|
||||||
|
Open the VM with all the crazy hardware and just verify that each
|
||||||
|
HW panel shows itself without raising any error.
|
||||||
|
"""
|
||||||
|
win = self._open_details_window()
|
||||||
|
|
||||||
|
# Ensure the Overview page is the first selected
|
||||||
|
uiutils.find_pattern(win, "Hypervisor Details", "label")
|
||||||
|
uiutils.find_pattern(win, "Overview", "table cell").click()
|
||||||
|
|
||||||
|
# After we hit this number of down presses, start checking for
|
||||||
|
# widget focus to determine if we hit the end of the list. We
|
||||||
|
# don't check for widget focus unconditionally because it's slow.
|
||||||
|
# The seemingly arbitrary number here is because it matches the
|
||||||
|
# number of devices in test-many-devices at the time of this writing.
|
||||||
|
check_after = 88
|
||||||
|
|
||||||
|
focused = None
|
||||||
|
old_focused = None
|
||||||
|
count = 0
|
||||||
|
while True:
|
||||||
|
count += 1
|
||||||
|
dogtail.rawinput.pressKey("Down")
|
||||||
|
|
||||||
|
if not win.getState().contains(pyatspi.STATE_ACTIVE):
|
||||||
|
# Should mean an error dialog popped up
|
||||||
|
uiutils.find_pattern(self.app.root, "Error", "alert")
|
||||||
|
raise AssertionError(
|
||||||
|
"One of the hardware pages raised an error")
|
||||||
|
|
||||||
|
if count < check_after:
|
||||||
|
time.sleep(.1)
|
||||||
|
continue
|
||||||
|
|
||||||
|
old_focused = focused
|
||||||
|
focused = uiutils.focused_nodes(win)
|
||||||
|
if old_focused is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
overlap = [w for w in old_focused if w in focused]
|
||||||
|
if len(overlap) == len(old_focused):
|
||||||
|
# Focus didn't change, meaning we hit the end of the HW list,
|
||||||
|
# so our testing is done
|
||||||
|
break
|
||||||
|
|
||||||
|
self.app.quit()
|
||||||
|
return
|
@ -87,6 +87,10 @@ class DogtailApp(object):
|
|||||||
time.sleep(.5)
|
time.sleep(.5)
|
||||||
|
|
||||||
|
|
||||||
|
#########################
|
||||||
|
# Widget search helpers #
|
||||||
|
#########################
|
||||||
|
|
||||||
def find_pattern(root, name, roleName=None, labeller_text=None):
|
def find_pattern(root, name, roleName=None, labeller_text=None):
|
||||||
"""
|
"""
|
||||||
Search root for any widget that contains the passed name/role regex
|
Search root for any widget that contains the passed name/role regex
|
||||||
@ -120,6 +124,26 @@ def find_fuzzy(root, name, roleName=None, labeller_text=None):
|
|||||||
labeller_pattern)
|
labeller_pattern)
|
||||||
|
|
||||||
|
|
||||||
|
def check_in_loop(func, timeout=-1):
|
||||||
|
"""
|
||||||
|
Run the passed func in a loop every .5 seconds until timeout is hit or
|
||||||
|
the func returns True.
|
||||||
|
If timeout=-1, check indefinitely.
|
||||||
|
"""
|
||||||
|
total_time = 0.0
|
||||||
|
while True:
|
||||||
|
time.sleep(.5)
|
||||||
|
total_time += .5
|
||||||
|
if func() is True:
|
||||||
|
return
|
||||||
|
if timeout > 0 and total_time >= timeout:
|
||||||
|
raise RuntimeError("Loop condition wasn't met")
|
||||||
|
|
||||||
|
|
||||||
|
#####################
|
||||||
|
# Debugging helpers #
|
||||||
|
#####################
|
||||||
|
|
||||||
def node_string(node):
|
def node_string(node):
|
||||||
msg = "name='%s' roleName='%s'" % (node.name, node.roleName)
|
msg = "name='%s' roleName='%s'" % (node.name, node.roleName)
|
||||||
if node.labeller:
|
if node.labeller:
|
||||||
@ -141,17 +165,15 @@ def print_nodes(root):
|
|||||||
root.findChildren(_walk, isLambda=True)
|
root.findChildren(_walk, isLambda=True)
|
||||||
|
|
||||||
|
|
||||||
def check_in_loop(func, timeout=-1):
|
def focused_nodes(root):
|
||||||
"""
|
"""
|
||||||
Run the passed func in a loop every .5 seconds until timeout is hit or
|
Return a list of all focused nodes. Useful for debugging
|
||||||
the func returns True.
|
|
||||||
If timeout=-1, check indefinitely.
|
|
||||||
"""
|
"""
|
||||||
total_time = 0.0
|
def _walk(node):
|
||||||
while True:
|
try:
|
||||||
time.sleep(.5)
|
if node.focused:
|
||||||
total_time += .5
|
return node
|
||||||
if func() is True:
|
except Exception, e:
|
||||||
return
|
print "got exception: %s" % e
|
||||||
if timeout > 0 and total_time >= timeout:
|
|
||||||
raise RuntimeError("Loop condition wasn't met")
|
return root.findChildren(_walk, isLambda=True)
|
||||||
|
@ -617,6 +617,16 @@
|
|||||||
<signal name="changed" handler="on_hw_list_changed" swapped="no"/>
|
<signal name="changed" handler="on_hw_list_changed" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
<child internal-child="accessible">
|
||||||
|
<object class="AtkObject" id="hw-list-atkobject">
|
||||||
|
<property name="AtkObject::accessible-name" translatable="yes">hw-list</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child internal-child="accessible">
|
||||||
|
<object class="AtkObject" id="scrolledwindow5-atkobject">
|
||||||
|
<property name="AtkObject::accessible-name" translatable="yes">hw-list-scroll</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
Loading…
Reference in New Issue
Block a user