commit 60a576541d981ec8304cc91c2cf3f536f9bc7cbb Author: Damian Johnson atagar@torproject.org Date: Thu Apr 7 10:34:22 2016 -0700
Adding @require_curses decorator
Similar to the @require_controller and @require_online of Stem, adding a decorator for our tests that do curses operations. This skips the test if the screen size is too small, and mocks out a size that works even on my tiny netbook. --- test/__init__.py | 31 ++++++++++++++++++++++++++++--- test/popups.py | 28 ++++++++++++++-------------- 2 files changed, 42 insertions(+), 17 deletions(-)
diff --git a/test/__init__.py b/test/__init__.py index 705e9b1..b606b4a 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -9,7 +9,6 @@ import unittest import nyx.curses
from nyx import expand_path, join, uses_settings - from mock import patch, Mock
__all__ = [ @@ -20,13 +19,39 @@ __all__ = [ 'tracker', ]
-# If set we make test content we render for this many seconds. +SHOW_RENDERED_CONTENT = None # if set, tests render content this many seconds
-SHOW_RENDERED_CONTENT = None +OUR_SCREEN_SIZE = None +TEST_SCREEN_SIZE = nyx.curses.Dimensions(80, 25)
RenderResult = collections.namedtuple('RenderResult', ['content', 'return_value', 'runtime'])
+def require_curses(func): + """ + Skips the test unless curses is available with a minimal dimension needed by + our tests. + """ + + if OUR_SCREEN_SIZE is None: + def _check_screen_size(): + global OUR_SCREEN_SIZE + OUR_SCREEN_SIZE = nyx.curses.screen_size() + + nyx.curses.start(_check_screen_size) + + def wrapped(self, *args, **kwargs): + if OUR_SCREEN_SIZE.width < TEST_SCREEN_SIZE.width: + self.skipTest("screen isn't wide enough") + elif OUR_SCREEN_SIZE.height < TEST_SCREEN_SIZE.height: + self.skipTest("screen isn't tall enough") + else: + with patch('nyx.curses.screen_size', Mock(return_value = TEST_SCREEN_SIZE)): + return func(self, *args, **kwargs) + + return wrapped + + def render(func, *args, **kwargs): """ Runs the given curses function, providing content that's rendered on the diff --git a/test/popups.py b/test/popups.py index 0394003..f38cb45 100644 --- a/test/popups.py +++ b/test/popups.py @@ -5,10 +5,12 @@ Unit tests for nyx.popups. import curses import unittest
+import nyx.curses import nyx.panel import nyx.popups import test
+from test import require_curses from mock import patch, Mock
EXPECTED_HELP_POPUP = """ @@ -187,15 +189,13 @@ Consensus Descriptor (29787760145CD1A473552A2FC64C72A9A130820E):---------------+ | 20 -----BEGIN SIGNATURE----- | | 21 EUFm38gONCoDuY7ZWHyJtBKuvk6Xi1MPuKuecS5frP3fX0wiZSrOVcpX0X8J+4Hr | | 22 Fb5i+yuMIAXeEn6UhtjqhhZBbY9PW9GdZOMTH8hJpG+evURyr+10PZq6UElg86rA | -| 23 NCGI042p6+7UgCVT1x3WcLnq3ScV//s1wXHrUXa7vi0= | -| 24 -----END SIGNATURE----- | +------------------------------------------------------------------------------+ """.strip()
class TestPopups(unittest.TestCase): + @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) @patch('nyx.controller.get_controller') def test_help(self, get_controller_mock): header_panel = Mock() @@ -230,20 +230,20 @@ class TestPopups(unittest.TestCase): rendered = test.render(nyx.popups.show_help) self.assertEqual(EXPECTED_HELP_POPUP, rendered.content)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) def test_about(self): rendered = test.render(nyx.popups.show_about) self.assertEqual(EXPECTED_ABOUT_POPUP, rendered.content)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) def test_counts_when_empty(self): rendered = test.render(nyx.popups.show_counts, 'Client Locales', {}) self.assertEqual(EXPECTED_EMPTY_COUNTS, rendered.content)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) def test_counts(self): clients = { 'fr': 5, @@ -256,16 +256,16 @@ class TestPopups(unittest.TestCase): rendered = test.render(nyx.popups.show_counts, 'Client Locales', clients, fill_char = '*') self.assertEqual(EXPECTED_COUNTS, rendered.content)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) def test_select_from_list(self): options = ['each second', '5 seconds', '30 seconds', 'minutely', '15 minute', '30 minute', 'hourly', 'daily'] rendered = test.render(nyx.popups.select_from_list, 'Update Interval:', options, 'each second') self.assertEqual(EXPECTED_LIST_SELECTOR, rendered.content) self.assertEqual('each second', rendered.return_value)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) def test_select_sort_order(self): previous_order = ['Man Page Entry', 'Name', 'Is Set'] options = ['Name', 'Value', 'Value Type', 'Category', 'Usage', 'Summary', 'Description', 'Man Page Entry', 'Is Set'] @@ -274,8 +274,8 @@ class TestPopups(unittest.TestCase): self.assertEqual(EXPECTED_SORT_DIALOG_START, rendered.content) self.assertEqual(None, rendered.return_value)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) def test_select_sort_order_usage(self): # Use the dialog to make a selection. At the end we render two options as # being selected (rather than three) because the act of selecing the third @@ -299,24 +299,24 @@ class TestPopups(unittest.TestCase): self.assertEqual(EXPECTED_SORT_DIALOG_END, rendered.content) self.assertEqual(['Name', 'Summary', 'Description'], rendered.return_value)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) @patch('nyx.controller.input_prompt', Mock(return_value = None)) def test_select_event_types_when_canceled(self): rendered = test.render(nyx.popups.select_event_types) self.assertEqual(EXPECTED_EVENT_SELECTOR, rendered.content) self.assertEqual(None, rendered.return_value)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) @patch('nyx.controller.input_prompt', Mock(return_value = '2bwe')) def test_select_event_types_with_input(self): rendered = test.render(nyx.popups.select_event_types) self.assertEqual(EXPECTED_EVENT_SELECTOR, rendered.content) self.assertEqual(set(['NYX_INFO', 'ERR', 'WARN', 'BW', 'NYX_ERR', 'NYX_WARN', 'NYX_NOTICE']), rendered.return_value)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) def test_confirm_save_torrc(self): rendered = test.render(nyx.popups.confirm_save_torrc, TORRC) self.assertEqual(EXPECTED_SAVE_TORRC_CONFIRMATION, rendered.content) @@ -330,15 +330,15 @@ class TestPopups(unittest.TestCase): self.assertEqual(EXPECTED_SAVE_TORRC_CONFIRMATION, rendered.content) self.assertEqual(True, rendered.return_value)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) def test_descriptor_without_fingerprint(self): rendered = test.render(nyx.popups.show_descriptor, None, nyx.curses.Color.RED, lambda key: key.match('esc')) self.assertEqual(EXPECTED_DESCRIPTOR_WITHOUT_FINGERPRINT, rendered.content) self.assertEqual(nyx.curses.KeyInput(27), rendered.return_value)
+ @require_curses @patch('nyx.popups._top', Mock(return_value = 0)) - @patch('nyx.curses.screen_size', Mock(return_value = nyx.curses.Dimensions(80, 60))) @patch('nyx.popups._descriptor_text', Mock(return_value = DESCRIPTOR_TEXT)) def test_descriptor(self): rendered = test.render(nyx.popups.show_descriptor, '29787760145CD1A473552A2FC64C72A9A130820E', nyx.curses.Color.RED, lambda key: key.match('esc'))
tor-commits@lists.torproject.org