From 178c417fb082aaced39b3fda3bae2e1eb475e041 Mon Sep 17 00:00:00 2001 From: bendikro Date: Mon, 13 Oct 2014 16:38:51 +0200 Subject: [PATCH] [Core] [Tests] Changes to component.shutdown and unit tests * component registry shutdown() now cleans up the component list this ensures that no old components are left when running unit tests. * Added class BaseTestCase that all tests that create components should inherit from. It verifies the compoent list before and after the tests are run. --- deluge/component.py | 7 +++++- deluge/tests/basetest.py | 37 ++++++++++++++++++++++++++++++ deluge/tests/test_component.py | 10 ++++---- deluge/tests/test_core.py | 5 ++-- deluge/tests/test_rpcserver.py | 11 ++++----- deluge/tests/test_sessionproxy.py | 10 ++++---- deluge/tests/test_torrentview.py | 14 ++++++----- deluge/tests/test_tracker_icons.py | 29 ++++++++++++----------- tox.ini | 16 ++++++++++++- 9 files changed, 100 insertions(+), 39 deletions(-) create mode 100644 deluge/tests/basetest.py diff --git a/deluge/component.py b/deluge/component.py index 4ae985ac9..904c8462c 100644 --- a/deluge/component.py +++ b/deluge/component.py @@ -385,8 +385,13 @@ class ComponentRegistry(object): :rtype: twisted.internet.defer.Deferred """ + def on_success(result, key): + del _ComponentRegistry.components[key] + return succeed(result) + def on_stopped(result): - return DeferredList(map(lambda c: c._component_shutdown(), self.components.values())) + return DeferredList(map(lambda t: t[1]._component_shutdown().addCallback(on_success, t[0]), + self.components.items())) return self.stop(self.components.keys()).addCallback(on_stopped) diff --git a/deluge/tests/basetest.py b/deluge/tests/basetest.py new file mode 100644 index 000000000..952c58661 --- /dev/null +++ b/deluge/tests/basetest.py @@ -0,0 +1,37 @@ +import warnings + +from twisted.internet.defer import maybeDeferred +from twisted.trial import unittest + +import deluge.component as component + + +class BaseTestCase(unittest.TestCase): + """This is the base class that should be used for all test classes + that create classes that inherit from deluge.component.Component. It + ensures that the component registry has been cleaned up when tests + have finished. + + """ + def setUp(self): # NOQA + + if len(component._ComponentRegistry.components) != 0: + warnings.warn("The component._ComponentRegistry.components is not empty on test setup." + "This is probably caused by another test that didn't clean up after finishing!: %s" % + component._ComponentRegistry.components) + return self.set_up() + + def tearDown(self): # NOQA + d = maybeDeferred(self.tear_down) + + def on_teared_down(result): + if len(component._ComponentRegistry.components) != 0: + warnings.warn("The component._ComponentRegistry.components is not empty after the test finished!: %s" % + component._ComponentRegistry.components) + return d.addCallback(on_teared_down) + + def set_up(self): + pass + + def tear_down(self): + pass diff --git a/deluge/tests/test_component.py b/deluge/tests/test_component.py index 671126e20..bdfd0a0e0 100644 --- a/deluge/tests/test_component.py +++ b/deluge/tests/test_component.py @@ -1,8 +1,9 @@ from twisted.internet import threads -from twisted.trial import unittest import deluge.component as component +from .basetest import BaseTestCase + class TestComponent(component.Component): def __init__(self, name, depend=None): @@ -56,10 +57,9 @@ class TestComponentShutdown(component.Component): self.stop_count += 1 -class ComponentTestClass(unittest.TestCase): - def tearDown(self): # NOQA - component.stop() - component._ComponentRegistry.components = {} +class ComponentTestClass(BaseTestCase): + def tear_down(self): + return component.shutdown() def test_start_component(self): def on_start(result, c): diff --git a/deluge/tests/test_core.py b/deluge/tests/test_core.py index 2c22febf4..16ccabddf 100644 --- a/deluge/tests/test_core.py +++ b/deluge/tests/test_core.py @@ -5,7 +5,6 @@ from hashlib import sha1 as sha from twisted.internet import reactor from twisted.internet.error import CannotListenError from twisted.python.failure import Failure -from twisted.trial import unittest from twisted.web.http import FORBIDDEN from twisted.web.resource import Resource from twisted.web.server import Site @@ -18,6 +17,7 @@ from deluge.core.rpcserver import RPCServer from deluge.ui.web.common import compress from . import common +from .basetest import BaseTestCase warnings.filterwarnings("ignore", category=RuntimeWarning) warnings.resetwarnings() @@ -67,7 +67,7 @@ class TopLevelResource(Resource): File(common.rpath("ubuntu-9.04-desktop-i386.iso.torrent"))) -class CoreTestCase(unittest.TestCase): +class CoreTestCase(BaseTestCase): def setUp(self): # NOQA common.set_tmp_config_dir() self.rpcserver = RPCServer(listen=False) @@ -96,7 +96,6 @@ class CoreTestCase(unittest.TestCase): def tearDown(self): # NOQA def on_shutdown(result): - component._ComponentRegistry.components = {} del self.rpcserver del self.core return self.webserver.stopListening() diff --git a/deluge/tests/test_rpcserver.py b/deluge/tests/test_rpcserver.py index e57ddda3b..0e5cfaa5a 100644 --- a/deluge/tests/test_rpcserver.py +++ b/deluge/tests/test_rpcserver.py @@ -7,8 +7,6 @@ # See LICENSE for more details. # -from twisted.trial import unittest - import deluge.component as component import deluge.error from deluge.core import rpcserver @@ -17,6 +15,8 @@ from deluge.core.rpcserver import DelugeRPCProtocol, RPCServer from deluge.log import setup_logger from deluge.ui.common import get_localhost_auth +from .basetest import BaseTestCase + setup_logger("none") @@ -28,9 +28,9 @@ class DelugeRPCProtocolTester(DelugeRPCProtocol): self.messages.append(data) -class RPCServerTestCase(unittest.TestCase): +class RPCServerTestCase(BaseTestCase): - def setUp(self): # NOQA + def set_up(self): self.rpcserver = RPCServer(listen=False) self.rpcserver.factory.protocol = DelugeRPCProtocolTester self.factory = self.rpcserver.factory @@ -45,9 +45,8 @@ class RPCServerTestCase(unittest.TestCase): self.protocol.sessionno = self.session_id return component.start() - def tearDown(self): # NOQA + def tear_down(self): def on_shutdown(result): - component._ComponentRegistry.components = {} del self.rpcserver return component.shutdown().addCallback(on_shutdown) diff --git a/deluge/tests/test_sessionproxy.py b/deluge/tests/test_sessionproxy.py index 2cb0ffec1..3937060a3 100644 --- a/deluge/tests/test_sessionproxy.py +++ b/deluge/tests/test_sessionproxy.py @@ -1,11 +1,12 @@ import time from twisted.internet.defer import maybeDeferred, succeed -from twisted.trial import unittest import deluge.component as component import deluge.ui.sessionproxy +from .basetest import BaseTestCase + class Core(object): def __init__(self): @@ -89,8 +90,9 @@ client = Client() deluge.ui.sessionproxy.client = client -class SessionProxyTestCase(unittest.TestCase): - def setUp(self): # NOQA +class SessionProxyTestCase(BaseTestCase): + + def set_up(self): self.sp = deluge.ui.sessionproxy.SessionProxy() client.core.reset() d = self.sp.start() @@ -101,7 +103,7 @@ class SessionProxyTestCase(unittest.TestCase): d.addCallback(do_get_torrents_status) return d - def tearDown(self): # NOQA + def tear_down(self): return component.deregister(self.sp) def test_startup(self): diff --git a/deluge/tests/test_torrentview.py b/deluge/tests/test_torrentview.py index 72cf6d43f..36f8e359c 100644 --- a/deluge/tests/test_torrentview.py +++ b/deluge/tests/test_torrentview.py @@ -1,3 +1,4 @@ +import pytest import gobject from twisted.trial import unittest @@ -8,10 +9,13 @@ from deluge.ui.gtkui.menubar import MenuBar from deluge.ui.gtkui.torrentdetails import TorrentDetails from deluge.ui.gtkui.torrentview import TorrentView +from .basetest import BaseTestCase + deluge.common.setup_translations() -class TorrentviewTestCase(unittest.TestCase): +@pytest.mark.gtkui +class TorrentviewTestCase(BaseTestCase): default_column_index = ['filter', 'torrent_id', 'dirty', '#', u'Name', u'Size', u'Downloaded', u'Uploaded', u'Remaining', u'Progress', @@ -25,16 +29,14 @@ class TorrentviewTestCase(unittest.TestCase): float, float, int, float, float, float, float, float, str, str, str, str, bool] - def setUp(self): # NOQA + def set_up(self): self.mainwindow = MainWindow() self.torrentview = TorrentView() self.torrentdetails = TorrentDetails() self.menubar = MenuBar() - def tearDown(self): # NOQA - def on_shutdown(result): - component._ComponentRegistry.components = {} - return component.shutdown().addCallback(on_shutdown) + def tear_down(self): + return component.shutdown() def test_torrentview_columns(self): diff --git a/deluge/tests/test_tracker_icons.py b/deluge/tests/test_tracker_icons.py index bed268bf3..40b4fa025 100644 --- a/deluge/tests/test_tracker_icons.py +++ b/deluge/tests/test_tracker_icons.py @@ -1,26 +1,29 @@ import os -from twisted.trial import unittest - +import deluge.component as component import deluge.ui.tracker_icons from deluge.ui.tracker_icons import TrackerIcon, TrackerIcons +from .basetest import BaseTestCase from .common import set_tmp_config_dir set_tmp_config_dir() -icons = TrackerIcons() - dirname = os.path.dirname(__file__) - deluge.ui.tracker_icons.PIL_INSTALLED = False -class TrackerIconsTestCase(unittest.TestCase): +class TrackerIconsTestCase(BaseTestCase): + + def set_up(self): + self.icons = TrackerIcons() + + def tear_down(self): + return component.shutdown() def test_get_deluge_png(self): # Deluge has a png favicon link icon = TrackerIcon(os.path.join(dirname, "deluge.png")) - d = icons.fetch("deluge-torrent.org") + d = self.icons.fetch("deluge-torrent.org") d.addCallback(self.assertNotIdentical, None) d.addCallback(self.assertEquals, icon) return d @@ -29,7 +32,7 @@ class TrackerIconsTestCase(unittest.TestCase): # Google doesn't have any icon links # So instead we'll grab its favicon.ico icon = TrackerIcon(os.path.join(dirname, "google.ico")) - d = icons.fetch("www.google.com") + d = self.icons.fetch("www.google.com") d.addCallback(self.assertNotIdentical, None) d.addCallback(self.assertEquals, icon) return d @@ -37,7 +40,7 @@ class TrackerIconsTestCase(unittest.TestCase): def test_get_google_ico_with_redirect(self): # google.com redirects to www.google.com icon = TrackerIcon(os.path.join(dirname, "google.ico")) - d = icons.fetch("google.com") + d = self.icons.fetch("google.com") d.addCallback(self.assertNotIdentical, None) d.addCallback(self.assertEquals, icon) return d @@ -45,7 +48,7 @@ class TrackerIconsTestCase(unittest.TestCase): def test_get_ubuntu_ico(self): # ubuntu.com has inline css which causes HTMLParser issues icon = TrackerIcon(os.path.join(dirname, "ubuntu.ico")) - d = icons.fetch("www.ubuntu.com") + d = self.icons.fetch("www.ubuntu.com") d.addCallback(self.assertNotIdentical, None) d.addCallback(self.assertEquals, icon) return d @@ -53,19 +56,19 @@ class TrackerIconsTestCase(unittest.TestCase): def test_get_openbt_png(self): # openbittorrent.com has an incorrect type (image/gif) icon = TrackerIcon(os.path.join(dirname, "openbt.png")) - d = icons.fetch("openbittorrent.com") + d = self.icons.fetch("openbittorrent.com") d.addCallback(self.assertNotIdentical, None) d.addCallback(self.assertEquals, icon) return d def test_get_publicbt_ico(self): icon = TrackerIcon(os.path.join(dirname, "publicbt.ico")) - d = icons.fetch("publicbt.org") + d = self.icons.fetch("publicbt.org") d.addCallback(self.assertNotIdentical, None) d.addCallback(self.assertEquals, icon) return d def test_get_empty_string_tracker(self): - d = icons.fetch("") + d = self.icons.fetch("") d.addCallback(self.assertIdentical, None) return d diff --git a/tox.ini b/tox.ini index e0f90e3fb..17a0cb807 100644 --- a/tox.ini +++ b/tox.ini @@ -52,7 +52,21 @@ commands = [testenv:pydef] commands = python -c "import libtorrent as lt; print lt.version" - py.test deluge/tests + py.test -v -s -m "not (todo or gtkui)" deluge/tests + +[testenv:pygtkui] +commands = + py.test -v -s -m "gtkui" deluge/tests + +[testenv:todo] +commands = + py.test -v -s -m "todo" deluge/tests + +[testenv:trial] +setenv = {[testenv]setenv}:{env:PWD}/deluge/tests +whitelist_externals = trial +commands = + trial --reporter=deluge-reporter deluge/tests [testenv:plugins] commands = py.test deluge/plugins