gtk: Create an XunitList base class
The XunitList implements the Gio.ListModel interface, and builds in some virtual functions to query and fill out the rows in the list in a standard way. I also update the TestCaseList and SummaryList to both inherit from this class. Signed-off-by: Anna Schumaker <anna@nowheycreamery.com>
This commit is contained in:
parent
c45ec1909e
commit
5dc7735ba7
|
@ -58,6 +58,49 @@ class TestXunitRow(unittest.TestCase):
|
|||
self.assertEqual(xunit.name, "xunit-2")
|
||||
|
||||
|
||||
class TestXunitList(unittest.TestCase):
|
||||
"""Test case for our base XunitList object."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up common variables."""
|
||||
self.xfstestsdb = xfstestsdb.Command()
|
||||
with unittest.mock.patch("sys.stdout"):
|
||||
self.xfstestsdb.run(["new", "/dev/vda1"])
|
||||
self.xfstestsdb.run(["xunit", "read", "--name", "xunit-1",
|
||||
"1", str(tests.xunit.XUNIT_1)])
|
||||
self.xfstestsdb.run(["xunit", "read", "--name", "xunit-2",
|
||||
"1", str(tests.xunit.XUNIT_1)])
|
||||
|
||||
self.xulist = xfstestsdb.gtk.model.XunitList(self.xfstestsdb.sql, 1)
|
||||
|
||||
def test_init(self):
|
||||
"""Test that the XunitList was set up properly."""
|
||||
self.assertIsInstance(self.xulist, GObject.GObject)
|
||||
self.assertIsInstance(self.xulist, Gio.ListModel)
|
||||
self.assertEqual(self.xulist.runid, 1)
|
||||
|
||||
def test_get_item_type(self):
|
||||
"""Test the get_item_type() function."""
|
||||
self.assertEqual(self.xulist.get_item_type(),
|
||||
xfstestsdb.gtk.model.XunitRow.__gtype__)
|
||||
|
||||
def test_get_n_items(self):
|
||||
"""Test the get_n_items() function."""
|
||||
self.assertEqual(self.xulist.get_n_items(), 0)
|
||||
self.assertEqual(self.xulist.n_items, 0)
|
||||
|
||||
self.xulist.n_items = 2
|
||||
self.assertEqual(self.xulist.get_n_items(), 2)
|
||||
|
||||
def test_get_item(self):
|
||||
"""Test the get_item() function."""
|
||||
self.assertIsNone(self.xulist.get_item(0))
|
||||
|
||||
def test_get_xunits(self):
|
||||
"""Test the get_xunits() function."""
|
||||
self.assertListEqual(self.xulist.get_xunits(), ["xunit-1", "xunit-2"])
|
||||
|
||||
|
||||
class TestTestResult(unittest.TestCase):
|
||||
"""Tests a single TestCase Xunit instance."""
|
||||
|
||||
|
@ -133,18 +176,8 @@ class TestCaseList(unittest.TestCase):
|
|||
|
||||
def test_init(self):
|
||||
"""Test that the TestCaseList was set up properly."""
|
||||
self.assertIsInstance(self.tclist, GObject.GObject)
|
||||
self.assertIsInstance(self.tclist, Gio.ListModel)
|
||||
self.assertIsInstance(self.tclist, xfstestsdb.gtk.model.XunitList)
|
||||
self.assertEqual(self.tclist.runid, 1)
|
||||
|
||||
def test_get_item_type(self):
|
||||
"""Test the get_item_type() function."""
|
||||
self.assertEqual(self.tclist.get_item_type(),
|
||||
xfstestsdb.gtk.model.TestCase.__gtype__)
|
||||
|
||||
def test_get_n_items(self):
|
||||
"""Test the get_n_items() function."""
|
||||
self.assertEqual(self.tclist.get_n_items(), 10)
|
||||
self.assertEqual(self.tclist.n_items, 10)
|
||||
|
||||
def test_get_item(self):
|
||||
|
@ -163,10 +196,6 @@ class TestCaseList(unittest.TestCase):
|
|||
|
||||
self.assertIsNone(self.tclist.get_item(10))
|
||||
|
||||
def test_get_xunits(self):
|
||||
"""Test the get_xunits() function."""
|
||||
self.assertListEqual(self.tclist.get_xunits(), ["xunit-1", "xunit-2"])
|
||||
|
||||
|
||||
class TestCaseFilter(unittest.TestCase):
|
||||
"""Tests our Gtk.Filter customized for filtering TestCases."""
|
||||
|
@ -314,18 +343,8 @@ class TestSummaryList(unittest.TestCase):
|
|||
|
||||
def test_init(self):
|
||||
"""Test that the SummaryList was set up properly."""
|
||||
self.assertIsInstance(self.summary, GObject.GObject)
|
||||
self.assertIsInstance(self.summary, Gio.ListModel)
|
||||
self.assertIsInstance(self.summary, xfstestsdb.gtk.model.XunitList)
|
||||
self.assertEqual(self.summary.runid, 1)
|
||||
|
||||
def test_get_item_type(self):
|
||||
"""Test the get_item_type() function."""
|
||||
self.assertEqual(self.summary.get_item_type(),
|
||||
xfstestsdb.gtk.model.Summary.__gtype__)
|
||||
|
||||
def test_get_n_items(self):
|
||||
"""Test the get_n_items() function."""
|
||||
self.assertEqual(self.summary.get_n_items(), 4)
|
||||
self.assertEqual(self.summary.n_items, 4)
|
||||
|
||||
def test_get_item(self):
|
||||
|
@ -342,7 +361,3 @@ class TestSummaryList(unittest.TestCase):
|
|||
case "skipped": expected = {"3 testcases"}
|
||||
case "time": expected = {"43 seconds"}
|
||||
self.assertSetEqual(summary.get_results(), expected)
|
||||
|
||||
def test_get_xunits(self):
|
||||
"""Test the get_xunits() function."""
|
||||
self.assertListEqual(self.summary.get_xunits(), ["xunit-1", "xunit-2"])
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Copyright 2023 (c) Anna Schumaker.
|
||||
"""Our Testcase Gio.ListModel."""
|
||||
import sqlite3
|
||||
import typing
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gio
|
||||
|
@ -48,6 +49,50 @@ class XunitRow(GObject.GObject):
|
|||
return {str(xunit) for xunit in self.__xunits.values()}
|
||||
|
||||
|
||||
class XunitList(GObject.GObject, Gio.ListModel):
|
||||
"""A list of XunitRows for a specific Xfstests Run."""
|
||||
|
||||
runid = GObject.Property(type=int)
|
||||
n_items = GObject.Property(type=int)
|
||||
|
||||
def __init__(self, sql: sqlite.Connection, runid: int) -> None:
|
||||
"""Initialize an XunitList."""
|
||||
super().__init__(runid=runid)
|
||||
self.__xunits = set()
|
||||
|
||||
rows = {}
|
||||
for row in self.do_query(sql).fetchall():
|
||||
self.do_parse(rows, row)
|
||||
self.__xunits.add(row["xunit"])
|
||||
|
||||
self.__items = sorted(rows.values())
|
||||
self.n_items = len(self.__items)
|
||||
|
||||
def do_get_item_type(self) -> GObject.GType:
|
||||
"""Get the type of the objects in the list."""
|
||||
return XunitRow.__gtype__
|
||||
|
||||
def do_get_n_items(self) -> int:
|
||||
"""Get the number of items in the list."""
|
||||
return self.n_items
|
||||
|
||||
def do_get_item(self, n: int) -> XunitRow | None:
|
||||
"""Get a specific item on the list."""
|
||||
return self.__items[n] if n < self.n_items else None
|
||||
|
||||
def do_parse(self, rows: dict[XunitRow], row: sqlite3.Row) -> None:
|
||||
"""Parse a sqlite3.Row and add it to the rows dict."""
|
||||
|
||||
def do_query(self, sql: sqlite.Connection) -> sqlite3.Cursor:
|
||||
"""Query the database."""
|
||||
return sql("SELECT name AS xunit FROM xunits WHERE runid=?",
|
||||
self.runid)
|
||||
|
||||
def get_xunits(self) -> list[str]:
|
||||
"""Get a list of xunits attached to this xfstests run."""
|
||||
return sorted(self.__xunits)
|
||||
|
||||
|
||||
class TestResult(XunitCell):
|
||||
"""The results for a single TestCase with a specific Xunit."""
|
||||
|
||||
|
@ -75,46 +120,20 @@ class TestCase(XunitRow):
|
|||
stderr=("" if stderr is None else stderr))
|
||||
|
||||
|
||||
class TestCaseList(GObject.GObject, Gio.ListModel):
|
||||
class TestCaseList(XunitList):
|
||||
"""A list of TestCases for a specific Xfstests Run."""
|
||||
|
||||
runid = GObject.Property(type=int)
|
||||
n_items = GObject.Property(type=int)
|
||||
def do_query(self, sql: sqlite.Connection) -> sqlite3.Cursor:
|
||||
"""Query the database for testcase results."""
|
||||
return sql("""SELECT testcase, xunit, status, time,
|
||||
message, stdout, stderr
|
||||
FROM testcases_view WHERE runid=?""", self.runid)
|
||||
|
||||
def __init__(self, sql: sqlite.Connection, runid: int) -> None:
|
||||
"""Initialize a TestCaseList."""
|
||||
super().__init__(runid=runid)
|
||||
self.__xunits = set()
|
||||
|
||||
cases = {}
|
||||
cur = sql("""SELECT testcase, xunit, status,
|
||||
time, message, stdout, stderr
|
||||
FROM testcases_view WHERE runid=?""", runid)
|
||||
for row in cur.fetchall():
|
||||
testcase = cases.setdefault(row["testcase"],
|
||||
TestCase(row["testcase"]))
|
||||
testcase.add_xunit(row["xunit"], row["status"], row["time"],
|
||||
row["message"], row["stdout"], row["stderr"])
|
||||
self.__xunits.add(row["xunit"])
|
||||
|
||||
self.__items = sorted(cases.values())
|
||||
self.n_items = len(self.__items)
|
||||
|
||||
def do_get_item_type(self) -> GObject.GType:
|
||||
"""Get the type of the objects in the list."""
|
||||
return TestCase.__gtype__
|
||||
|
||||
def do_get_n_items(self) -> int:
|
||||
"""Get the number of items in the list."""
|
||||
return self.n_items
|
||||
|
||||
def do_get_item(self, n: int) -> TestCase | None:
|
||||
"""Get a specific item on the list."""
|
||||
return self.__items[n] if n < self.n_items else None
|
||||
|
||||
def get_xunits(self) -> list[str]:
|
||||
"""Get a list of xunits attached to this xfstests run."""
|
||||
return sorted(self.__xunits)
|
||||
def do_parse(self, rows: dict[TestCase], row: sqlite3.Cursor) -> None:
|
||||
"""Parse the data in the row and add it to the rows dict."""
|
||||
testcase = rows.setdefault(row["testcase"], TestCase(row["testcase"]))
|
||||
testcase.add_xunit(row["xunit"], row["status"], row["time"],
|
||||
row["message"], row["stdout"], row["stderr"])
|
||||
|
||||
|
||||
class TestCaseFilter(Gtk.Filter):
|
||||
|
@ -183,42 +202,17 @@ class Summary(XunitRow):
|
|||
return SummaryValue(name=name, value=value, unit=unit)
|
||||
|
||||
|
||||
class SummaryList(GObject.GObject, Gio.ListModel):
|
||||
class SummaryList(XunitList):
|
||||
"""A list summarizing the results of a specific Xfstests Run."""
|
||||
|
||||
runid = GObject.Property(type=int)
|
||||
n_items = GObject.Property(type=int)
|
||||
def do_query(self, sql: sqlite.Connection) -> sqlite3.Cursor:
|
||||
"""Query the database for xunit summaries."""
|
||||
return sql("""SELECT name AS xunit, passed, failed, skipped, time
|
||||
FROM xunits_view WHERE runid=?""", self.runid)
|
||||
|
||||
def __init__(self, sql: sqlite.Connection, runid: int) -> None:
|
||||
"""Initialize a SummaryList."""
|
||||
super().__init__(runid=runid)
|
||||
self.__xunits = set()
|
||||
|
||||
results = {}
|
||||
cur = sql("""SELECT name AS xunit, passed, failed, skipped, time
|
||||
FROM xunits_view WHERE runid=?""", runid)
|
||||
for row in cur.fetchall():
|
||||
for field in ["passed", "failed", "skipped", "time"]:
|
||||
summary = results.setdefault(field, Summary(field))
|
||||
summary.add_xunit(row["xunit"], row[field],
|
||||
"second" if field == "time" else "testcase")
|
||||
self.__xunits.add(row["xunit"])
|
||||
|
||||
self.__items = sorted(results.values())
|
||||
self.n_items = len(self.__items)
|
||||
|
||||
def do_get_item_type(self) -> GObject.GType:
|
||||
"""Get the type of the objects in the list."""
|
||||
return Summary.__gtype__
|
||||
|
||||
def do_get_n_items(self) -> int:
|
||||
"""Get the number of items in the list."""
|
||||
return self.n_items
|
||||
|
||||
def do_get_item(self, n: int) -> Summary | None:
|
||||
"""Get a specific item on the list."""
|
||||
return self.__items[n] if n < self.n_items else None
|
||||
|
||||
def get_xunits(self) -> list[str]:
|
||||
"""Get a list of xunits attached to this xfstests run."""
|
||||
return sorted(self.__xunits)
|
||||
def do_parse(self, rows: dict[Summary], row: sqlite3.Row) -> None:
|
||||
"""Parse the data in the row and add it to the rows dict."""
|
||||
for field in ["passed", "failed", "skipped", "time"]:
|
||||
summary = rows.setdefault(field, Summary(field))
|
||||
summary.add_xunit(row["xunit"], row[field],
|
||||
"second" if field == "time" else "testcase")
|
||||
|
|
Loading…
Reference in New Issue