From 1ee401678e5abc41adaab31cb34198b68bcc7b99 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Wed, 19 Jan 2011 14:53:03 -0800 Subject: [PATCH] a real system for mocking IO for UI functions --- test/_common.py | 46 +++++++++++++++++++++++++++++++++++++++++++ test/test_albumify.py | 11 +++++++---- test/test_ui.py | 42 +++++++++++++-------------------------- 3 files changed, 67 insertions(+), 32 deletions(-) diff --git a/test/_common.py b/test/_common.py index 925a4db7a..ad4963ac2 100644 --- a/test/_common.py +++ b/test/_common.py @@ -1,5 +1,6 @@ """Some common functionality for beets' test cases.""" import time +import sys class Timecop(object): """Mocks the timing system (namely time() and sleep()) for testing. @@ -25,3 +26,48 @@ class Timecop(object): def restore(self): time.time = self.orig['time'] time.sleep = self.orig['sleep'] + +class DummyOut(object): + encoding = 'utf8' + def __init__(self): + self.buf = [] + def write(self, s): + self.buf.append(s) + def get(self): + return ''.join(self.buf) + def clear(self): + self.buf = [] +class DummyIn(object): + encoding = 'utf8' + def __init__(self): + self.buf = [] + self.reads = 0 + def add(self, s): + self.buf.append(s + '\n') + def readline(self): + self.reads += 1 + return self.buf.pop(0) +class DummyIO(object): + """Mocks input and output streams for testing UI code.""" + def __init__(self): + self.stdin = DummyIn() + self.stdout = DummyOut() + + def addinput(self, s): + self.stdin.add(s) + + def getoutput(self): + res = self.stdout.get() + self.stdout.clear() + return res + + def readcount(self): + return self.stdin.reads + + def install(self): + sys.stdin = self.stdin + sys.stdout = self.stdout + + def restore(self): + sys.stdin = sys.__stdin__ + sys.stdout = sys.__stdout__ diff --git a/test/test_albumify.py b/test/test_albumify.py index e2f7a6307..e34e724a1 100644 --- a/test/test_albumify.py +++ b/test/test_albumify.py @@ -19,16 +19,16 @@ import sys sys.path.append('..') from beets import library -from beets import ui from beetsplug.albumify import albumify +import _common from test_db import item -# Silence UI output. -ui.print_ = lambda s: None - class AlbumifyTest(unittest.TestCase): def setUp(self): + self.io = _common.DummyIO() + self.io.install() + self.lib = library.Library(':memory:') i1, i2, i3 = item(), item(), item() i1.album = 'album1' @@ -38,6 +38,9 @@ class AlbumifyTest(unittest.TestCase): self.lib.add(i2) self.lib.add(i3) + def tearDown(self): + self.io.restore() + def test_albumify_creates_albums(self): albumify(self.lib) albums = [a.album for a in self.lib.albums()] diff --git a/test/test_ui.py b/test/test_ui.py index 0ddecfa65..7bd86f4ee 100644 --- a/test/test_ui.py +++ b/test/test_ui.py @@ -18,56 +18,41 @@ import unittest import sys import os +import _common sys.path.append('..') from beets import library from beets import ui from beets.ui import commands import test_db -# Dummy printing so we can get the commands' output. -outbuffer = [] -def buffer_append(*txt): - outbuffer.extend(txt) -def get_output(): - return u' '.join(outbuffer) -def clear_buffer(): - outbuffer[:] - class ListTest(unittest.TestCase): def setUp(self): - self.old_print = ui.print_ - ui.print_ = buffer_append - commands.print_ = buffer_append + self.io = _common.DummyIO() + self.io.install() - clear_buffer() self.lib = library.Library(':memory:') i = test_db.item() self.lib.add(i) def tearDown(self): - ui.print_ = self.old_print - commands.print_ = self.old_print + self.io.restore() def test_list_outputs_item(self): commands.list_items(self.lib, '', False) - out = get_output() + out = self.io.getoutput() self.assertTrue(u'the title' in out) def test_list_album_omits_title(self): commands.list_items(self.lib, '', True) - out = get_output() + out = self.io.getoutput() self.assertTrue(u'the title' not in out) class PrintTest(unittest.TestCase): def setUp(self): - class Devnull(object): - def write(self, d): - pass - self.stdout = sys.stdout - sys.stdout = Devnull() - + self.io = _common.DummyIO() + self.io.install() def tearDown(self): - sys.stdout = self.stdout + self.io.restore() def test_print_without_locale(self): lang = os.environ.get('LANG') @@ -104,13 +89,14 @@ class PrintTest(unittest.TestCase): class InputTest(unittest.TestCase): def setUp(self): - def my_input(prompt=None): - return '\xc3\x82me' - commands.raw_input = my_input + self.io = _common.DummyIO() + self.io.install() def tearDown(self): - commands.raw_input = raw_input + self.io.restore() def test_manual_search_gets_unicode(self): + self.io.addinput('\xc3\x82me') + self.io.addinput('\xc3\x82me') artist, album = commands.manual_search() self.assertEqual(artist, u'\xc2me') self.assertEqual(album, u'\xc2me')