Skip to content

Commit 528023d

Browse files
authored
[cueman] Add Unit Tests for Layer Display Formatting (AcademySoftwareFoundation#1971)
**Link the Issue(s) this Pull Request is related to.** - AcademySoftwareFoundation#1934 **Summarize your change.** This PR adds unit tests for the `displayLayers()` function in `cueman,` covering: - Layer table formatting and alignment - Header generation and spacing - Layer name truncation for long names - Frame statistics display (total, done, running, waiting, failed) - Tag display formatting - Empty layer handling - Large dataset formatting - Unicode character handling in layer names Co-authored-by: Ramon Figueiredo rfigueiredo@imageworks.com Co-authored-by: Aniket Singh Yadav <singhyadavaniket43@gmail.com>
1 parent 19041b4 commit 528023d

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed

cueman/tests/test_layer_display.py

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# Copyright Contributors to the OpenCue Project
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
"""
17+
Unit tests for displayLayers formatting in cueman.
18+
"""
19+
20+
from __future__ import absolute_import, division, print_function
21+
22+
import io
23+
import os
24+
import sys
25+
import unittest
26+
import warnings
27+
28+
import mock
29+
30+
# Suppress protobuf version warnings
31+
warnings.filterwarnings(
32+
"ignore", category=UserWarning, module="google.protobuf.runtime_version"
33+
)
34+
35+
# Add the parent directory to the path to import the module
36+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
37+
from cueman import main # pylint: disable=wrong-import-position
38+
39+
40+
class TestDisplayLayers(unittest.TestCase):
41+
"""Test cases for displayLayers formatting function."""
42+
43+
def setUp(self):
44+
"""Set up test fixtures."""
45+
self.mock_job = mock.Mock()
46+
self.mock_job.data.name = "TestJob"
47+
48+
def _capture_output(self, job):
49+
"""Helper method to capture stdout output from displayLayers.
50+
51+
Args:
52+
job: Mock job object to pass to displayLayers
53+
54+
Returns:
55+
Captured output as a string
56+
"""
57+
captured = io.StringIO()
58+
sys_stdout = sys.stdout
59+
sys.stdout = captured
60+
try:
61+
main.displayLayers(job)
62+
finally:
63+
sys.stdout = sys_stdout
64+
return captured.getvalue()
65+
66+
def test_header_and_alignment(self):
67+
"""Test that header is properly formatted and columns are aligned."""
68+
layer = mock.Mock()
69+
layer.data.name = "Layer1"
70+
layer.data.layer_stats.total_frames = 10
71+
layer.data.layer_stats.succeeded_frames = 5
72+
layer.data.layer_stats.running_frames = 2
73+
layer.data.layer_stats.waiting_frames = 2
74+
layer.data.layer_stats.dead_frames = 1
75+
layer.data.tags = ["tagA", "tagB"]
76+
self.mock_job.getLayers.return_value = [layer]
77+
output = self._capture_output(self.mock_job)
78+
79+
# Check header presence
80+
self.assertIn("Layer", output)
81+
self.assertIn("Total", output)
82+
self.assertIn("Done", output)
83+
self.assertIn("Running", output)
84+
self.assertIn("Waiting", output)
85+
self.assertIn("Failed", output)
86+
87+
# Check layer data
88+
self.assertIn("Layer1", output)
89+
self.assertIn("tags: tagA | tagB", output)
90+
91+
def test_layer_name_truncation(self):
92+
"""Test that long layer names are truncated to 29 characters."""
93+
long_name = "L" * 40
94+
layer = mock.Mock()
95+
layer.data.name = long_name
96+
layer.data.layer_stats.total_frames = 1
97+
layer.data.layer_stats.succeeded_frames = 1
98+
layer.data.layer_stats.running_frames = 0
99+
layer.data.layer_stats.waiting_frames = 0
100+
layer.data.layer_stats.dead_frames = 0
101+
layer.data.tags = []
102+
self.mock_job.getLayers.return_value = [layer]
103+
output = self._capture_output(self.mock_job)
104+
105+
# Should contain first 29 characters
106+
self.assertIn(long_name[:29], output)
107+
# Should not contain the full 40-character name
108+
self.assertNotIn(long_name, output)
109+
110+
def test_frame_statistics_display(self):
111+
"""Test that frame statistics are correctly displayed."""
112+
layer = mock.Mock()
113+
layer.data.name = "StatsLayer"
114+
layer.data.layer_stats.total_frames = 20
115+
layer.data.layer_stats.succeeded_frames = 10
116+
layer.data.layer_stats.running_frames = 5
117+
layer.data.layer_stats.waiting_frames = 3
118+
layer.data.layer_stats.dead_frames = 2
119+
layer.data.tags = []
120+
self.mock_job.getLayers.return_value = [layer]
121+
output = self._capture_output(self.mock_job)
122+
123+
# Check all statistics are present
124+
self.assertIn("20", output) # total
125+
self.assertIn("10", output) # succeeded
126+
self.assertIn("5", output) # running
127+
self.assertIn("3", output) # waiting
128+
self.assertIn("2", output) # dead/failed
129+
130+
def test_tag_display_formatting(self):
131+
"""Test that tags are formatted with pipe separators."""
132+
layer = mock.Mock()
133+
layer.data.name = "TagLayer"
134+
layer.data.layer_stats.total_frames = 1
135+
layer.data.layer_stats.succeeded_frames = 1
136+
layer.data.layer_stats.running_frames = 0
137+
layer.data.layer_stats.waiting_frames = 0
138+
layer.data.layer_stats.dead_frames = 0
139+
layer.data.tags = ["tag1", "tag2", "tag3"]
140+
self.mock_job.getLayers.return_value = [layer]
141+
output = self._capture_output(self.mock_job)
142+
143+
# Check tags formatting
144+
self.assertIn("tags: tag1 | tag2 | tag3", output)
145+
146+
def test_empty_layer_handling(self):
147+
"""Test handling of jobs with no layers."""
148+
self.mock_job.getLayers.return_value = []
149+
output = self._capture_output(self.mock_job)
150+
151+
# Should show 0 layers message
152+
self.assertIn("Job: TestJob has 0 layers", output)
153+
154+
def test_large_dataset_formatting(self):
155+
"""Test formatting with many layers."""
156+
layers = []
157+
for i in range(30):
158+
layer = mock.Mock()
159+
layer.data.name = f"Layer{i}"
160+
layer.data.layer_stats.total_frames = i
161+
layer.data.layer_stats.succeeded_frames = i // 2
162+
layer.data.layer_stats.running_frames = i // 4
163+
layer.data.layer_stats.waiting_frames = i // 8
164+
layer.data.layer_stats.dead_frames = i % 3
165+
layer.data.tags = []
166+
layers.append(layer)
167+
self.mock_job.getLayers.return_value = layers
168+
output = self._capture_output(self.mock_job)
169+
170+
# Check job summary
171+
self.assertIn("Job: TestJob has 30 layers", output)
172+
# Check first and last layers are present
173+
self.assertIn("Layer0", output)
174+
self.assertIn("Layer29", output)
175+
176+
def test_unicode_layer_name(self):
177+
"""Test handling of Unicode characters in layer names and tags."""
178+
layer = mock.Mock()
179+
layer.data.name = "LäyerÜñîçødë"
180+
layer.data.layer_stats.total_frames = 1
181+
layer.data.layer_stats.succeeded_frames = 1
182+
layer.data.layer_stats.running_frames = 0
183+
layer.data.layer_stats.waiting_frames = 0
184+
layer.data.layer_stats.dead_frames = 0
185+
layer.data.tags = ["täg"]
186+
self.mock_job.getLayers.return_value = [layer]
187+
output = self._capture_output(self.mock_job)
188+
189+
# Check Unicode handling
190+
self.assertIn("LäyerÜñîçødë", output)
191+
self.assertIn("täg", output)
192+
193+
194+
if __name__ == "__main__":
195+
unittest.main()

0 commit comments

Comments
 (0)