[tor-commits] [nyx/master] Unit test rendering about popup

atagar at torproject.org atagar at torproject.org
Sat Apr 2 22:43:22 UTC 2016


commit e9576a7a9812d63abfaf03227a8c6074271296ca
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Apr 2 15:39:31 2016 -0700

    Unit test rendering about popup
    
    Hell yeah, we can unit test curses! Just a proof of concept for our simplest
    draw function but this can be applied to anything, opening a brave new world of
    testability!
    
    /me does a little happy dance
---
 nyx/curses.py    | 16 ++++++++++++++++
 nyx/popups.py    |  4 ++--
 test/__init__.py | 38 ++++++++++++++++++++++++++++++++++++++
 test/popups.py   | 31 +++++++++++++++++++++++++++++++
 4 files changed, 87 insertions(+), 2 deletions(-)

diff --git a/nyx/curses.py b/nyx/curses.py
index 909a055..6d3b170 100644
--- a/nyx/curses.py
+++ b/nyx/curses.py
@@ -15,6 +15,7 @@ if we want Windows support in the future too.
   raw_screen - provides direct access to the curses screen
   key_input - get keypress by user
   curses_attr - curses encoded text attribute
+  screenshot - dump of the present on-screen content
 
   is_color_supported - checks if terminal supports color output
   get_color_override - provides color we override requests with
@@ -250,6 +251,21 @@ def curses_attr(*attributes):
   return encoded
 
 
+def screenshot():
+  """
+  Provides a dump of the present content of the screen.
+
+  :returns: **str** with the present content shown on the screen
+  """
+
+  lines = []
+
+  for y in range(CURSES_SCREEN.getmaxyx()[0]):
+    lines.append(CURSES_SCREEN.instr(y, 0).rstrip())
+
+  return '\n'.join(lines).rstrip()
+
+
 def is_color_supported():
   """
   Checks if curses currently supports rendering colors.
diff --git a/nyx/popups.py b/nyx/popups.py
index c56cb25..e65be70 100644
--- a/nyx/popups.py
+++ b/nyx/popups.py
@@ -147,7 +147,7 @@ def show_about():
 
   with nyx.curses.CURSES_LOCK:
     nyx.curses.draw(_render, top = nyx.controller.get_controller().header_panel().get_height(), width = 80, height = 9)
-    keypress = nyx.curses.key_input()
+    nyx.curses.key_input()
 
 
 def show_counts(title, counts):
@@ -195,7 +195,7 @@ def show_counts(title, counts):
     else:
       nyx.curses.draw(_render_stats, top = top, width = 80, height = 4 + max(1, len(counts)))
 
-    keypress = nyx.curses.key_input()
+    nyx.curses.key_input()
 
 
 def show_sort_dialog(title, options, old_selection, option_colors):
diff --git a/test/__init__.py b/test/__init__.py
index e64593c..44a53b0 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -2,8 +2,12 @@
 Unit tests for nyx.
 """
 
+import collections
+import time
 import unittest
 
+import nyx.curses
+
 from nyx import expand_path, join, uses_settings
 
 from mock import patch, Mock
@@ -16,6 +20,40 @@ __all__ = [
   'tracker',
 ]
 
+# If set we make test content we render for this many seconds.
+
+SHOW_RENDERED_CONTENT = None
+
+RenderResult = collections.namedtuple('RenderResult', ['content', 'return_value', 'runtime'])
+
+
+def render(func):
+  """
+  Runs the given curses function, providing content that's rendered on the
+  screen.
+
+  :param function func: draw function to be invoked
+
+  :returns: :data:`~test.RenderResult` with information about what was rendered
+  """
+
+  attr = {}
+
+  def draw_func():
+    nyx.curses.disable_acs()
+    start_time = time.time()
+    attr['return_value'] = func()
+    attr['runtime'] = time.time() - start_time
+    attr['content'] = nyx.curses.screenshot()
+
+    if SHOW_RENDERED_CONTENT:
+      time.sleep(SHOW_RENDERED_CONTENT)
+
+  with patch('nyx.curses.key_input', return_value = Mock()):
+    nyx.curses.start(draw_func, transparent_background = True, cursor = False)
+
+  return RenderResult(attr.get('content'), attr.get('return_value'), attr.get('runtime'))
+
 
 class TestBaseUtil(unittest.TestCase):
   @patch('nyx.tor_controller')
diff --git a/test/popups.py b/test/popups.py
new file mode 100644
index 0000000..c4f56ea
--- /dev/null
+++ b/test/popups.py
@@ -0,0 +1,31 @@
+"""
+Unit tests for nyx.popups.
+"""
+
+import unittest
+
+import nyx.popups
+import test
+
+from mock import patch
+
+EXPECTED_ABOUT_POPUP = """
+About:-------------------------------------------------------------------------+
+| Nyx, version 1.4.6-dev (released April 28, 2011)                             |
+|   Written by Damian Johnson (atagar at torproject.org)                          |
+|   Project page: http://www.atagar.com/arm/                                   |
+|                                                                              |
+| Released under the GPL v3 (http://www.gnu.org/licenses/gpl.html)             |
+|                                                                              |
+| Press any key...                                                             |
++------------------------------------------------------------------------------+
+""".strip()
+
+
+class TestPopups(unittest.TestCase):
+  @patch('nyx.controller.get_controller')
+  def test_about(self, get_controller_mock):
+    get_controller_mock().header_panel().get_height.return_value = 0
+
+    rendered = test.render(nyx.popups.show_about)
+    self.assertEqual(EXPECTED_ABOUT_POPUP, rendered.content)



More information about the tor-commits mailing list