Add test coverage of status class

This commit is contained in:
Veronica Berglyd Olsen
2024-04-10 22:19:15 +02:00
parent adfd003532
commit d1dbb0b378
3 changed files with 146 additions and 78 deletions
+5 -2
View File
@@ -57,8 +57,11 @@ class StatusEntry:
@classmethod
def duplicate(cls, source: StatusEntry) -> StatusEntry:
"""Create a shallow copy of the source object."""
return dataclasses.replace(source)
"""Create a deep copy of the source object."""
cls = dataclasses.replace(source)
cls.color = QColor(source.color)
cls.icon = QIcon(source.icon)
return cls
# END Class StatusEntry
+1 -1
View File
@@ -75,7 +75,7 @@ class MockStatusBar:
class MockTheme:
def __init__(self):
self.baseIconHeight = 10
self.baseIconHeight = 20
return
def getPixmap(self, *a):
+140 -75
View File
@@ -26,7 +26,7 @@ from tools import C
from PyQt5.QtGui import QColor, QIcon
from novelwriter.core.status import NWStatus
from novelwriter.core.status import NWStatus, StatusEntry, _ShapeCache
from novelwriter.enum import nwStatusShape
statusKeys = [C.sNew, C.sNote, C.sDraft, C.sFinished]
@@ -34,7 +34,36 @@ importKeys = [C.iNew, C.iMinor, C.iMajor, C.iMain]
@pytest.mark.core
def testCoreStatus_Internal(mockRnd):
def testCoreStatus_StatusEntry():
"""Test the StatusEntry class."""
color = QColor(255, 0, 0)
icon = NWStatus.createIcon(24, color, nwStatusShape.CIRCLE)
entry = StatusEntry("Test", color, nwStatusShape.CIRCLE, icon, 42)
# Check values
assert entry.name == "Test"
assert entry.color is color
assert entry.shape == nwStatusShape.CIRCLE
assert entry.icon is icon
assert entry.count == 42
# Make a copy
other = StatusEntry.duplicate(entry)
assert other is not entry
# Check copy is not the same
assert other.name == "Test"
assert other.color is not color # Not the same object
assert other.color == color # But same colours
assert other.shape == nwStatusShape.CIRCLE
assert other.icon is not icon # Not the same icon, but a copy
assert other.count == 42
# END Test testCoreStatus_StatusEntry
@pytest.mark.core
def testCoreStatus_Internal(mockGUI, mockRnd):
"""Test all the internal functions of the NWStatus class."""
nStatus = NWStatus(NWStatus.STATUS)
nImport = NWStatus(NWStatus.IMPORT)
@@ -82,18 +111,25 @@ def testCoreStatus_Internal(mockRnd):
assert nImport._isKey("i12345F") is False # Not a lower case hex value
assert nImport._isKey("i12345f") is True # Valid hex value
assert nStatus._checkKey(None) == "s000008" # Creates next key
assert nStatus._checkKey("s654321") == "s654321" # Status key accepted
assert nStatus._checkKey("i123456") == "s000009" # Import key not accepted
assert nImport._checkKey(None) == "i00000a" # Creates next key
assert nImport._checkKey("s654321") == "i00000b" # Status key not accepted
assert nImport._checkKey("i123456") == "i123456" # Import key accepted
# END Test testCoreStatus_Internal
@pytest.mark.core
def testCoreStatus_Iterator(mockRnd):
def testCoreStatus_Iterator(mockGUI, mockRnd):
"""Test the iterator functions of the NWStatus class."""
nStatus = NWStatus(NWStatus.STATUS)
nStatus.add(None, "New", (100, 100, 100), "SQUARE", 0)
nStatus.add(None, "Note", (200, 50, 0), "SQUARE", 0)
nStatus.add(None, "Draft", (200, 150, 0), "SQUARE", 0)
nStatus.add(None, "Finished", (50, 200, 0), "SQUARE", 0)
nStatus.add(None, "Note", (200, 50, 0), "CIRCLE", 1)
nStatus.add(None, "Draft", (200, 150, 0), "SQUARE", 2)
nStatus.add(None, "Finished", (50, 200, 0), "CIRCLE", 3)
# Direct access
entry = nStatus[statusKeys[0]]
@@ -106,36 +142,63 @@ def testCoreStatus_Iterator(mockRnd):
assert len(nStatus._store) == 4
assert len(nStatus) == 4
# Content : Keys
assert [k for k, _ in nStatus.iterItems()] == [
"s000000", "s000001", "s000002", "s000003"
]
# Content : Names
assert [e.name for _, e in nStatus.iterItems()] == [
"New", "Note", "Draft", "Finished"
]
# Content : Colours
assert [e.color for _, e in nStatus.iterItems()] == [
QColor(100, 100, 100), QColor(200, 50, 0), QColor(200, 150, 0), QColor(50, 200, 0)
]
# Content : Shape
assert [e.shape for _, e in nStatus.iterItems()] == [
nwStatusShape.SQUARE, nwStatusShape.CIRCLE, nwStatusShape.SQUARE, nwStatusShape.CIRCLE
]
# Content : Count
assert [e.count for _, e in nStatus.iterItems()] == [0, 1, 2, 3]
# END Test testCoreStatus_Iterator
@pytest.mark.core
def testCoreStatus_Entries(mockRnd):
def testCoreStatus_Entries(mockGUI, mockRnd):
"""Test all the simple setters for the NWStatus class."""
nStatus = NWStatus(NWStatus.STATUS)
# Write
# =====
# Add
# ===
# Have a key
# Has a key
nStatus.add(statusKeys[0], "Entry 1", (200, 100, 50), "SQUARE", 0)
assert nStatus[statusKeys[0]].name == "Entry 1"
assert nStatus[statusKeys[0]].color == QColor(200, 100, 50)
assert nStatus[statusKeys[0]].shape == nwStatusShape.SQUARE
# Don't have a key
# Doesn't have a key
nStatus.add(None, "Entry 2", (210, 110, 60), "SQUARE", 0)
assert nStatus[statusKeys[1]].name == "Entry 2"
assert nStatus[statusKeys[1]].color == QColor(210, 110, 60)
assert nStatus[statusKeys[1]].shape == nwStatusShape.SQUARE
# Wrong colour spec
nStatus.add(None, "Entry 3", "what?", "SQUARE", 0) # type: ignore
# Wrong colour spec, unknown shape
nStatus.add(None, "Entry 3", "what?", "", 0) # type: ignore
assert nStatus[statusKeys[2]].name == "Entry 3"
assert nStatus[statusKeys[2]].color == QColor(100, 100, 100)
assert nStatus[statusKeys[2]].shape == nwStatusShape.SQUARE
# Wrong colour count
nStatus.add(None, "Entry 4", (10, 20), "SQUARE", 0) # type: ignore
nStatus.add(None, "Entry 4", (10, 20), "CIRCLE", 0) # type: ignore
assert nStatus[statusKeys[3]].name == "Entry 4"
assert nStatus[statusKeys[3]].color == QColor(100, 100, 100)
assert nStatus[statusKeys[3]].shape == nwStatusShape.CIRCLE
# Check
# =====
@@ -174,6 +237,15 @@ def testCoreStatus_Entries(mockRnd):
assert isinstance(nStatus[statusKeys[3]].icon, QIcon)
assert isinstance(nStatus["blablabla"].icon, QIcon)
# Shape Access
# ============
assert nStatus[statusKeys[0]].shape == nwStatusShape.SQUARE
assert nStatus[statusKeys[1]].shape == nwStatusShape.SQUARE
assert nStatus[statusKeys[2]].shape == nwStatusShape.SQUARE
assert nStatus[statusKeys[3]].shape == nwStatusShape.CIRCLE
assert nStatus["blablabla"].shape == nwStatusShape.SQUARE
# Increment and Count Access
# ==========================
@@ -195,37 +267,19 @@ def testCoreStatus_Entries(mockRnd):
assert nStatus[statusKeys[2]].count == 0
assert nStatus[statusKeys[3]].count == 0
# Reorder
# =======
# Update
# ======
# cOrder = list(nStatus._store.keys())
# assert cOrder == statusKeys
assert list(nStatus._store.keys()) == statusKeys
# # Wrong length
# assert nStatus.reorder([]) is False
# Reverse
order: list[tuple[str | None, StatusEntry]] = list(nStatus.iterItems())
nStatus.update(list(reversed(order)))
assert list(nStatus._store.keys()) == list(reversed(statusKeys))
# # No change
# assert nStatus.reorder(cOrder) is False
# # Actual re-order
# nOrder = [
# statusKeys[0],
# statusKeys[2],
# statusKeys[1],
# statusKeys[3],
# ]
# assert nStatus.reorder(nOrder) is True
# assert list(nStatus._store.keys()) == nOrder
# # Add an unknown key
# wOrder = nOrder.copy()
# wOrder[3] = nStatus._newKey()
# assert nStatus.reorder(wOrder) is False
# assert list(nStatus._store.keys()) == nOrder
# # Put it back
# assert nStatus.reorder(cOrder) is True
# assert list(nStatus._store.keys()) == cOrder
# Restore
nStatus.update(order)
assert list(nStatus._store.keys()) == statusKeys
# Default
# =======
@@ -242,46 +296,31 @@ def testCoreStatus_Entries(mockRnd):
nStatus._default = default
# # Remove
# # ======
# Remove
# ======
# This uses update with deleted items
# # Non-existing entry
# assert nStatus.remove("blablabla") is False
order: list[tuple[str | None, StatusEntry]] = list(nStatus.iterItems())
# # Non-zero entry
# nStatus.increment(statusKeys[3])
# assert nStatus.remove(statusKeys[3]) is False
# Remove Entry 0
nStatus.update([order[1], order[3], order[2]])
assert list(nStatus._store.keys()) == [statusKeys[1], statusKeys[3], statusKeys[2]]
assert nStatus._default == statusKeys[1]
# # Delete last entry
# nStatus.resetCounts()
# lastName = nStatus[statusKeys[3]].name
# assert lastName == "Entry 4"
# assert nStatus.remove(statusKeys[3]) is True
# assert nStatus.check(statusKeys[3]) == nStatus._default
# assert nStatus.check(lastName) == nStatus._default
# # Delete default entry, Entry 2 is new default
# firstName = nStatus[nStatus._default].name
# assert firstName == "Entry 1"
# assert nStatus.remove(nStatus._default) is True # type: ignore
# assert nStatus[firstName].name == "Entry 2"
# # Remove remaining entries
# assert nStatus.remove(statusKeys[1]) is True
# assert nStatus.remove(statusKeys[2]) is True
# assert len(nStatus) == 0
# assert nStatus._default is None
# Remove Entry 1
nStatus.update([order[3], order[2]])
assert list(nStatus._store.keys()) == [statusKeys[3], statusKeys[2]]
assert nStatus._default == statusKeys[3]
# END Test testCoreStatus_Entries
@pytest.mark.core
def testCoreStatus_PackUnpack(mockRnd):
"""Test all the pack/unpack of the NWStatus class."""
def testCoreStatus_Pack(mockGUI, mockRnd):
"""Test data packing of the NWStatus class."""
nStatus = NWStatus(NWStatus.STATUS)
nStatus.add(None, "New", (100, 100, 100), "SQUARE", 0)
nStatus.add(None, "Note", (200, 50, 0), "SQUARE", 0)
nStatus.add(None, "Note", (200, 50, 0), "CIRCLE", 0)
nStatus.add(None, "Draft", (200, 150, 0), "SQUARE", 0)
nStatus.add(None, "Finished", (50, 200, 0), "SQUARE", 0)
@@ -306,7 +345,7 @@ def testCoreStatus_PackUnpack(mockRnd):
"red": "200",
"green": "50",
"blue": "0",
"shape": "SQUARE",
"shape": "CIRCLE",
}),
("Draft", {
"key": statusKeys[2],
@@ -326,4 +365,30 @@ def testCoreStatus_PackUnpack(mockRnd):
}),
]
# END Test testCoreStatus_PackUnpack
# END Test testCoreStatus_Pack
@pytest.mark.core
def testCoreStatus_ShapeCache():
"""Test the _ShapeCache class."""
shapes = _ShapeCache()
# Generate all shapes
square = shapes.getShape(nwStatusShape.SQUARE)
circle = shapes.getShape(nwStatusShape.CIRCLE)
triangle = shapes.getShape(nwStatusShape.TRIANGLE)
diamond = shapes.getShape(nwStatusShape.DIAMOND)
pentagon = shapes.getShape(nwStatusShape.PENTAGON)
star = shapes.getShape(nwStatusShape.STAR)
pacman = shapes.getShape(nwStatusShape.PACMAN)
# Request again should return from cache
assert shapes.getShape(nwStatusShape.SQUARE) is square
assert shapes.getShape(nwStatusShape.CIRCLE) is circle
assert shapes.getShape(nwStatusShape.TRIANGLE) is triangle
assert shapes.getShape(nwStatusShape.DIAMOND) is diamond
assert shapes.getShape(nwStatusShape.PENTAGON) is pentagon
assert shapes.getShape(nwStatusShape.STAR) is star
assert shapes.getShape(nwStatusShape.PACMAN) is pacman
# END Test testCoreStatus_ShapeCache