gtk: Create a TestCaseView and XfstestsView

The XfstestsView contains the TestCaseView, and will eventually contain
other views used to display test results and information.

For the moment, the TestCaseView displays the name of the testcases in a
single Xfstests run in a single column. I plan on adding more columns in
the near future.

Signed-off-by: Anna Schumaker <anna@nowheycreamery.com>
This commit is contained in:
Anna Schumaker 2023-08-01 15:33:02 -04:00
parent 4bce147e45
commit 796cf6eec7
4 changed files with 163 additions and 1 deletions

100
tests/gtk/test_view.py Normal file
View File

@ -0,0 +1,100 @@
# Copyright 2023 (c) Anna Schumaker.
"""Tests our TestCaseView for displaying xfstests results."""
import unittest
import tests.xunit
import xfstestsdb.gtk.view
from gi.repository import Gtk
class TestTestCaseView(unittest.TestCase):
"""Tests the TestCaseView."""
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.model = xfstestsdb.gtk.model.TestCaseList(self.xfstestsdb.sql, 1)
self.view = xfstestsdb.gtk.view.TestCaseView()
def test_init(self):
"""Test that we create the TestCaseView correctly."""
self.assertIsInstance(self.view, Gtk.ScrolledWindow)
self.assertTrue(self.view.has_css_class("card"))
self.assertIsNone(self.view.model)
def test_columnview(self):
"""Test that we set up the Columnview correctly."""
self.assertIsInstance(self.view.props.child, Gtk.ColumnView)
self.assertIsInstance(self.view.props.child.get_model(),
Gtk.NoSelection)
self.assertEqual(len(self.view.props.child.get_columns()), 0)
self.assertTrue(self.view.props.child.get_show_column_separators())
self.assertTrue(self.view.props.child.get_show_row_separators())
self.assertTrue(self.view.props.child.get_hexpand())
self.assertTrue(self.view.props.child.get_vexpand())
def test_testcase_column(self):
"""Test that we set up the 'testcase' column correctly."""
self.assertIsInstance(self.view._testcase, Gtk.ColumnViewColumn)
self.assertIsInstance(self.view._testcase.props.factory,
xfstestsdb.gtk.row.LabelFactory)
self.assertEqual(self.view._testcase.props.factory.property, "name")
self.assertEqual(self.view._testcase.props.title, "testcase")
self.assertFalse(self.view._testcase.props.expand)
def test_model(self):
"""Test setting the model property."""
self.view.model = self.model
self.assertEqual(self.view.props.child.get_model().get_model(),
self.model)
columns = self.view.props.child.get_columns()
self.assertEqual(len(columns), 1)
self.assertEqual(columns[0], self.view._testcase)
self.view.model = None
self.assertEqual(len(self.view.props.child.get_columns()), 0)
self.view.model = self.model
self.assertEqual(self.view.props.child.get_columns()[0],
self.view._testcase)
class TestXfstestsView(unittest.TestCase):
"""Test the XfstestsView."""
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.model = xfstestsdb.gtk.model.TestCaseList(self.xfstestsdb.sql, 1)
self.view = xfstestsdb.gtk.view.XfstestsView()
def test_init(self):
"""Check that the XfstestsView was set up correctly."""
self.assertIsInstance(self.view, Gtk.Box)
self.assertEqual(self.view.props.orientation, Gtk.Orientation.VERTICAL)
def test_testcase_view(self):
"""Check that the XfstestsView sets up a TestCaseView correctly."""
self.assertIsInstance(self.view._testcaseview,
xfstestsdb.gtk.view.TestCaseView)
self.assertEqual(self.view.get_first_child(), self.view._testcaseview)
def test_model(self):
"""Test the XfstestsView 'model' property."""
self.assertIsNone(self.view.model)
self.view.model = self.model
self.assertEqual(self.view._testcaseview.model, self.model)

View File

@ -62,17 +62,25 @@ class TestApplication(unittest.TestCase):
mock_add_window: unittest.mock.Mock):
"""Check that startup sets up our application instance correctly."""
self.assertIsNone(self.application.win)
self.assertIsNone(self.application.view)
self.application.emit("startup")
self.assertIsInstance(self.application.view,
xfstestsdb.gtk.view.XfstestsView)
self.assertIsInstance(self.application.win,
xfstestsdb.gtk.window.Window)
self.assertEqual(self.application.win.child, self.application.view)
mock_startup.assert_called_with(self.application)
mock_add_window.assert_called_with(self.application.win)
self.application.runid = 42
self.assertEqual(self.application.win.runid, 42)
model = xfstestsdb.gtk.model.TestCaseList(self.xfstestsdb.sql, 42)
self.application.model = model
self.assertEqual(self.application.view.model, model)
@unittest.mock.patch("gi.repository.Adw.Application.add_window")
@unittest.mock.patch("gi.repository.Adw.Application.do_startup")
@unittest.mock.patch("gi.repository.Adw.Application.do_activate")

View File

@ -8,6 +8,7 @@ from gi.repository import GObject
from gi.repository import Gio
from gi.repository import Adw
from . import model
from . import view
from . import window
from .. import commands
from .. import sqlite
@ -19,6 +20,7 @@ class Application(Adw.Application):
runid = GObject.Property(type=int)
model = GObject.Property(type=model.TestCaseList)
win = GObject.Property(type=window.Window)
view = GObject.Property(type=view.XfstestsView)
sql = GObject.Property(type=GObject.TYPE_PYOBJECT)
def __init__(self, sql: sqlite.Connection):
@ -44,8 +46,10 @@ class Application(Adw.Application):
def do_startup(self) -> None:
"""Handle the Adw.Application::startup signal."""
Adw.Application.do_startup(self)
self.win = window.Window()
self.view = view.XfstestsView()
self.win = window.Window(child=self.view)
self.bind_property("runid", self.win, "runid")
self.bind_property("model", self.view, "model")
self.add_window(self.win)
def do_activate(self) -> None:

50
xfstestsdb/gtk/view.py Normal file
View File

@ -0,0 +1,50 @@
# Copyright 2023 (c) Anna Schumaker.
"""A view widget used to display our TestCaseModel."""
from gi.repository import GObject
from gi.repository import Gtk
from .model import TestCaseList
from . import row
class TestCaseView(Gtk.ScrolledWindow):
"""Displays our TestCaseList model to the user."""
def __init__(self):
"""Initialize a TestCaseView."""
super().__init__(child=Gtk.ColumnView(model=Gtk.NoSelection(),
show_row_separators=True,
show_column_separators=True,
hexpand=True, vexpand=True))
self._testcase = Gtk.ColumnViewColumn(title="testcase",
factory=row.LabelFactory("name"))
self.add_css_class("card")
@GObject.Property(type=TestCaseList)
def model(self) -> TestCaseList:
"""Get the TestCaseList shown by the View."""
return self.props.child.get_model().get_model()
@model.setter
def model(self, new: TestCaseList) -> None:
for col in [col for col in self.props.child.get_columns()]:
self.props.child.remove_column(col)
self.props.child.get_model().set_model(new)
if new is not None:
self.props.child.append_column(self._testcase)
class XfstestsView(Gtk.Box):
"""A widget to display the results of an Xfstests runs."""
model = GObject.Property(type=TestCaseList)
def __init__(self):
"""Initialize an XfstestsView."""
super().__init__(orientation=Gtk.Orientation.VERTICAL)
self._testcaseview = TestCaseView()
self.bind_property("model", self._testcaseview, "model")
self.append(self._testcaseview)