report-xfstests.py: Convert test properties into a Gtk.Stack
And use a Gtk.ColumnView to display the results instead of packing everything into a Gtk.Grid Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
b47955fe5a
commit
6f3c37e568
|
@ -15,42 +15,6 @@ from gi.repository import Gio
|
|||
|
||||
XFSTESTS = pathlib.Path(xdg.BaseDirectory.xdg_data_home) / "xfstests" / "date"
|
||||
|
||||
class TestProperty():
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.prop = dict()
|
||||
|
||||
def __lt__(self, rhs):
|
||||
return self.name.upper() < rhs.name.upper()
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.prop[key]
|
||||
|
||||
def __setitem__(self, key, val):
|
||||
self.prop[key] = val
|
||||
|
||||
|
||||
class PropertyPage(Gtk.ScrolledWindow):
|
||||
def __init__(self, name, results):
|
||||
Gtk.ScrolledWindow.__init__(self, vscrollbar_policy=Gtk.PolicyType.NEVER)
|
||||
self.set_child(Gtk.Grid())
|
||||
|
||||
res = { p.name : p[name] for p in results.properties }
|
||||
passed = int(res['tests']) - (int(res['skipped']) + int(res['failures']))
|
||||
res["RESULTS"] = f"Ran {res['tests']} tests in {res['time']} seconds: " \
|
||||
f"{passed} passed, {res['failures']} failed, {res['skipped']} skipped"
|
||||
|
||||
fields = [ "PLATFORM", "timestamp", "FSTYP", "MOUNT_OPTIONS", "CHECK_OPTIONS",
|
||||
"TEST_DIR", "TEST_DEV", "SCRATCH_DEV", "SCRATCH_MNT", "RESULTS" ]
|
||||
for i, field in enumerate(fields):
|
||||
key = Gtk.Label.new(field.upper() + " = ")
|
||||
key.set_xalign(100)
|
||||
val = Gtk.Label.new(res[field])
|
||||
val.set_xalign(0)
|
||||
self.get_child().get_child().attach(key, 0, i, 1, 1)
|
||||
self.get_child().get_child().attach(val, 1, i, 1, 1)
|
||||
|
||||
|
||||
class TestCase(GObject.GObject):
|
||||
def __init__(self, name):
|
||||
GObject.GObject.__init__(self)
|
||||
|
@ -88,7 +52,6 @@ class TestCase(GObject.GObject):
|
|||
class TestResultsModel(GObject.GObject, Gio.ListModel):
|
||||
def __init__(self):
|
||||
GObject.GObject.__init__(self)
|
||||
self.properties = [ ]
|
||||
self.tests = [ ]
|
||||
self.columns = [ "Test Name" ]
|
||||
|
||||
|
@ -98,13 +61,6 @@ class TestResultsModel(GObject.GObject, Gio.ListModel):
|
|||
def get_n_columns(self): return len(self.columns)
|
||||
def get_column_name(self, n): return self.columns[n]
|
||||
|
||||
def find_property(self, name):
|
||||
for prop in self.properties:
|
||||
if prop.name == name:
|
||||
return prop
|
||||
self.properties.append(TestProperty(name))
|
||||
return self.properties[-1]
|
||||
|
||||
def find_testcase(self, name):
|
||||
i = bisect.bisect(self.tests, name, key=str)
|
||||
if i > 0 and self.tests[i-1].name == name:
|
||||
|
@ -115,24 +71,16 @@ class TestResultsModel(GObject.GObject, Gio.ListModel):
|
|||
def set_tests(self, path):
|
||||
rm = len(self.tests)
|
||||
self.columns = [ "Test Name" ]
|
||||
self.properties.clear()
|
||||
self.tests.clear()
|
||||
|
||||
for file in sorted(path.iterdir() if path else []):
|
||||
self.columns.append(file.stem)
|
||||
root = xml.etree.ElementTree.parse(file).getroot()
|
||||
for prop in root.attrib.keys():
|
||||
self.find_property(prop)[file.stem] = root.attrib[prop]
|
||||
|
||||
for elm in root:
|
||||
if elm.tag == "testcase":
|
||||
testcase = self.find_testcase(elm.attrib["name"])
|
||||
testcase[file.stem] = elm
|
||||
elif elm.tag == "properties":
|
||||
for prop in elm:
|
||||
name = prop.attrib["name"]
|
||||
value = prop.attrib["value"]
|
||||
self.find_property(name)[file.stem] = value
|
||||
self.emit("items-changed", 0, rm, len(self.tests))
|
||||
|
||||
|
||||
|
@ -224,7 +172,6 @@ class TestWindow(Gtk.ScrolledWindow):
|
|||
self.filter = Gtk.FilterListModel.new(self.results, TestResultsFilter())
|
||||
self.selection = Gtk.NoSelection.new(self.filter)
|
||||
self.view = Gtk.ColumnView.new(self.selection)
|
||||
self.notebook = Gtk.Notebook()
|
||||
self.set_child(self.view)
|
||||
if len(sys.argv) > 1:
|
||||
self.set_tests(pathlib.Path(sys.argv[1]))
|
||||
|
@ -241,23 +188,19 @@ class TestWindow(Gtk.ScrolledWindow):
|
|||
def set_tests(self, path):
|
||||
for column in [ c for c in self.view.get_columns() ]:
|
||||
self.view.remove_column(column)
|
||||
for n in range(self.notebook.get_n_pages()):
|
||||
self.notebook.remove_page(0)
|
||||
self.results.set_tests(path)
|
||||
for n in range(self.results.get_n_columns()):
|
||||
name = self.results.get_column_name(n)
|
||||
col = Gtk.ColumnViewColumn.new(name, TestResultsFactory(name))
|
||||
col.set_expand(n > 0)
|
||||
self.view.append_column(col)
|
||||
if n > 0:
|
||||
self.notebook.append_page(PropertyPage(name, self.results),
|
||||
Gtk.Label.new(name))
|
||||
|
||||
|
||||
class Window(Gtk.Window):
|
||||
def __init__(self):
|
||||
Gtk.Window.__init__(self, title="Xfstests Results")
|
||||
self.chooser = reporter.TestChooser()
|
||||
self.testview = reporter.TestView()
|
||||
self.passing = Gtk.Switch(halign=Gtk.Align.CENTER, active=True)
|
||||
self.lpass = Gtk.Label.new("Show Passing Tests")
|
||||
self.skipped = Gtk.Switch(halign=Gtk.Align.CENTER, active=True)
|
||||
|
@ -274,7 +217,7 @@ class Window(Gtk.Window):
|
|||
self.left.attach(self.lskip, 1, 2, 1, 1)
|
||||
|
||||
self.right = Gtk.Box.new(Gtk.Orientation.VERTICAL, 5)
|
||||
self.right.append(self.xfstests.notebook)
|
||||
self.right.append(self.testview)
|
||||
self.right.append(self.search)
|
||||
self.right.append(self.xfstests)
|
||||
|
||||
|
@ -282,8 +225,6 @@ class Window(Gtk.Window):
|
|||
self.child.append(self.left)
|
||||
self.child.append(self.right)
|
||||
|
||||
reporter.common.SizeGroup.add_widget(self.xfstests.notebook)
|
||||
|
||||
self.lskip.set_xalign(0)
|
||||
self.lpass.set_xalign(0)
|
||||
self.set_default_size(1100, 750)
|
||||
|
@ -295,9 +236,8 @@ class Window(Gtk.Window):
|
|||
self.search.connect("search-changed", self.search_changed)
|
||||
|
||||
def test_changed(self, window, file):
|
||||
self.testview.set_test_result(file)
|
||||
self.xfstests.set_tests(file.path if file else None)
|
||||
if file and file.get_is_test_result():
|
||||
results = reporter.testresults.TestResults(file.path)
|
||||
|
||||
def show_passing(self, passing, param):
|
||||
self.xfstests.set_show_passing(passing.get_active())
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/python
|
||||
from . import common
|
||||
from . import testchooser
|
||||
from . import testproperties
|
||||
from . import testresults
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
|
@ -18,3 +19,17 @@ class TestChooser(Gtk.Box):
|
|||
|
||||
@GObject.Signal(arg_types=(testchooser.Path,))
|
||||
def test_selected(self, path): pass
|
||||
|
||||
|
||||
class TestView(Gtk.Box):
|
||||
def __init__(self):
|
||||
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
|
||||
self.stack = testproperties.Stack()
|
||||
self.append(Gtk.StackSwitcher(stack=self.stack, halign=Gtk.Align.CENTER))
|
||||
self.append(self.stack)
|
||||
|
||||
def set_test_result(self, file):
|
||||
self.stack.clear()
|
||||
if file and file.get_is_test_result():
|
||||
results = testresults.TestResults(file.path)
|
||||
self.stack.show_properties(results)
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
#!/usr/bin/python
|
||||
from . import common
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gio
|
||||
from gi.repository import Gtk
|
||||
|
||||
PROPERTIES = [ "PLATFORM", "TIMESTAMP", "FSTYP", "MOUNT_OPTIONS", "CHECK_OPTIONS",
|
||||
"TEST_DIR", "TEST_DEV", "SCRATCH_DEV", "SCRATCH_MNT" ] #, "RESULTS" ]
|
||||
|
||||
class Property(GObject.GObject):
|
||||
def __init__(self, key, value):
|
||||
GObject.GObject.__init__(self)
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
||||
|
||||
class Results(Property):
|
||||
def __init__(self, properties):
|
||||
total = properties["TESTS"]
|
||||
time = properties["TIME"]
|
||||
failed = properties["FAILURES"]
|
||||
skipped = properties["SKIPPED"]
|
||||
passed = int(total) - (int(skipped) + int(failed))
|
||||
Property.__init__(self, "RESULTS",
|
||||
f"Ran {total} tests in {time} seconds: " \
|
||||
f"{passed} passed, {failed} failed, {skipped} skipped")
|
||||
|
||||
|
||||
class Model(GObject.GObject, Gio.ListModel):
|
||||
def __init__(self, properties):
|
||||
GObject.GObject.__init__(self)
|
||||
self.properties = [ Property(p, properties[p]) for p in PROPERTIES ]
|
||||
self.properties.append(Results(properties))
|
||||
|
||||
def do_get_item_type(self): return GObject.TYPE_PYOBJECT
|
||||
def do_get_n_items(self): return len(self.properties)
|
||||
def do_get_item(self, i): return self.properties[i]
|
||||
|
||||
|
||||
class Factory(Gtk.SignalListItemFactory):
|
||||
def __init__(self, column):
|
||||
Gtk.SignalListItemFactory.__init__(self)
|
||||
self.column = column
|
||||
self.connect("setup", self.on_setup)
|
||||
self.connect("bind", self.on_bind)
|
||||
self.connect("unbind", self.on_unbind)
|
||||
self.connect("teardown", self.on_teardown)
|
||||
|
||||
def on_setup(self, factory, listitem):
|
||||
listitem.set_child(Gtk.Label(xalign=0))
|
||||
|
||||
def on_bind(self, factory, listitem):
|
||||
label = listitem.get_child()
|
||||
match self.column:
|
||||
case "Property": label.set_text(listitem.get_item().key)
|
||||
case "Value": label.set_text(listitem.get_item().value)
|
||||
case _: label.set_text("=")
|
||||
|
||||
def on_unbind(self, factory, listitem):
|
||||
listitem.get_child().set_text("")
|
||||
|
||||
def on_teardown(self, factory, listitem):
|
||||
listitem.set_child(None)
|
||||
|
||||
|
||||
class View(Gtk.ColumnView):
|
||||
def __init__(self, properties):
|
||||
self.selection = Gtk.NoSelection.new(Model(properties))
|
||||
Gtk.ColumnView.__init__(self, model=self.selection)
|
||||
self.add_css_class("data-table")
|
||||
for title in [ "Property", "=", "Value" ]:
|
||||
self.append_column(Gtk.ColumnViewColumn.new(title, Factory(title)))
|
||||
|
||||
|
||||
class Stack(Gtk.Stack):
|
||||
def __init__(self):
|
||||
Gtk.Stack.__init__(self, transition_type=Gtk.StackTransitionType.OVER_LEFT_RIGHT)
|
||||
common.SizeGroup.add_widget(self)
|
||||
|
||||
def clear(self):
|
||||
pages = self.get_pages()
|
||||
children = [ pages.get_item(i).get_child() for i in range(pages.get_n_items()) ]
|
||||
for child in children:
|
||||
self.remove(child)
|
||||
|
||||
def show_properties(self, results):
|
||||
for version in results.versions:
|
||||
window = Gtk.ScrolledWindow(vscrollbar_policy=Gtk.PolicyType.NEVER,
|
||||
child=View(results.properties[version]))
|
||||
self.add_titled(window, version, version)
|
|
@ -61,7 +61,7 @@ class TestResults:
|
|||
self.add_testcase(elm.attrib["name"], file.stem, result)
|
||||
|
||||
def set_property(self, name, vers, value):
|
||||
self.properties.setdefault(name.upper(), dict())[vers] = value
|
||||
self.properties.setdefault(vers, dict())[name.upper()] = value
|
||||
|
||||
def add_testcase(self, name, vers, result):
|
||||
self.tests.setdefault(name, TestCase(name))[vers] = result
|
||||
|
|
Loading…
Reference in New Issue