From 39fa7788b46d6064b3b018d99fd363a530f7d6b4 Mon Sep 17 00:00:00 2001 From: Tobias Witek Date: Sat, 20 Jun 2020 14:53:44 +0200 Subject: [PATCH] [tests] switch to pytest --- .travis.yml | 4 +- coverage.sh | 2 +- pytests/__init__.py | 4 - pytests/core/test_config.py | 102 ------ pytests/core/test_decorators.py | 103 ------ pytests/core/test_event.py | 73 ----- pytests/core/test_input.py | 104 ------ pytests/core/test_module.py | 177 ---------- pytests/core/test_output.py | 173 ---------- pytests/core/test_theme.py | 175 ---------- pytests/core/test_widget.py | 97 ------ pytests/modules/__init__.py | 0 pytests/modules/contrib/__init__.py | 0 pytests/util/test_algorithm.py | 50 --- pytests/util/test_cli.py | 27 -- pytests/util/test_format.py | 113 ------- pytests/util/test_location.py | 57 ---- pytests/util/test_store.py | 48 --- tests/__init__.py | 1 + tests/core/test_config.py | 147 +++++---- tests/core/test_decorators.py | 158 ++++----- tests/core/test_event.py | 99 +++--- tests/core/test_input.py | 166 +++++----- tests/core/test_module.py | 304 +++++++++--------- tests/core/test_output.py | 261 ++++++++------- tests/core/test_theme.py | 246 +++++++------- tests/core/test_widget.py | 120 +++---- .../modules/contrib}/__init__.py | 0 .../modules/contrib/test_kernel.py | 0 .../modules/contrib/test_mpd.py | 0 tests/modules/test_kernel.py | 21 -- tests/util/__init__.py | 0 tests/util/test_algorithm.py | 64 ++-- tests/util/test_cli.py | 48 +-- tests/util/test_format.py | 164 +++++----- tests/util/test_location.py | 84 ++--- tests/util/test_store.py | 76 ++--- 37 files changed, 1009 insertions(+), 2259 deletions(-) delete mode 100644 pytests/__init__.py delete mode 100644 pytests/core/test_config.py delete mode 100644 pytests/core/test_decorators.py delete mode 100644 pytests/core/test_event.py delete mode 100644 pytests/core/test_input.py delete mode 100644 pytests/core/test_module.py delete mode 100644 pytests/core/test_output.py delete mode 100644 pytests/core/test_theme.py delete mode 100644 pytests/core/test_widget.py delete mode 100644 pytests/modules/__init__.py delete mode 100644 pytests/modules/contrib/__init__.py delete mode 100644 pytests/util/test_algorithm.py delete mode 100644 pytests/util/test_cli.py delete mode 100644 pytests/util/test_format.py delete mode 100644 pytests/util/test_location.py delete mode 100644 pytests/util/test_store.py rename {pytests/core => tests/modules/contrib}/__init__.py (100%) rename {pytests => tests}/modules/contrib/test_kernel.py (100%) rename {pytests => tests}/modules/contrib/test_mpd.py (100%) delete mode 100644 tests/modules/test_kernel.py delete mode 100644 tests/util/__init__.py diff --git a/.travis.yml b/.travis.yml index 63b6eb7..1586938 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,10 +8,10 @@ python: before_install: - sudo apt-get -qq update install: - - pip install -U coverage==4.3 + - pip install -U coverage==4.3 pytest - pip install codeclimate-test-reporter script: - - coverage run --source=. -m unittest discover -v + - coverage run --source=. -m pytest tests -v - CODECLIMATE_REPO_TOKEN=40cb00907f7a10e04868e856570bb997ab9c42fd3b63d980f2b2269433195fdf codeclimate-test-reporter addons: code_climate: diff --git a/coverage.sh b/coverage.sh index 7910a98..73911b4 100755 --- a/coverage.sh +++ b/coverage.sh @@ -1,4 +1,4 @@ #!/bin/bash -coverage run --source=. -m unittest discover -v -b +coverage run --source=. -m pytest tests -v coverage report -m diff --git a/pytests/__init__.py b/pytests/__init__.py deleted file mode 100644 index afddb20..0000000 --- a/pytests/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -import bumblebee_status.discover - -bumblebee_status.discover.discover() - diff --git a/pytests/core/test_config.py b/pytests/core/test_config.py deleted file mode 100644 index 774b806..0000000 --- a/pytests/core/test_config.py +++ /dev/null @@ -1,102 +0,0 @@ -import os -import pytest - -import core.config - -@pytest.fixture -def defaultConfig(): - return core.config.Config([]) - -def test_module(): - modules = ["module-1", "module-2", "module-3"] - - cfg = core.config.Config(["-m"] + modules) - - assert cfg.modules() == modules - -def test_module_ordering_maintained(): - modules = ["module-1", "module-5", "module-7"] - more_modules = ["module-0", "module-2", "aaa"] - - cfg = core.config.Config(["-m"] + modules + ["-m"] + more_modules) - - assert cfg.modules() == modules + more_modules - -def test_default_interval(defaultConfig): - assert defaultConfig.interval() == 1 - -def test_interval(): - interval = 4 - cfg = core.config.Config(["-p", "interval={}".format(interval)]) - - assert cfg.interval() == interval - -def test_floating_interval(): - interval = 4.5 - cfg = core.config.Config(["-p", "interval={}".format(interval)]) - - assert cfg.interval() == interval - -def test_default_theme(defaultConfig): - assert defaultConfig.theme() == "default" - -def test_theme(): - theme_name = "sample-theme" - cfg = core.config.Config(["-t", theme_name]) - assert cfg.theme() == theme_name - -def test_default_iconset(defaultConfig): - assert defaultConfig.iconset() == "auto" - -def test_iconset(): - iconset_name = "random-iconset" - cfg = core.config.Config(["-i", iconset_name]) - assert cfg.iconset() == iconset_name - -def test_reverse(defaultConfig): - assert defaultConfig.reverse() == False - - cfg = core.config.Config(["-r"]) - - assert cfg.reverse() == True - -def test_logfile(defaultConfig): - assert defaultConfig.logfile() is None - - logfile = "some-random-logfile" - cfg = core.config.Config(["-f", logfile]) - assert cfg.logfile() == logfile - - - -def test_all_modules(): - modules = core.config.all_modules() - assert len(modules) > 0 - - for module in modules: - pyname = "{}.py".format(module) - base = os.path.abspath( - os.path.join( - os.path.dirname(os.path.realpath(__file__)), - "..", - "..", - "bumblebee_status", - "modules", - ) - ) - assert os.path.exists(os.path.join(base, "contrib", pyname)) \ - or os.path.exists(os.path.join(base, "core", pyname)) - -def test_list_output(mocker): - mocker.patch("core.config.sys") - cfg = core.config.Config(["-l", "themes"]) - cfg = core.config.Config(["-l", "modules"]) - cfg = core.config.Config(["-l", "modules-rst"]) - -def test_missing_parameter(): - cfg = core.config.Config(["-p", "test.key"]) - - assert cfg.get("test.key") == None - assert cfg.get("test.key", "no-value-set") == "no-value-set" -# -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/core/test_decorators.py b/pytests/core/test_decorators.py deleted file mode 100644 index 25f8b9c..0000000 --- a/pytests/core/test_decorators.py +++ /dev/null @@ -1,103 +0,0 @@ -import pytest - -import core.decorators -import core.widget -import core.module -import core.config - -@pytest.fixture -def module(): - class TestModule(core.module.Module): - @core.decorators.never - def __init__(self, config=None, theme=None): - config = core.config.Config([]) - super().__init__(config, theme, core.widget.Widget(self.get)) - self.text = "" - - @core.decorators.scrollable - def get(self, widget): - return self.text - module = TestModule() - module.set("scrolling.width", 10) - return module - -def test_never(module): - assert module.parameter("interval") == "never" - -def test_no_text(module): - assert module.text == "" - assert module.get(module.widget()) == "" - -def test_smaller(module): - module.text = "test" - assert module.parameter("scrolling.width") > len(module.text) - assert module.get(module.widget()) == module.text - -def test_bigger(module): - module.text = "this is a really really long sample text" - maxwidth = module.parameter("scrolling.width") - assert maxwidth < len(module.text) - assert module.get(module.widget()) == module.text[:maxwidth] - -def test_bounce(module): - module.text = "abcd" - module.set("scrolling.width", 2) - assert module.get(module.widget()) == "ab" - assert module.get(module.widget()) == "bc" - assert module.get(module.widget()) == "cd" - assert module.get(module.widget()) == "bc" - assert module.get(module.widget()) == "ab" - assert module.get(module.widget()) == "bc" - assert module.get(module.widget()) == "cd" - assert module.get(module.widget()) == "bc" - assert module.get(module.widget()) == "ab" - -def test_nobounce(module): - module.set("scrolling.bounce", False) - module.set("scrolling.width", 2) - module.text = "abcd" - - assert module.get(module.widget()) == "ab" - assert module.get(module.widget()) == "bc" - assert module.get(module.widget()) == "cd" - assert module.get(module.widget()) == "ab" - assert module.get(module.widget()) == "bc" - assert module.get(module.widget()) == "cd" - -def test_completely_changed_data(module): - module.text = "abcd" - module.set("scrolling.width", 2) - - assert module.get(module.widget()) == "ab" - assert module.get(module.widget()) == "bc" - - module.text = "wxyz" - assert module.get(module.widget()) == "wx" - assert module.get(module.widget()) == "xy" - -def test_slightly_changed_data(module): - module.text = "this is a sample song (0:00)" - module.set("scrolling.width", 10) - - assert module.get(module.widget()) == module.text[0:10] - module.text = "this is a sample song (0:01)" - assert module.get(module.widget()) == module.text[1:11] - module.text = "this is a sample song (0:02)" - assert module.get(module.widget()) == module.text[2:12] - module.text = "this is a sample song (0:13)" - assert module.get(module.widget()) == module.text[3:13] - module.text = "this is a different song (0:13)" - assert module.get(module.widget()) == module.text[0:10] - -def test_n_plus_one(module): - module.text = "10 letters" - module.set("scrolling.width", 9) - - assert module.get(module.widget()) == module.text[0:9] - assert module.get(module.widget()) == module.text[1:10] - assert module.get(module.widget()) == module.text[0:9] - assert module.get(module.widget()) == module.text[1:10] - assert module.get(module.widget()) == module.text[0:9] - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/core/test_event.py b/pytests/core/test_event.py deleted file mode 100644 index b64478f..0000000 --- a/pytests/core/test_event.py +++ /dev/null @@ -1,73 +0,0 @@ -import pytest - -import core.event - -@pytest.fixture -def someEvent(): - class Event(): - def __init__(self): - core.event.clear() - self.id = "some event" - self.called = 0 - self.call_args = [] - self.call_kwargs = [] - - def callback(self, *args, **kwargs): - self.called += 1 - if args: - self.call_args.append(list(args)) - if kwargs: - self.call_kwargs.append(kwargs) - - return Event() - - -def test_simple_callback(someEvent): - assert someEvent.called == 0 - - core.event.register(someEvent.id, someEvent.callback) - core.event.register(someEvent.id, someEvent.callback) - - core.event.trigger(someEvent.id) - - assert someEvent.called == 2 - -def test_args_callback(someEvent): - core.event.register(someEvent.id, someEvent.callback, "a", "b") - core.event.trigger(someEvent.id) - - assert someEvent.called == 1 - assert len(someEvent.call_args) == 1 - assert someEvent.call_args[0] == ["a", "b"] - -def test_kwargs_callback(someEvent): - core.event.register( - someEvent.id, someEvent.callback, "a", "b", key1="test", key2="another" - ) - core.event.trigger(someEvent.id) - - assert someEvent.called == 1 - assert len(someEvent.call_args) == 1 - assert someEvent.call_args[0] == ["a", "b"] - assert len(someEvent.call_kwargs) == 1 - assert someEvent.call_kwargs[0] == { "key1": "test", "key2": "another" } - -def test_arg_trigger(someEvent): - core.event.register(someEvent.id, someEvent.callback) - core.event.trigger(someEvent.id, "a", "b") - - assert someEvent.called == 1 - assert len(someEvent.call_args) == 1 - assert someEvent.call_args[0] == ["a", "b"] - -def test_kwargs_trigger(someEvent): - core.event.register(someEvent.id, someEvent.callback) - core.event.trigger(someEvent.id, "a", "c", key1="test", key2="something") - - assert someEvent.called == 1 - assert len(someEvent.call_args) == 1 - assert someEvent.call_args[0] == ["a", "c"] - assert len(someEvent.call_kwargs) == 1 - assert someEvent.call_kwargs[0] == { "key1": "test", "key2": "something" } - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/core/test_input.py b/pytests/core/test_input.py deleted file mode 100644 index 962b5b2..0000000 --- a/pytests/core/test_input.py +++ /dev/null @@ -1,104 +0,0 @@ -import pytest - -import core.input - - -@pytest.fixture -def obj(): - return core.input.Object() - - -@pytest.fixture -def obj2(): - return core.input.Object() - - -@pytest.fixture -def cb(mocker): - return mocker.MagicMock() - - -@pytest.fixture -def cb2(mocker): - return mocker.MagicMock() - - -def event(input_object): - return {"button": core.input.LEFT_MOUSE, "instance": input_object.id} - - -def event2(input_object): - return {"button": core.input.RIGHT_MOUSE, "instance": input_object.id} - - -def test_callable_gets_called(obj, cb): - core.input.register(obj, event(obj)["button"], cb) - core.input.trigger(event(obj)) - - cb.assert_called_once_with(event(obj)) - - -def test_nonexistent_callback(obj, obj2, cb): - core.input.register(obj, event(obj)["button"], cb) - core.input.trigger(event(obj2)) - - cb.assert_not_called() - - -def test_different_events(obj, obj2, cb, cb2): - core.input.register(obj, event(obj)["button"], cb) - core.input.register(obj, event2(obj)["button"], cb) - core.input.register(obj2, event(obj)["button"], cb2) - core.input.register(obj2, event2(obj)["button"], cb2) - - core.input.trigger(event(obj)) - core.input.trigger(event2(obj)) - - cb.assert_any_call(event(obj)) - cb.assert_any_call(event2(obj)) - cb2.assert_not_called() - - -def test_multiple_registrations(obj, cb, cb2): - core.input.register(obj, event(obj)["button"], cb) - core.input.register(obj, event(obj)["button"], cb2) - - core.input.trigger(event(obj)) - - cb.assert_called_once_with(event(obj)) - cb2.assert_called_once_with(event(obj)) - - -def test_event_names(): - assert core.input.button_name(core.input.LEFT_MOUSE) == "left-mouse" - assert core.input.button_name(core.input.RIGHT_MOUSE) == "right-mouse" - assert core.input.button_name(core.input.MIDDLE_MOUSE) == "middle-mouse" - assert core.input.button_name(core.input.WHEEL_UP) == "wheel-up" - assert core.input.button_name(core.input.WHEEL_DOWN) == "wheel-down" - assert core.input.button_name(12345) == "n/a" - - -def test_non_callable_callback(mocker, obj): - cli = mocker.patch("core.input.util.cli") - cli.execute.return_value = "" - - core.input.register(obj, event(obj)["button"], "sample-command") - - core.input.trigger(event(obj)) - - cli.execute.assert_called_once_with("sample-command", wait=False, shell=True) - - -def test_non_existent_callback(mocker, obj): - cli = mocker.patch("core.input.util.cli") - cli.execute.return_value = "" - cli.execute.side_effect = RuntimeError("some-error") - - core.input.register(obj, event(obj)["button"], "sample-command") - - core.input.trigger(event(obj)) - - cli.execute.assert_called_once_with("sample-command", wait=False, shell=True) - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/core/test_module.py b/pytests/core/test_module.py deleted file mode 100644 index ef65c88..0000000 --- a/pytests/core/test_module.py +++ /dev/null @@ -1,177 +0,0 @@ -import pytest - -import sys -import shlex - -import core.module -import core.widget -import core.config -import core.input - - -@pytest.fixture(autouse=True) -def clear_events(): - core.event.clear() - - -@pytest.fixture -def empty_config(): - return core.config.Config([]) - - -@pytest.fixture -def widget_a(): - return core.widget.Widget("randomwWidget content", name="A") - - -@pytest.fixture -def widget_b(): - return core.widget.Widget("another randomwWidget content", name="B") - - -class SampleModule(core.module.Module): - def update(self): - if self.fail: - raise Exception(self.error) - pass - - -def test_loadinvalid_module(mocker): - config = mocker.MagicMock() - module = core.module.load(module_name="i-do-not-exist", config=config) - assert module.__class__.__module__ == "core.module" - assert module.__class__.__name__ == "Error" - - -@pytest.mark.skipif( - sys.version_info.major == 3 and sys.version_info.minor in [4, 5], - reason="importlib error reporting in Python 3.{4,5} different", -) -def test_importerror(mocker): - importlib = mocker.patch("core.module.importlib") - importlib.import_module.side_effect = ImportError("some-error") - config = mocker.MagicMock() - - module = core.module.load(module_name="test", config=config) - - assert module.__class__.__name__ == "Error" - assert module.widget().full_text() == "test: some-error" - - -def test_loadvalid_module(): - module = core.module.load(module_name="test") - assert module.__class__.__module__ == "modules.core.test" - assert module.__class__.__name__ == "Module" - assert module.state(None) == [] - - -def test_empty_widgets(): - module = core.module.Module(widgets=[]) - assert module.widgets() == [] - - -def test_error_widget(): - cfg = core.config.Config(shlex.split("-p test_module.foo=5")) - module = core.module.Error("test-mod", "xyz", config=cfg) - full_text = module.full_text(module.widget()) - - assert module.state(None) == ["critical"] - assert "test-mod" in full_text - assert "xyz" in full_text - - -def test_single_widget(widget_a): - module = core.module.Module(widgets=widget_a) - assert module.widgets() == [widget_a] - - -def test_widget_list(widget_a, widget_b): - module = core.module.Module(widgets=[widget_a, widget_b]) - assert module.widgets() == [widget_a, widget_b] - - -def test_module_Name(): - module = SampleModule() - assert module.name == "test_module" - assert module.module_name == "test_module" - - -def testvalid_parameter(): - cfg = core.config.Config(shlex.split("-p test_module.foo=5")) - module = SampleModule(config=cfg) - assert module.parameter("foo") == "5" - - -def test_default_parameter(empty_config): - module = SampleModule(config=empty_config) - assert module.parameter("foo", "default") == "default" - - -def test_default_is_none(empty_config): - module = SampleModule(config=empty_config) - assert module.parameter("foo") == None - - -def test_error_widget(empty_config): - module = SampleModule(config=empty_config) - module.fail = True - module.error = "!!" - module.update_wrapper() - assert len(module.widgets()) == 1 - assert module.widget().full_text() == "error: !!" - - -def test_get_widget_by_name(empty_config, widget_a, widget_b): - module = SampleModule(config=empty_config, widgets=[widget_a, widget_b]) - - assert module.widget(widget_a.name) == widget_a - assert module.widget(widget_b.name) == widget_b - assert module.widget("i-do-not-exist") == None - assert module.widget() == widget_a - - -def test_default_thresholds(empty_config, widget_a, widget_b): - module = SampleModule(config=empty_config, widgets=[widget_a, widget_b]) - - assert module.threshold_state(100, 80, 99) == "critical" - assert module.threshold_state(100, 80, 100) == "warning" - assert module.threshold_state(81, 80, 100) == "warning" - assert module.threshold_state(80, 80, 100) == None - assert module.threshold_state(10, 80, 100) == None - - -def test_configured_callbacks(mocker, empty_config, widget_a, widget_b): - module = SampleModule(config=empty_config, widgets=[widget_a, widget_b]) - - cmd = "sample-tool arg1 arg2 arg3" - module.set("left-click", cmd) - module.register_callbacks() - - cli = mocker.patch("core.input.util.cli") - cli.execute.return_value = "" - core.input.trigger( - {"button": core.input.LEFT_MOUSE, "instance": module.id,} - ) - - cli.execute.assert_called_once_with(cmd, wait=False, shell=True) - - -def test_configured_callbacks_with_parameters(mocker, empty_config, widget_a): - module = SampleModule(config=empty_config, widgets=[widget_a]) - - cmd = "sample-tool {instance} {name}" - module.set("left-click", cmd) - module.register_callbacks() - - cli = mocker.patch("core.input.util.cli") - cli.execute.return_value = "" - core.input.trigger( - {"button": core.input.LEFT_MOUSE, "instance": module.id, "name": "sample-name",} - ) - - cli.execute.assert_called_once_with( - cmd.format(instance=module.id, name="sample-name"), wait=False, shell=True, - ) - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/core/test_output.py b/pytests/core/test_output.py deleted file mode 100644 index 69c8b15..0000000 --- a/pytests/core/test_output.py +++ /dev/null @@ -1,173 +0,0 @@ -import json -import pytest - -import core.event -import core.config -import core.output -import core.module - - -class SampleModule(core.module.Module): - pass - -@pytest.fixture(autouse=True) -def clear_events(): - core.event.clear() - -@pytest.fixture -def i3(): - return core.output.i3() - -@pytest.fixture -def module_a(mocker): - widget = mocker.MagicMock() - widget.full_text.return_value = "test" - return SampleModule( - config=core.config.Config([]), widgets=[widget, widget, widget] - ) - -@pytest.fixture -def paddedTheme(): - return core.theme.Theme(raw_data={"defaults": {"padding": " "}}) - -@pytest.fixture -def separatorTheme(): - return core.theme.Theme( - raw_data={ - "defaults": {"separator": "***", "fg": "red", "bg": "blue"} - } - ) - -@pytest.fixture -def block_a(separatorTheme, module_a): - return core.output.block( - theme=separatorTheme, - module=module_a, - widget=module_a.widget(), - ) - -#def setUp(self): -# self.i3 = core.output.i3() -# widget = unittest.mock.MagicMock() -# widget.full_text.return_value = "test" -# self.someModule = SampleModule( -# config=core.config.Config([]), widgets=[widget, widget, widget] -# ) -# self.separator = "***" -# -def test_start(i3): - all_data = i3.start() - data = all_data["blocks"] - - assert data["version"] == 1 - assert data["click_events"] == True - assert all_data["suffix"] == "\n[" - -def test_stop(i3): - assert i3.stop()["suffix"] == "\n]" - -def test_no_modules_by_default(i3): - assert i3.modules() == [] - -def test_register_single_module(i3, module_a): - i3.modules(module_a) - - assert i3.modules() == [module_a] - -def test_register_multiple_modules(i3, module_a): - i3.modules([module_a, module_a, module_a]) - assert i3.modules() == [module_a, module_a, module_a] - -def test_draw_existing_module(mocker, i3): - i3.test_draw = mocker.MagicMock( - return_value={"blocks": {"test": True}, "suffix": "end"} - ) - i3.draw("test_draw") - i3.test_draw.assert_called_once_with() - -def test_empty_status_line(i3): - data = i3.statusline() - - assert data["blocks"] == [] - assert data["suffix"] == "," - -def test_statusline(i3, module_a): - i3.modules([module_a, module_a, module_a]) - i3.update() - data = i3.statusline() - assert len(data["blocks"]) == len(module_a.widgets())*3 - -def test_padding(i3, paddedTheme, module_a): - i3.theme(paddedTheme) - blk = core.output.block( - i3.theme(), module_a, module_a.widget() - ) - blk.set("full_text", "abc") - result = blk.dict()["full_text"] - assert result == " abc " - -def test_no_separator(i3, module_a): - result = i3.separator_block(module_a, module_a.widget()) - assert result == [] - -def test_separator(i3, separatorTheme, module_a): - i3.theme(separatorTheme) - result = i3.separator_block(module_a, module_a.widget()) - - assert len(result) == 1 - assert result[0].dict()["full_text"] == "***" - assert result[0].dict().get("_decorator") == True - assert result[0].dict()["color"] == separatorTheme.get("bg", module_a.widget()) - -def test_dump_json(mocker): - obj = mocker.MagicMock() - obj.dict = mocker.MagicMock() - core.output.dump_json(obj) - obj.dict_assert_called_once_with() - -def test_assign(): - src = {"a": "x", "b": "y", "c": "z"} - dst = {} - - core.output.assign(src, dst, "a") - assert src["a"] == dst["a"] - - core.output.assign(src, dst, "123", "b") - assert src["b"] == dst["123"] - - core.output.assign(src, dst, "blub", default="def") - assert dst["blub"] == "def" - -def test_pango_detection(block_a): - assert block_a.is_pango({}) == False - assert block_a.is_pango({ "pango": {} }) == True - -def test_pangoize(block_a): - assert block_a.pangoize("test") == "test" - assert not "markup" in block_a.dict() - - pango = block_a.pangoize( - {"pango": {"attr": "blub", "x": "y", "full_text": "test"}} - ) - assert 'attr="blub"' in pango - assert 'x="y"' in pango - assert "test" in pango - assert block_a.dict()["markup"] == "pango" - -def test_padding(block_a): - block_a.set("padding", "***") - block_a.set("full_text", "test") - - assert block_a.dict()["full_text"] == "***test***" - -def test_pre_suffix(block_a): - block_a.set("padding", "*") - block_a.set("prefix", "pre") - block_a.set("suffix", "suf") - block_a.set("full_text", "test") - - assert block_a.dict()["full_text"] == "*pre*test*suf*" - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/core/test_theme.py b/pytests/core/test_theme.py deleted file mode 100644 index 1ec1799..0000000 --- a/pytests/core/test_theme.py +++ /dev/null @@ -1,175 +0,0 @@ -import pytest -import types - -import core.theme -import core.event -import core.widget -import core.module - - -class SampleModule(core.module.Module): - def __init__(self, widgets, config=core.config.Config([]), theme=None): - super().__init__(config, theme, widgets) - self.name = "test" - -@pytest.fixture(autouse=True) -def clear_events(): - core.event.clear() - -@pytest.fixture -def defaultsTheme(): - return {"defaults": {"fg": "red", "bg": "black"}} - -@pytest.fixture -def cycleTheme(): - return { - "cycle": [ - {"fg": "red", "bg": "black"}, - {"fg": "black", "bg": "red"}, - {"fg": "white", "bg": "blue"}, - ] - } - -@pytest.fixture -def colorTheme(): - return {"colors": [{"red": "#ff0000", "blue": "#0000ff"}]} - -@pytest.fixture -def walTheme(): - return {"colors": ["wal"]} - -@pytest.fixture -def cycleValueTheme(): - return {"defaults": {"fg": ["red", "green", "blue"]}} - -@pytest.fixture -def stateTheme(): - return {"warning": {"fg": "yellow"}, "critical": {"fg": "red"}} - -@pytest.fixture -def overlayTheme(): - return { - "load": {"prefix": "a"}, - "test": {"load": {"prefix": "b"}, "prefix": "x"}, - } - -def test_invalid_theme(): - with pytest.raises(RuntimeError): - core.theme.Theme("this-theme-does-not-exist") - -def test_valid_theme(): - theme = core.theme.Theme("default") - assert theme.name == "default" - -def test_defaults(defaultsTheme): - theme = core.theme.Theme(raw_data=defaultsTheme) - - assert theme.get("fg") == defaultsTheme["defaults"]["fg"] - assert theme.get("bg") == defaultsTheme["defaults"]["bg"] - -def test_cycle(mocker, cycleTheme): - theme = core.theme.Theme(raw_data=cycleTheme) - - assert theme.get("bg", "previous") == None - assert theme.get("fg") == cycleTheme["cycle"][0]["fg"] - assert theme.get("bg") == cycleTheme["cycle"][0]["bg"] - - core.event.trigger("next-widget") - - assert theme.get("bg", "previous") == cycleTheme["cycle"][0]["bg"] - - core.event.trigger("next-widget") - - assert theme.get("fg") == cycleTheme["cycle"][2]["fg"] - assert theme.get("bg") == cycleTheme["cycle"][2]["bg"] - - stdout = mocker.patch("core.output.sys.stdout") - - core.event.trigger("draw") - - assert theme.get("fg") == cycleTheme["cycle"][0]["fg"] - assert theme.get("bg") == cycleTheme["cycle"][0]["bg"] - -def test_custom_iconset(defaultsTheme): - theme = core.theme.Theme(raw_data=defaultsTheme) - - assert theme.get("padding") != "aaa" - assert theme.get("fg") != "blue" - - theme = core.theme.Theme( - raw_data=defaultsTheme, iconset={"defaults": {"padding": "aaa", "fg": "blue"}} - ) - - assert theme.get("padding") == "aaa" - assert theme.get("fg") == "blue" # test override - -def test_colors(defaultsTheme, colorTheme): - theme = core.theme.Theme(raw_data=defaultsTheme) - assert theme.keywords() == {} - - theme = core.theme.Theme(raw_data=colorTheme) - assert theme.keywords() == colorTheme["colors"][0] - -def test_wal_colors(mocker, walTheme): - io = mocker.patch("core.theme.io") - os = mocker.patch("core.theme.os") - - os.path.isfile.return_value = True - io.open.return_value = mocker.MagicMock() - io.open.return_value.__enter__.return_value.read.return_value = """ - { "colors": { "red": "#ff0000" } } - """ - - theme = core.theme.Theme(raw_data=walTheme) - - assert theme.keywords() == {"red": "#ff0000"} - -def test_wal_special(mocker, walTheme): - io = mocker.patch("core.theme.io") - os = mocker.patch("core.theme.os") - - os.path.isfile.return_value = True - io.open.return_value.__enter__.return_value.read.return_value = """ - { "special": { "background": "#ff0000" } } - """ - - theme = core.theme.Theme(raw_data=walTheme) - - assert theme.keywords() == {"background": "#ff0000"} - -def test_cycle_value(cycleValueTheme): - widget = core.widget.Widget() - expected = cycleValueTheme["defaults"]["fg"] - theme = core.theme.Theme(raw_data=cycleValueTheme) - - for i in range(0, len(expected) * 3): - assert theme.get("fg", widget) == expected[i%len(expected)] - # ensure multiple invocations are OK - assert theme.get("fg", widget) == expected[i%len(expected)] - core.event.trigger("draw") - -def test_state(stateTheme): - widget = core.widget.Widget() - theme = core.theme.Theme(raw_data=stateTheme) - - assert theme.get("fg", widget) == None - - widget.state = types.MethodType(lambda self: ["warning"], widget) - assert theme.get("fg", widget) == stateTheme["warning"]["fg"] - - widget.state = types.MethodType(lambda self: ["critical"], widget) - assert theme.get("fg", widget) == stateTheme["critical"]["fg"] - -def test_overlay(overlayTheme): - widget = core.widget.Widget() - module = SampleModule(widget) - theme = core.theme.Theme(raw_data=overlayTheme) - - assert theme.get("prefix", widget) == overlayTheme[module.name]["prefix"] - - widget.state = types.MethodType(lambda self: ["load"], widget) - - assert theme.get("prefix", widget) == overlayTheme[module.name]["load"]["prefix"] - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/core/test_widget.py b/pytests/core/test_widget.py deleted file mode 100644 index 9a51021..0000000 --- a/pytests/core/test_widget.py +++ /dev/null @@ -1,97 +0,0 @@ -import pytest - -import core.widget -import core.module -import core.config - - -class SampleModule(core.module.Module): - def __init__(self, widgets, config=core.config.Config([]), theme=None): - super().__init__(config, theme, widgets) - self.states = [] - - def update(self): - if self.fail: - raise Exception(self.error) - pass - - def state(self, widget): - return self.states - -@pytest.fixture -def widget_a(): - return core.widget.Widget("some random value") - -#class widget(unittest.TestCase): -# def setUp(self): -# self.someValue = "some random value" -# self.someOtherValue = "some different value" -# self.callbackReturnValue = "callback return value" -# self.someWidget = core.widget.Widget(full_text=self.someValue) -# self.someCallback = unittest.mock.MagicMock( -# return_value=self.callbackReturnValue -# ) -# -# self.assertNotEqual(self.someValue, self.someOtherValue) - -def test_text_fulltext(): - widget = core.widget.Widget(full_text="this is some value") - assert widget.full_text() == "this is some value" - -def test_set_fulltext(widget_a): - assert widget_a.full_text() != "new value" - widget_a.full_text("new value") - assert widget_a.full_text() == "new value" - -def test_callable_fulltext(mocker): - callback = mocker.MagicMock(return_value="callback returns") - widget = core.widget.Widget(full_text=callback) - assert widget.full_text() == "callback returns" - callback.assert_called_once_with(widget) - -def test_set_callable_fulltext(mocker, widget_a): - callback = mocker.MagicMock(return_value="this is a test") - widget_a.full_text(callback) - assert widget_a.full_text() == "this is a test" - callback.assert_called_once_with(widget_a) - -def test_state_defaults_to_empty(widget_a): - assert widget_a.state() == [] - -def test_single_widget_state(widget_a): - widget_a.set("state", "state1") - assert widget_a.state() == ["state1"] - -def test_multiple_widget_states(widget_a): - widget_a.set("state", ["state1", "state2"]) - assert widget_a.state() == ["state1", "state2"] - -def test_widget_module_state(widget_a): - module = SampleModule(widgets=widget_a) - widget_a.set("state", ["state1", "state2"]) - - module.states = "x" - assert widget_a.state() == ["state1", "state2", "x"] - - module.states = ["a", "b"] - assert widget_a.state() == ["state1", "state2", "a", "b"] - -def test_multiple_widget_themes(): - widget1 = core.widget.Widget(full_text="a") - widget2 = core.widget.Widget(full_text="b") - widget3 = core.widget.Widget(full_text="c") - - module = SampleModule(widgets=[widget1, widget2, widget3]) - module.set("theme.test", "1,2,3") - module.set("theme.test2", "x") - - assert widget1.theme("test") == "1" - assert widget2.theme("test") == "2" - assert widget3.theme("test") == "3" - - assert widget1.theme("test2") == "x" - assert widget2.theme("test2") == None - assert widget3.theme("test2") == None - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/modules/__init__.py b/pytests/modules/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/pytests/modules/contrib/__init__.py b/pytests/modules/contrib/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/pytests/util/test_algorithm.py b/pytests/util/test_algorithm.py deleted file mode 100644 index 617187c..0000000 --- a/pytests/util/test_algorithm.py +++ /dev/null @@ -1,50 +0,0 @@ -import pytest - -from util.algorithm import * - -@pytest.fixture -def someData(): - return {"a": 100, "b": 200, "c": [1, 2, 3]} - -@pytest.fixture -def differentData(): - return {"x": 20, "y": "bla", "z": ["a", "b"]} - -@pytest.fixture -def moreData(): - return {"n": 100} - -@pytest.fixture -def overlapData(): - return {"a": 200, "c": [1, 2, 4]} - -def test_merge_with_empty(someData): - assert merge(someData, {}) == someData - assert merge(someData, None) == None - - def test_merge_no_overwrite(someData, differentData): - result = merge(someData, differentData) - for k in someData: - assert someData[k] == result[k] - for k in self.differentData: - assert differentData[k] == result[k] - - def test_merge_multiple(someData, differentData, moreData): - result = merge(someData, differentData, moreData) - for k in someData: - assert someData[k] == result[k] - for k in differentData: - assert differentData[k] == result[k] - for k in moreData: - assert moreData[k] == result[k] - - def merge_overlap(someData, overlapData): - result = merge(someData, overlapData) - for k in someData: - if not k in self.overlapData: - assert someData[k] == result[k] - for k in self.overlapData: - assert overlapData[k] == result[k] - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/util/test_cli.py b/pytests/util/test_cli.py deleted file mode 100644 index b2d8f81..0000000 --- a/pytests/util/test_cli.py +++ /dev/null @@ -1,27 +0,0 @@ -import pytest - -import util.cli - -def test_valid_command(): - assert util.cli.execute("echo test") == "test\n" - -def test_utf_command(): - rv = util.cli.execute("echo ÖPmŧß") - assert util.cli.execute("echo ÖPmŧß") == "ÖPmŧß\n" - -def test_invalid_command(): - with pytest.raises(RuntimeError): - util.cli.execute("i-do-not-exist") - -def test_command_exit_code(): - with pytest.raises(RuntimeError): - util.cli.execute("cat i-do-not-exist") - -def test_command_exit_code_no_error(): - util.cli.execute("cat i-do-not-exist", ignore_errors=True) - -def test_async(): - assert util.cli.execute("echo test", wait=False) == "" - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/util/test_format.py b/pytests/util/test_format.py deleted file mode 100644 index 4dda6e9..0000000 --- a/pytests/util/test_format.py +++ /dev/null @@ -1,113 +0,0 @@ -import pytest - -from util.format import * - - -def test_int_from_string(): - assert asint("100") == 100 - assert asint("-100") == -100 - assert asint("0") == 0 - - -def test_int_from_none(): - assert asint(None) == 0 - - -def test_int_from_int(): - assert asint(100) == 100 - assert asint(-100) == -100 - assert asint(0) == 0 - - -def test_int_minimum(): - assert asint(100, minimum=10) == 100 - assert asint(100, minimum=100) == 100 - assert asint(5, minimum=10) == 10 - - -def test_int_maximum(): - assert asint(100, maximum=200) == 100 - assert asint(100, maximum=100) == 100 - assert asint(200, maximum=100) == 100 - - -def test_true_from_str(): - assert asbool("true") == True - assert asbool(True) == True - assert asbool("t") == True - assert asbool("1") == True - assert asbool("yes") == True - assert asbool("y") == True - assert asbool("on") == True - - -def test_false_from_str(): - assert asbool("false") == False - assert asbool(False) == False - assert asbool("f") == False - assert asbool("0") == False - assert asbool("no") == False - assert asbool("n") == False - assert asbool("off") == False - assert asbool(None) == False - - -def test_list_from_None(): - assert aslist(None) == [] - - -def test_list_from_list(): - assert aslist([1, 2, 3] == [1, 2, 3]) - - -def test_list_from_str(): - assert aslist("12,13,14") == ["12", "13", "14"] - - -def test_byteformat(): - assert byte(500) == "500.00B" - assert byte(1024) == "1.00KiB" - assert byte(1024, "{:.0f}") == "1KiB" - assert byte(1024 + 512) == "1.50KiB" - assert byte(1024 * 1024 * 2 + 1024 * 512) == "2.50MiB" - assert byte(1024 * 1024 * 1024 * 4 + 1024 * 1024 * 512) == "4.50GiB" - assert byte(1024 * 1024 * 1024 * 1024 * 2) == "2048.00GiB" - - -def test_duration(): - assert duration(4 * 60 * 60 + 20 * 60) == "04:20:00" - assert duration(4 * 60 * 60 + 20 * 60, unit=True) == "04:20:00h" - assert duration(4 * 60 * 60 + 20 * 60, compact=True, unit=True) == "04:20h" - - assert duration(20 * 60) == "20:00" - assert duration(20 * 60, unit=True) == "20:00m" - assert duration(20 * 60, compact=True, unit=True) == "20:00m" - - assert duration(20) == "00:20" - assert duration(20, unit=True) == "00:20m" - assert duration(20, compact=True, unit=True) == "00:20m" - - assert duration(-1) == "n/a" - - -def test_seconds(): - assert seconds(10) == 10 - assert seconds("10") == 10 - - assert seconds("5m") == 300 - assert seconds("5m20s") == 320 - - assert seconds("4h") == 4 * 3600 - assert seconds("4h5m22s") == 4 * 3600 + 5 * 60 + 22 - - assert seconds("4h5m") == 4 * 3600 + 5 * 60 - - -def test_temperature(): - assert astemperature(10) == "10°C" - assert astemperature(10, "metric") == "10°C" - assert astemperature(-100, "imperial") == "-100°F" - assert astemperature(-100, "kelvin") == "-100°K" - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/util/test_location.py b/pytests/util/test_location.py deleted file mode 100644 index 21dd2e2..0000000 --- a/pytests/util/test_location.py +++ /dev/null @@ -1,57 +0,0 @@ -import pytest -import json - -import util.location - - -@pytest.fixture -def urllib_req(mocker): - util.location.reset() - return mocker.patch("util.location.urllib.request") - - -@pytest.fixture -def primaryLocation(): - return { - "country": "Middle Earth", - "longitude": "10.0", - "latitude": "20.5", - "ip": "127.0.0.1", - } - - -@pytest.fixture -def secondaryLocation(): - return { - "country_name": "Rivia", - "longitude": "-10.0", - "latitude": "-23", - "ip": "127.0.0.6", - } - - -def test_primary_provider(urllib_req, primaryLocation): - urllib_req.urlopen.return_value.read.return_value = json.dumps(primaryLocation) - - assert util.location.country() == primaryLocation["country"] - assert util.location.coordinates() == ( - primaryLocation["latitude"], - primaryLocation["longitude"], - ) - assert util.location.public_ip() == primaryLocation["ip"] - - -def test_secondary_provider(mocker, urllib_req, secondaryLocation): - urlopen = mocker.MagicMock() - urlopen.read.return_value = json.dumps(secondaryLocation) - urllib_req.urlopen.side_effect = [RuntimeError(), urlopen] - - assert util.location.country() == secondaryLocation["country_name"] - assert util.location.coordinates() == ( - secondaryLocation["latitude"], - secondaryLocation["longitude"], - ) - assert util.location.public_ip() == secondaryLocation["ip"] - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/util/test_store.py b/pytests/util/test_store.py deleted file mode 100644 index 9128edd..0000000 --- a/pytests/util/test_store.py +++ /dev/null @@ -1,48 +0,0 @@ -import pytest - -import util.store - - -@pytest.fixture -def emptyStore(): - return util.store.Store() - - -@pytest.fixture -def store(): - return util.store.Store() - - -def test_get_of_unset_key(emptyStore): - assert emptyStore.get("any-key") == None - assert emptyStore.get("any-key", "default-value") == "default-value" - - -def test_get_of_set_key(store): - store.set("key", "value") - assert store.get("key") == "value" - - -def test_overwrite_set(store): - store.set("key", "value 1") - store.set("key", "value 2") - - assert store.get("key") == "value 2" - - -def test_unused_keys(store): - store.set("key 1", "value x") - store.set("key 2", "value y") - - assert store.unused_keys() == sorted(["key 1", "key 2"]) - - store.get("key 2") - - assert store.unused_keys() == ["key 1"] - - store.get("key 1") - - assert store.unused_keys() == [] - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/__init__.py b/tests/__init__.py index 8df5d95..afddb20 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,3 +1,4 @@ import bumblebee_status.discover bumblebee_status.discover.discover() + diff --git a/tests/core/test_config.py b/tests/core/test_config.py index e468f3a..774b806 100644 --- a/tests/core/test_config.py +++ b/tests/core/test_config.py @@ -1,89 +1,102 @@ import os -import unittest +import pytest import core.config +@pytest.fixture +def defaultConfig(): + return core.config.Config([]) -class config(unittest.TestCase): - def setUp(self): - self.someModules = ["b", "x", "a"] - self.moreModules = ["this", "module", "here"] - self.someTheme = "some-theme" - self.someIconset = "some-iconset" - self.defaultConfig = core.config.Config([]) +def test_module(): + modules = ["module-1", "module-2", "module-3"] - def test_module(self): - cfg = core.config.Config(["-m"] + self.someModules) - self.assertEqual(self.someModules, cfg.modules()) + cfg = core.config.Config(["-m"] + modules) - def test_module_ordering_maintained(self): - cfg = core.config.Config(["-m"] + self.someModules + ["-m"] + self.moreModules) - self.assertEqual(self.someModules + self.moreModules, cfg.modules()) + assert cfg.modules() == modules - def test_default_interval(self): - self.assertEqual(1, self.defaultConfig.interval()) +def test_module_ordering_maintained(): + modules = ["module-1", "module-5", "module-7"] + more_modules = ["module-0", "module-2", "aaa"] - def test_interval(self): - cfg = core.config.Config(["-p", "interval=4"]) - self.assertEqual(4, cfg.interval()) + cfg = core.config.Config(["-m"] + modules + ["-m"] + more_modules) - def test_float_interval(self): - cfg = core.config.Config(["-p", "interval=0.5"]) - self.assertEqual(0.5, cfg.interval()) + assert cfg.modules() == modules + more_modules - def test_default_theme(self): - self.assertEqual("default", self.defaultConfig.theme()) +def test_default_interval(defaultConfig): + assert defaultConfig.interval() == 1 - def test_theme(self): - cfg = core.config.Config(["-t", self.someTheme]) - self.assertEqual(self.someTheme, cfg.theme()) +def test_interval(): + interval = 4 + cfg = core.config.Config(["-p", "interval={}".format(interval)]) - def test_default_iconset(self): - self.assertEqual("auto", self.defaultConfig.iconset()) + assert cfg.interval() == interval - def test_iconset(self): - cfg = core.config.Config(["-i", self.someIconset]) - self.assertEqual(self.someIconset, cfg.iconset()) +def test_floating_interval(): + interval = 4.5 + cfg = core.config.Config(["-p", "interval={}".format(interval)]) - def test_right_to_left(self): - cfg = core.config.Config(["-r"]) - self.assertTrue(cfg.reverse()) - self.assertFalse(self.defaultConfig.reverse()) + assert cfg.interval() == interval - def test_logfile(self): - cfg = core.config.Config(["-f", "my-custom-logfile"]) - self.assertEqual(None, self.defaultConfig.logfile()) - self.assertEqual("my-custom-logfile", cfg.logfile()) +def test_default_theme(defaultConfig): + assert defaultConfig.theme() == "default" - def test_all_modules(self): - modules = core.config.all_modules() - self.assertGreater(len(modules), 0) - for module in modules: - pyname = "{}.py".format(module) - base = os.path.abspath( - os.path.join( - os.path.dirname(os.path.realpath(__file__)), - "..", - "..", - "bumblebee_status", - "modules", - ) - ) - self.assertTrue( - os.path.exists(os.path.join(base, "contrib", pyname)) - or os.path.exists(os.path.join(base, "core", pyname)) +def test_theme(): + theme_name = "sample-theme" + cfg = core.config.Config(["-t", theme_name]) + assert cfg.theme() == theme_name + +def test_default_iconset(defaultConfig): + assert defaultConfig.iconset() == "auto" + +def test_iconset(): + iconset_name = "random-iconset" + cfg = core.config.Config(["-i", iconset_name]) + assert cfg.iconset() == iconset_name + +def test_reverse(defaultConfig): + assert defaultConfig.reverse() == False + + cfg = core.config.Config(["-r"]) + + assert cfg.reverse() == True + +def test_logfile(defaultConfig): + assert defaultConfig.logfile() is None + + logfile = "some-random-logfile" + cfg = core.config.Config(["-f", logfile]) + assert cfg.logfile() == logfile + + + +def test_all_modules(): + modules = core.config.all_modules() + assert len(modules) > 0 + + for module in modules: + pyname = "{}.py".format(module) + base = os.path.abspath( + os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "..", + "..", + "bumblebee_status", + "modules", ) + ) + assert os.path.exists(os.path.join(base, "contrib", pyname)) \ + or os.path.exists(os.path.join(base, "core", pyname)) - def test_list_output(self): - with unittest.mock.patch("core.config.sys") as sys: - cfg = core.config.Config(["-l", "themes"]) - cfg = core.config.Config(["-l", "modules"]) - cfg = core.config.Config(["-l", "modules-rst"]) - # TODO: think of some plausibility testing here - - def test_missing_parameter(self): - cfg = core.config.Config(["-p", "test.key"]) - self.assertEqual("no-value-set", cfg.get("test.key", "no-value-set")) +def test_list_output(mocker): + mocker.patch("core.config.sys") + cfg = core.config.Config(["-l", "themes"]) + cfg = core.config.Config(["-l", "modules"]) + cfg = core.config.Config(["-l", "modules-rst"]) +def test_missing_parameter(): + cfg = core.config.Config(["-p", "test.key"]) + assert cfg.get("test.key") == None + assert cfg.get("test.key", "no-value-set") == "no-value-set" +# # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_decorators.py b/tests/core/test_decorators.py index ab924da..25f8b9c 100644 --- a/tests/core/test_decorators.py +++ b/tests/core/test_decorators.py @@ -1,99 +1,103 @@ -import unittest +import pytest import core.decorators import core.widget import core.module import core.config +@pytest.fixture +def module(): + class TestModule(core.module.Module): + @core.decorators.never + def __init__(self, config=None, theme=None): + config = core.config.Config([]) + super().__init__(config, theme, core.widget.Widget(self.get)) + self.text = "" -class TestModule(core.module.Module): - @core.decorators.never - def __init__(self, config=None, theme=None): - config = core.config.Config([]) - super().__init__(config, theme, core.widget.Widget(self.get)) - self.text = "" + @core.decorators.scrollable + def get(self, widget): + return self.text + module = TestModule() + module.set("scrolling.width", 10) + return module - @core.decorators.scrollable - def get(self, widget): - return self.text +def test_never(module): + assert module.parameter("interval") == "never" +def test_no_text(module): + assert module.text == "" + assert module.get(module.widget()) == "" -class config(unittest.TestCase): - def setUp(self): - self.module = TestModule() - self.widget = self.module.widget() - self.width = 10 - self.module.set("scrolling.width", self.width) +def test_smaller(module): + module.text = "test" + assert module.parameter("scrolling.width") > len(module.text) + assert module.get(module.widget()) == module.text - def test_never(self): - self.module = TestModule() - self.assertEqual("never", self.module.parameter("interval")) +def test_bigger(module): + module.text = "this is a really really long sample text" + maxwidth = module.parameter("scrolling.width") + assert maxwidth < len(module.text) + assert module.get(module.widget()) == module.text[:maxwidth] - def test_no_text(self): - self.assertEqual("", self.module.text) - self.assertEqual("", self.module.get(self.widget)) +def test_bounce(module): + module.text = "abcd" + module.set("scrolling.width", 2) + assert module.get(module.widget()) == "ab" + assert module.get(module.widget()) == "bc" + assert module.get(module.widget()) == "cd" + assert module.get(module.widget()) == "bc" + assert module.get(module.widget()) == "ab" + assert module.get(module.widget()) == "bc" + assert module.get(module.widget()) == "cd" + assert module.get(module.widget()) == "bc" + assert module.get(module.widget()) == "ab" - def test_smaller(self): - self.module.text = "test" - self.assertLess(len(self.module.text), self.width) - self.assertEqual("test", self.module.get(self.widget)) +def test_nobounce(module): + module.set("scrolling.bounce", False) + module.set("scrolling.width", 2) + module.text = "abcd" - def test_bigger(self): - self.module.text = "abcdefghijklmnopqrst" - self.assertGreater(len(self.module.text), self.width) - self.assertEqual(self.module.text[: self.width], self.module.get(self.widget)) + assert module.get(module.widget()) == "ab" + assert module.get(module.widget()) == "bc" + assert module.get(module.widget()) == "cd" + assert module.get(module.widget()) == "ab" + assert module.get(module.widget()) == "bc" + assert module.get(module.widget()) == "cd" - def test_bounce(self): - self.module.text = "abcd" - self.module.set("scrolling.width", 2) - self.assertEqual("ab", self.module.get(self.widget)) - self.assertEqual("bc", self.module.get(self.widget)) - self.assertEqual("cd", self.module.get(self.widget)) - self.assertEqual("bc", self.module.get(self.widget)) - self.assertEqual("ab", self.module.get(self.widget)) - self.assertEqual("bc", self.module.get(self.widget)) - self.assertEqual("cd", self.module.get(self.widget)) - self.assertEqual("bc", self.module.get(self.widget)) - self.assertEqual("ab", self.module.get(self.widget)) +def test_completely_changed_data(module): + module.text = "abcd" + module.set("scrolling.width", 2) - def test_nobounce(self): - self.module.set("scrolling.bounce", False) - self.module.text = "abcd" - self.module.set("scrolling.width", 2) - self.assertEqual("ab", self.module.get(self.widget)) - self.assertEqual("bc", self.module.get(self.widget)) - self.assertEqual("cd", self.module.get(self.widget)) - self.assertEqual("ab", self.module.get(self.widget)) - self.assertEqual("bc", self.module.get(self.widget)) - self.assertEqual("cd", self.module.get(self.widget)) + assert module.get(module.widget()) == "ab" + assert module.get(module.widget()) == "bc" - def test_changed_data(self): - self.module.text = "abcd" - self.module.set("scrolling.width", 2) - self.assertEqual("ab", self.module.get(self.widget)) - self.assertEqual("bc", self.module.get(self.widget)) - self.module.text = "wxyz" - self.assertEqual("wx", self.module.get(self.widget)) + module.text = "wxyz" + assert module.get(module.widget()) == "wx" + assert module.get(module.widget()) == "xy" - def test_minimum_changed_data(self): - self.module.text = "this is a sample song (0:00)" - self.module.set("scrolling.width", 10) - self.assertEqual(self.module.text[0:10], self.module.get(self.widget)) - self.module.text = "this is a sample song (0:01)" - self.assertEqual(self.module.text[1:11], self.module.get(self.widget)) - self.module.text = "this is a sample song (0:12)" - self.assertEqual(self.module.text[2:12], self.module.get(self.widget)) - self.module.text = "this is a different song (0:12)" - self.assertEqual(self.module.text[0:10], self.module.get(self.widget)) +def test_slightly_changed_data(module): + module.text = "this is a sample song (0:00)" + module.set("scrolling.width", 10) - def test_n_plus_one(self): - self.module.text = "10 letters" - self.module.set("scrolling.width", 9) - self.assertEqual(self.module.text[0:9], self.module.get(self.widget)) - self.assertEqual(self.module.text[1:10], self.module.get(self.widget)) - self.assertEqual(self.module.text[0:9], self.module.get(self.widget)) - self.assertEqual(self.module.text[1:10], self.module.get(self.widget)) - self.assertEqual(self.module.text[0:9], self.module.get(self.widget)) + assert module.get(module.widget()) == module.text[0:10] + module.text = "this is a sample song (0:01)" + assert module.get(module.widget()) == module.text[1:11] + module.text = "this is a sample song (0:02)" + assert module.get(module.widget()) == module.text[2:12] + module.text = "this is a sample song (0:13)" + assert module.get(module.widget()) == module.text[3:13] + module.text = "this is a different song (0:13)" + assert module.get(module.widget()) == module.text[0:10] + +def test_n_plus_one(module): + module.text = "10 letters" + module.set("scrolling.width", 9) + + assert module.get(module.widget()) == module.text[0:9] + assert module.get(module.widget()) == module.text[1:10] + assert module.get(module.widget()) == module.text[0:9] + assert module.get(module.widget()) == module.text[1:10] + assert module.get(module.widget()) == module.text[0:9] # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_event.py b/tests/core/test_event.py index e256bc4..b64478f 100644 --- a/tests/core/test_event.py +++ b/tests/core/test_event.py @@ -1,62 +1,73 @@ -import unittest +import pytest import core.event +@pytest.fixture +def someEvent(): + class Event(): + def __init__(self): + core.event.clear() + self.id = "some event" + self.called = 0 + self.call_args = [] + self.call_kwargs = [] -class event(unittest.TestCase): - def setUp(self): - self.someEvent = "event" - self.called = {} - self.params = [] - core.event.clear() + def callback(self, *args, **kwargs): + self.called += 1 + if args: + self.call_args.append(list(args)) + if kwargs: + self.call_kwargs.append(kwargs) - def callback1(self): - self.called["callback1"] = True + return Event() - def callback2(self): - self.called["callback2"] = True - def callback_args(self, val1, val2): - self.called["callback_args"] = True - self.params = [val1, val2] +def test_simple_callback(someEvent): + assert someEvent.called == 0 - def callback_kwargs(self, val1, val2, key1=None, key2=None): - self.called["callback_kwargs"] = True - self.params = [val1, val2, key1, key2] + core.event.register(someEvent.id, someEvent.callback) + core.event.register(someEvent.id, someEvent.callback) - def test_simple_callback(self): - core.event.register(self.someEvent, self.callback1) - core.event.register(self.someEvent, self.callback2) + core.event.trigger(someEvent.id) - core.event.trigger(self.someEvent) + assert someEvent.called == 2 - self.assertEqual(2, len(self.called.keys())) +def test_args_callback(someEvent): + core.event.register(someEvent.id, someEvent.callback, "a", "b") + core.event.trigger(someEvent.id) - def test_arg_callback(self): - core.event.register(self.someEvent, self.callback_args, "a", "b") - core.event.trigger(self.someEvent) - self.assertEqual(1, len(self.called.keys())) - self.assertEqual(["a", "b"], self.params) + assert someEvent.called == 1 + assert len(someEvent.call_args) == 1 + assert someEvent.call_args[0] == ["a", "b"] - def test_kwargs_callback(self): - core.event.register( - self.someEvent, self.callback_kwargs, "a", "b", key1="test", key2="x" - ) - core.event.trigger(self.someEvent) - self.assertEqual(1, len(self.called.keys())) - self.assertEqual(["a", "b", "test", "x"], self.params) +def test_kwargs_callback(someEvent): + core.event.register( + someEvent.id, someEvent.callback, "a", "b", key1="test", key2="another" + ) + core.event.trigger(someEvent.id) - def test_arg_trigger(self): - core.event.register(self.someEvent, self.callback_args) - core.event.trigger(self.someEvent, "a", "b") - self.assertEqual(1, len(self.called.keys())) - self.assertEqual(["a", "b"], self.params) + assert someEvent.called == 1 + assert len(someEvent.call_args) == 1 + assert someEvent.call_args[0] == ["a", "b"] + assert len(someEvent.call_kwargs) == 1 + assert someEvent.call_kwargs[0] == { "key1": "test", "key2": "another" } - def test_kwargs_trigger(self): - core.event.register(self.someEvent, self.callback_kwargs) - core.event.trigger(self.someEvent, "a", "b", key1="test", key2="x") - self.assertEqual(1, len(self.called.keys())) - self.assertEqual(["a", "b", "test", "x"], self.params) +def test_arg_trigger(someEvent): + core.event.register(someEvent.id, someEvent.callback) + core.event.trigger(someEvent.id, "a", "b") + assert someEvent.called == 1 + assert len(someEvent.call_args) == 1 + assert someEvent.call_args[0] == ["a", "b"] + +def test_kwargs_trigger(someEvent): + core.event.register(someEvent.id, someEvent.callback) + core.event.trigger(someEvent.id, "a", "c", key1="test", key2="something") + + assert someEvent.called == 1 + assert len(someEvent.call_args) == 1 + assert someEvent.call_args[0] == ["a", "c"] + assert len(someEvent.call_kwargs) == 1 + assert someEvent.call_kwargs[0] == { "key1": "test", "key2": "something" } # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_input.py b/tests/core/test_input.py index ba5641e..962b5b2 100644 --- a/tests/core/test_input.py +++ b/tests/core/test_input.py @@ -1,90 +1,104 @@ -import unittest +import pytest import core.input -class config(unittest.TestCase): - def setUp(self): - self.inputObject = core.input.Object() - self.anotherObject = core.input.Object() - self.someEvent = { - "button": core.input.LEFT_MOUSE, - "instance": self.inputObject.id, - } - self.anotherEvent = { - "button": core.input.RIGHT_MOUSE, - "instance": self.inputObject.id, - } - self.callback = unittest.mock.MagicMock() - self.callback2 = unittest.mock.MagicMock() - self.someCommand = "some sample command" +@pytest.fixture +def obj(): + return core.input.Object() - def test_callable_gets_called(self): - core.input.register(self.inputObject, self.someEvent["button"], self.callback) - core.input.trigger(self.someEvent) - self.callback.assert_called_once_with(self.someEvent) - def test_nonexistent_callback(self): - core.input.register(self.inputObject, self.someEvent["button"], self.callback) - core.input.trigger(self.anotherEvent) - self.callback.assert_not_called() +@pytest.fixture +def obj2(): + return core.input.Object() - def test_different_events(self): - core.input.register(self.inputObject, self.someEvent["button"], self.callback) - core.input.register( - self.inputObject, self.anotherEvent["button"], self.callback - ) - core.input.register( - self.anotherObject, self.someEvent["button"], self.callback2 - ) - core.input.register( - self.anotherObject, self.anotherEvent["button"], self.callback2 - ) - core.input.trigger(self.someEvent) - core.input.trigger(self.anotherEvent) - self.callback.assert_any_call(self.someEvent) - self.callback.assert_any_call(self.anotherEvent) - self.callback2.assert_not_called() - def test_multiple_registrations(self): - core.input.register(self.inputObject, self.someEvent["button"], self.callback) - core.input.register(self.inputObject, self.someEvent["button"], self.callback2) - core.input.trigger(self.someEvent) - self.callback.assert_called_once_with(self.someEvent) - self.callback2.assert_called_once_with(self.someEvent) +@pytest.fixture +def cb(mocker): + return mocker.MagicMock() - def test_event_names(self): - self.assertEqual(core.input.button_name(core.input.LEFT_MOUSE), "left-mouse") - self.assertEqual(core.input.button_name(core.input.RIGHT_MOUSE), "right-mouse") - self.assertEqual( - core.input.button_name(core.input.MIDDLE_MOUSE), "middle-mouse" - ) - self.assertEqual(core.input.button_name(core.input.WHEEL_UP), "wheel-up") - self.assertEqual(core.input.button_name(core.input.WHEEL_DOWN), "wheel-down") - self.assertEqual(core.input.button_name(12345), "n/a") - def test_non_callable_callback(self): - with unittest.mock.patch("core.input.util.cli") as cli: - cli.execute.return_value = "" - core.input.register( - self.inputObject, self.someEvent["button"], self.someCommand - ) - core.input.trigger(self.someEvent) - cli.execute.assert_called_once_with( - self.someCommand, wait=False, shell=True - ) +@pytest.fixture +def cb2(mocker): + return mocker.MagicMock() - def test_non_existent_callback(self): - with unittest.mock.patch("core.input.util.cli") as cli: - cli.execute.return_value = "" - cli.execute.side_effect = RuntimeError("some-error") - core.input.register( - self.inputObject, self.someEvent["button"], self.someCommand - ) - try: - core.input.trigger(self.someEvent) - except Exception: - self.fail("input module propagated exception") + +def event(input_object): + return {"button": core.input.LEFT_MOUSE, "instance": input_object.id} + + +def event2(input_object): + return {"button": core.input.RIGHT_MOUSE, "instance": input_object.id} + + +def test_callable_gets_called(obj, cb): + core.input.register(obj, event(obj)["button"], cb) + core.input.trigger(event(obj)) + + cb.assert_called_once_with(event(obj)) + + +def test_nonexistent_callback(obj, obj2, cb): + core.input.register(obj, event(obj)["button"], cb) + core.input.trigger(event(obj2)) + + cb.assert_not_called() + + +def test_different_events(obj, obj2, cb, cb2): + core.input.register(obj, event(obj)["button"], cb) + core.input.register(obj, event2(obj)["button"], cb) + core.input.register(obj2, event(obj)["button"], cb2) + core.input.register(obj2, event2(obj)["button"], cb2) + + core.input.trigger(event(obj)) + core.input.trigger(event2(obj)) + + cb.assert_any_call(event(obj)) + cb.assert_any_call(event2(obj)) + cb2.assert_not_called() + + +def test_multiple_registrations(obj, cb, cb2): + core.input.register(obj, event(obj)["button"], cb) + core.input.register(obj, event(obj)["button"], cb2) + + core.input.trigger(event(obj)) + + cb.assert_called_once_with(event(obj)) + cb2.assert_called_once_with(event(obj)) + + +def test_event_names(): + assert core.input.button_name(core.input.LEFT_MOUSE) == "left-mouse" + assert core.input.button_name(core.input.RIGHT_MOUSE) == "right-mouse" + assert core.input.button_name(core.input.MIDDLE_MOUSE) == "middle-mouse" + assert core.input.button_name(core.input.WHEEL_UP) == "wheel-up" + assert core.input.button_name(core.input.WHEEL_DOWN) == "wheel-down" + assert core.input.button_name(12345) == "n/a" + + +def test_non_callable_callback(mocker, obj): + cli = mocker.patch("core.input.util.cli") + cli.execute.return_value = "" + + core.input.register(obj, event(obj)["button"], "sample-command") + + core.input.trigger(event(obj)) + + cli.execute.assert_called_once_with("sample-command", wait=False, shell=True) + + +def test_non_existent_callback(mocker, obj): + cli = mocker.patch("core.input.util.cli") + cli.execute.return_value = "" + cli.execute.side_effect = RuntimeError("some-error") + + core.input.register(obj, event(obj)["button"], "sample-command") + + core.input.trigger(event(obj)) + + cli.execute.assert_called_once_with("sample-command", wait=False, shell=True) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_module.py b/tests/core/test_module.py index 307277e..ef65c88 100644 --- a/tests/core/test_module.py +++ b/tests/core/test_module.py @@ -1,4 +1,4 @@ -import unittest +import pytest import sys import shlex @@ -9,175 +9,169 @@ import core.config import core.input -class TestModule(core.module.Module): +@pytest.fixture(autouse=True) +def clear_events(): + core.event.clear() + + +@pytest.fixture +def empty_config(): + return core.config.Config([]) + + +@pytest.fixture +def widget_a(): + return core.widget.Widget("randomwWidget content", name="A") + + +@pytest.fixture +def widget_b(): + return core.widget.Widget("another randomwWidget content", name="B") + + +class SampleModule(core.module.Module): def update(self): if self.fail: raise Exception(self.error) pass -class module(unittest.TestCase): - def setUp(self): - core.event.clear() - self.invalidModuleName = "invalid-module-name" - self.validModuleName = "test" - self.someWidget = core.widget.Widget("randomeWidgetContent", name="A") - self.anotherWidget = core.widget.Widget("more Widget content", name="B") - self.unusedWidgetName = "C" +def test_loadinvalid_module(mocker): + config = mocker.MagicMock() + module = core.module.load(module_name="i-do-not-exist", config=config) + assert module.__class__.__module__ == "core.module" + assert module.__class__.__name__ == "Error" - def test_loadinvalid_module(self): - config = unittest.mock.MagicMock() - module = core.module.load(module_name=self.invalidModuleName, config=config) - self.assertEqual( - "core.module", module.__class__.__module__, "module must be a module object" - ) - self.assertEqual( - "Error", - module.__class__.__name__, - "an invalid module must be a core.module.Error", - ) - @unittest.skipIf( - sys.version_info.major == 3 and sys.version_info.minor in [4, 5], - "importlib error reporting in Python 3.{4,5} different", +@pytest.mark.skipif( + sys.version_info.major == 3 and sys.version_info.minor in [4, 5], + reason="importlib error reporting in Python 3.{4,5} different", +) +def test_importerror(mocker): + importlib = mocker.patch("core.module.importlib") + importlib.import_module.side_effect = ImportError("some-error") + config = mocker.MagicMock() + + module = core.module.load(module_name="test", config=config) + + assert module.__class__.__name__ == "Error" + assert module.widget().full_text() == "test: some-error" + + +def test_loadvalid_module(): + module = core.module.load(module_name="test") + assert module.__class__.__module__ == "modules.core.test" + assert module.__class__.__name__ == "Module" + assert module.state(None) == [] + + +def test_empty_widgets(): + module = core.module.Module(widgets=[]) + assert module.widgets() == [] + + +def test_error_widget(): + cfg = core.config.Config(shlex.split("-p test_module.foo=5")) + module = core.module.Error("test-mod", "xyz", config=cfg) + full_text = module.full_text(module.widget()) + + assert module.state(None) == ["critical"] + assert "test-mod" in full_text + assert "xyz" in full_text + + +def test_single_widget(widget_a): + module = core.module.Module(widgets=widget_a) + assert module.widgets() == [widget_a] + + +def test_widget_list(widget_a, widget_b): + module = core.module.Module(widgets=[widget_a, widget_b]) + assert module.widgets() == [widget_a, widget_b] + + +def test_module_Name(): + module = SampleModule() + assert module.name == "test_module" + assert module.module_name == "test_module" + + +def testvalid_parameter(): + cfg = core.config.Config(shlex.split("-p test_module.foo=5")) + module = SampleModule(config=cfg) + assert module.parameter("foo") == "5" + + +def test_default_parameter(empty_config): + module = SampleModule(config=empty_config) + assert module.parameter("foo", "default") == "default" + + +def test_default_is_none(empty_config): + module = SampleModule(config=empty_config) + assert module.parameter("foo") == None + + +def test_error_widget(empty_config): + module = SampleModule(config=empty_config) + module.fail = True + module.error = "!!" + module.update_wrapper() + assert len(module.widgets()) == 1 + assert module.widget().full_text() == "error: !!" + + +def test_get_widget_by_name(empty_config, widget_a, widget_b): + module = SampleModule(config=empty_config, widgets=[widget_a, widget_b]) + + assert module.widget(widget_a.name) == widget_a + assert module.widget(widget_b.name) == widget_b + assert module.widget("i-do-not-exist") == None + assert module.widget() == widget_a + + +def test_default_thresholds(empty_config, widget_a, widget_b): + module = SampleModule(config=empty_config, widgets=[widget_a, widget_b]) + + assert module.threshold_state(100, 80, 99) == "critical" + assert module.threshold_state(100, 80, 100) == "warning" + assert module.threshold_state(81, 80, 100) == "warning" + assert module.threshold_state(80, 80, 100) == None + assert module.threshold_state(10, 80, 100) == None + + +def test_configured_callbacks(mocker, empty_config, widget_a, widget_b): + module = SampleModule(config=empty_config, widgets=[widget_a, widget_b]) + + cmd = "sample-tool arg1 arg2 arg3" + module.set("left-click", cmd) + module.register_callbacks() + + cli = mocker.patch("core.input.util.cli") + cli.execute.return_value = "" + core.input.trigger( + {"button": core.input.LEFT_MOUSE, "instance": module.id,} ) - def test_importerror(self): - with unittest.mock.patch("core.module.importlib") as importlib: - importlib.import_module.side_effect = ImportError("some-error") - config = unittest.mock.MagicMock() - module = core.module.load(module_name=self.validModuleName, config=config) - module.widget().full_text() - self.assertEqual( - "Error", - module.__class__.__name__, - "an invalid module must be a core.module.Error", - ) - self.assertEqual(module.widget().full_text(), "test: some-error") + cli.execute.assert_called_once_with(cmd, wait=False, shell=True) - def test_loadvalid_module(self): - module = core.module.load(module_name=self.validModuleName) - self.assertEqual( - "modules.core.{}".format(self.validModuleName), - module.__class__.__module__, - "module must be a modules.core. object", - ) - self.assertEqual( - "Module", - module.__class__.__name__, - "a valid module must have a Module class", - ) - self.assertEqual([], module.state(None), "default state of module is empty") - def test_empty_widgets(self): - module = core.module.Module(widgets=[]) - self.assertEqual([], module.widgets()) +def test_configured_callbacks_with_parameters(mocker, empty_config, widget_a): + module = SampleModule(config=empty_config, widgets=[widget_a]) - def test_error_widget(self): - cfg = core.config.Config(shlex.split("-p test_module.foo=5")) - module = core.module.Error(cfg, "test-mod", "xyz") - self.assertEqual( - ["critical"], module.state(None), "error module must have critical state" - ) - full_text = module.full_text(module.widget()) - self.assertTrue("test-mod" in full_text) - self.assertTrue("xyz" in full_text) + cmd = "sample-tool {instance} {name}" + module.set("left-click", cmd) + module.register_callbacks() - def test_single_widget(self): - module = core.module.Module(widgets=self.someWidget) - self.assertEqual([self.someWidget], module.widgets()) + cli = mocker.patch("core.input.util.cli") + cli.execute.return_value = "" + core.input.trigger( + {"button": core.input.LEFT_MOUSE, "instance": module.id, "name": "sample-name",} + ) - def test_widget_list(self): - module = core.module.Module(widgets=[self.someWidget, self.anotherWidget]) - self.assertEqual([self.someWidget, self.anotherWidget], module.widgets()) - - def test_module_Name(self): - module = TestModule() - self.assertEqual("test_module", module.name, "module has wrong name") - self.assertEqual("test_module", module.module_name, "module has wrong name") - - def testvalid_parameter(self): - cfg = core.config.Config(shlex.split("-p test_module.foo=5")) - module = TestModule(config=cfg) - self.assertEqual(5, int(module.parameter("foo"))) - - def test_default_parameter(self): - cfg = core.config.Config([]) - module = TestModule(config=cfg) - self.assertEqual("default", module.parameter("foo", "default")) - - def test_default_is_none(self): - cfg = core.config.Config([]) - module = TestModule(config=cfg) - self.assertEqual(None, module.parameter("foo")) - - def test_error_widget(self): - cfg = core.config.Config([]) - module = TestModule(config=cfg) - module.fail = True - module.error = "!!" - module.update_wrapper() - self.assertEqual(1, len(module.widgets())) - self.assertEqual("error: !!", module.widget().full_text()) - - def test_get_widget_by_name(self): - cfg = core.config.Config([]) - module = TestModule(config=cfg, widgets=[self.someWidget, self.anotherWidget]) - - self.assertEqual(self.someWidget, module.widget(self.someWidget.name)) - self.assertEqual(self.anotherWidget, module.widget(self.anotherWidget.name)) - self.assertEqual(None, module.widget(self.unusedWidgetName)) - self.assertEqual(self.someWidget, module.widget()) - - def test_default_thresholds(self): - cfg = core.config.Config([]) - module = TestModule(config=cfg, widgets=[self.someWidget, self.anotherWidget]) - - self.assertEqual("critical", module.threshold_state(100, 80, 99)) - self.assertEqual("warning", module.threshold_state(100, 80, 100)) - self.assertEqual("warning", module.threshold_state(81, 80, 100)) - self.assertEqual(None, module.threshold_state(80, 80, 100)) - self.assertEqual(None, module.threshold_state(10, 80, 100)) - - def test_configured_callbacks(self): - cfg = core.config.Config([]) - module = TestModule(config=cfg, widgets=[self.someWidget, self.anotherWidget]) - - cmd = "sample-tool arg1 arg2 arg3" - module.set("left-click", cmd) - module.register_callbacks() - - with unittest.mock.patch("core.input.util.cli") as cli: - cli.execute.return_value = "" - core.input.trigger( - {"button": core.input.LEFT_MOUSE, "instance": module.id,} - ) - - cli.execute.assert_called_once_with(cmd, wait=False, shell=True) - - def test_configured_callbacks_with_parameters(self): - cfg = core.config.Config([]) - module = TestModule(config=cfg, widgets=[self.someWidget]) - - cmd = "sample-tool {instance} {name}" - module.set("left-click", cmd) - module.register_callbacks() - - with unittest.mock.patch("core.input.util.cli") as cli: - cli.execute.return_value = "" - core.input.trigger( - { - "button": core.input.LEFT_MOUSE, - "instance": module.id, - "name": "sample-name", - } - ) - - cli.execute.assert_called_once_with( - cmd.format(instance=module.id, name="sample-name"), - wait=False, - shell=True, - ) + cli.execute.assert_called_once_with( + cmd.format(instance=module.id, name="sample-name"), wait=False, shell=True, + ) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_output.py b/tests/core/test_output.py index 724e05e..69c8b15 100644 --- a/tests/core/test_output.py +++ b/tests/core/test_output.py @@ -1,162 +1,173 @@ import json -import unittest +import pytest +import core.event import core.config import core.output import core.module -class TestModule(core.module.Module): +class SampleModule(core.module.Module): pass +@pytest.fixture(autouse=True) +def clear_events(): + core.event.clear() -class i3(unittest.TestCase): - def setUp(self): - self.i3 = core.output.i3() - widget = unittest.mock.MagicMock() - widget.full_text.return_value = "test" - self.someModule = TestModule( - config=core.config.Config([]), widgets=[widget, widget, widget] - ) - self.paddedTheme = core.theme.Theme(raw_data={"defaults": {"padding": " "}}) - self.separator = "***" - self.separatorTheme = core.theme.Theme( - raw_data={ - "defaults": {"separator": self.separator, "fg": "red", "bg": "blue"} - } - ) - self.someBlock = core.output.block( - theme=self.separatorTheme, - module=self.someModule, - widget=self.someModule.widget(), - ) +@pytest.fixture +def i3(): + return core.output.i3() - def test_start(self): - core.event.clear() +@pytest.fixture +def module_a(mocker): + widget = mocker.MagicMock() + widget.full_text.return_value = "test" + return SampleModule( + config=core.config.Config([]), widgets=[widget, widget, widget] + ) - all_data = self.i3.start() - data = all_data["blocks"] - self.assertEqual(1, data["version"], "i3bar protocol version 1 expected") - self.assertTrue(data["click_events"], "click events should be enabled") - self.assertEqual("\n[", all_data["suffix"]) +@pytest.fixture +def paddedTheme(): + return core.theme.Theme(raw_data={"defaults": {"padding": " "}}) - def test_stop(self): - self.assertEqual( - "\n]", self.i3.stop()["suffix"], "wrong i3bar protocol during stop" - ) +@pytest.fixture +def separatorTheme(): + return core.theme.Theme( + raw_data={ + "defaults": {"separator": "***", "fg": "red", "bg": "blue"} + } + ) - def test_no_modules_by_default(self): - self.assertEqual( - 0, len(self.i3.modules()), "module list should be empty by default" - ) +@pytest.fixture +def block_a(separatorTheme, module_a): + return core.output.block( + theme=separatorTheme, + module=module_a, + widget=module_a.widget(), + ) - def test_register_single_module(self): - self.i3.modules(self.someModule) - self.assertEqual( - 1, len(self.i3.modules()), "setting single module does not work" - ) +#def setUp(self): +# self.i3 = core.output.i3() +# widget = unittest.mock.MagicMock() +# widget.full_text.return_value = "test" +# self.someModule = SampleModule( +# config=core.config.Config([]), widgets=[widget, widget, widget] +# ) +# self.separator = "***" +# +def test_start(i3): + all_data = i3.start() + data = all_data["blocks"] - def test_register_multiple_modules(self): - self.i3.modules([self.someModule, self.someModule, self.someModule]) - self.assertEqual(3, len(self.i3.modules()), "setting module list does not work") + assert data["version"] == 1 + assert data["click_events"] == True + assert all_data["suffix"] == "\n[" - def test_draw_existing_module(self): - self.i3.test_draw = unittest.mock.MagicMock( - return_value={"blocks": {"test": True}, "suffix": "end"} - ) - self.i3.draw("test_draw") - self.i3.test_draw.assert_called_once_with() +def test_stop(i3): + assert i3.stop()["suffix"] == "\n]" - def test_empty_status_line(self): - data = self.i3.statusline() - self.assertEqual( - [], data["blocks"], "expected empty list of status line entries" - ) - self.assertEqual(",", data["suffix"], 'expected "," as suffix') +def test_no_modules_by_default(i3): + assert i3.modules() == [] - def test_statusline(self): - self.i3.modules([self.someModule, self.someModule, self.someModule]) - self.i3.update() - data = self.i3.statusline() - self.assertEqual( - len(self.someModule.widgets()) * 3, - len(data["blocks"]), - "wrong number of widgets", - ) +def test_register_single_module(i3, module_a): + i3.modules(module_a) - def test_padding(self): - self.i3.theme(self.paddedTheme) - blk = core.output.block( - self.i3.theme(), self.someModule, self.someModule.widget() - ) - blk.set("full_text", "abc") - result = blk.dict()["full_text"] - self.assertEqual(" abc ", result) + assert i3.modules() == [module_a] - def test_no_separator(self): - result = self.i3.separator_block(self.someModule, self.someModule.widget()) - self.assertEqual([], result) +def test_register_multiple_modules(i3, module_a): + i3.modules([module_a, module_a, module_a]) + assert i3.modules() == [module_a, module_a, module_a] - def test_separator(self): - self.i3.theme(self.separatorTheme) - result = self.i3.separator_block(self.someModule, self.someModule.widget()) - self.assertEqual(1, len(result)) - self.assertEqual("***", result[0].dict()["full_text"]) - self.assertTrue(result[0].dict().get("_decorator", False)) - self.assertEqual( - self.separatorTheme.get("bg", self.someModule.widget()), - result[0].dict()["color"], - ) +def test_draw_existing_module(mocker, i3): + i3.test_draw = mocker.MagicMock( + return_value={"blocks": {"test": True}, "suffix": "end"} + ) + i3.draw("test_draw") + i3.test_draw.assert_called_once_with() - def test_dump_json(self): - obj = unittest.mock.MagicMock() - obj.dict = unittest.mock.MagicMock() - core.output.dump_json(obj) - obj.dict_assert_called_once_with() +def test_empty_status_line(i3): + data = i3.statusline() - def test_assign(self): - src = {"a": "x", "b": "y", "c": "z"} - dst = {} + assert data["blocks"] == [] + assert data["suffix"] == "," - core.output.assign(src, dst, "a") - self.assertEqual(dst["a"], src["a"]) +def test_statusline(i3, module_a): + i3.modules([module_a, module_a, module_a]) + i3.update() + data = i3.statusline() + assert len(data["blocks"]) == len(module_a.widgets())*3 - core.output.assign(src, dst, "123", "b") - self.assertEqual(dst["123"], src["b"]) +def test_padding(i3, paddedTheme, module_a): + i3.theme(paddedTheme) + blk = core.output.block( + i3.theme(), module_a, module_a.widget() + ) + blk.set("full_text", "abc") + result = blk.dict()["full_text"] + assert result == " abc " - core.output.assign(src, dst, "blub", default="def") - self.assertEqual("def", dst["blub"]) +def test_no_separator(i3, module_a): + result = i3.separator_block(module_a, module_a.widget()) + assert result == [] - def test_pango_detection(self): - self.assertFalse(self.someBlock.is_pango({})) - self.assertTrue(self.someBlock.is_pango({"pango": {}})) +def test_separator(i3, separatorTheme, module_a): + i3.theme(separatorTheme) + result = i3.separator_block(module_a, module_a.widget()) - def test_pangoize(self): - self.assertEqual("test", self.someBlock.pangoize("test")) - self.assertFalse("markup" in self.someBlock.dict()) + assert len(result) == 1 + assert result[0].dict()["full_text"] == "***" + assert result[0].dict().get("_decorator") == True + assert result[0].dict()["color"] == separatorTheme.get("bg", module_a.widget()) - pango = self.someBlock.pangoize( - {"pango": {"attr": "blub", "x": "y", "full_text": "test"}} - ) - self.assertTrue('attr="blub"' in pango) - self.assertTrue('x="y"' in pango) - self.assertTrue("test" in pango) - self.assertEqual("pango", self.someBlock.dict()["markup"]) +def test_dump_json(mocker): + obj = mocker.MagicMock() + obj.dict = mocker.MagicMock() + core.output.dump_json(obj) + obj.dict_assert_called_once_with() - def test_padding(self): - self.someBlock.set("padding", "***") - self.someBlock.set("full_text", "test") +def test_assign(): + src = {"a": "x", "b": "y", "c": "z"} + dst = {} - self.assertEqual("***test***", self.someBlock.dict()["full_text"]) + core.output.assign(src, dst, "a") + assert src["a"] == dst["a"] - def test_pre_suffix(self): - self.someBlock.set("padding", "*") - self.someBlock.set("prefix", "pre") - self.someBlock.set("suffix", "suf") - self.someBlock.set("full_text", "test") + core.output.assign(src, dst, "123", "b") + assert src["b"] == dst["123"] - self.assertEqual("*pre*test*suf*", self.someBlock.dict()["full_text"]) + core.output.assign(src, dst, "blub", default="def") + assert dst["blub"] == "def" + +def test_pango_detection(block_a): + assert block_a.is_pango({}) == False + assert block_a.is_pango({ "pango": {} }) == True + +def test_pangoize(block_a): + assert block_a.pangoize("test") == "test" + assert not "markup" in block_a.dict() + + pango = block_a.pangoize( + {"pango": {"attr": "blub", "x": "y", "full_text": "test"}} + ) + assert 'attr="blub"' in pango + assert 'x="y"' in pango + assert "test" in pango + assert block_a.dict()["markup"] == "pango" + +def test_padding(block_a): + block_a.set("padding", "***") + block_a.set("full_text", "test") + + assert block_a.dict()["full_text"] == "***test***" + +def test_pre_suffix(block_a): + block_a.set("padding", "*") + block_a.set("prefix", "pre") + block_a.set("suffix", "suf") + block_a.set("full_text", "test") + + assert block_a.dict()["full_text"] == "*pre*test*suf*" # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_theme.py b/tests/core/test_theme.py index 3ed6ea0..1ec1799 100644 --- a/tests/core/test_theme.py +++ b/tests/core/test_theme.py @@ -1,4 +1,4 @@ -import unittest +import pytest import types import core.theme @@ -7,139 +7,169 @@ import core.widget import core.module -class TestModule(core.module.Module): +class SampleModule(core.module.Module): def __init__(self, widgets, config=core.config.Config([]), theme=None): super().__init__(config, theme, widgets) self.name = "test" +@pytest.fixture(autouse=True) +def clear_events(): + core.event.clear() -class theme(unittest.TestCase): - def setUp(self): - core.event.clear() - self.invalidThemeName = "this-theme-does-not-exist" - self.validThemeName = "default" - self.defaultsTheme = {"defaults": {"fg": "red", "bg": "black"}} - self.cycleTheme = { - "cycle": [ - {"fg": "red", "bg": "black"}, - {"fg": "black", "bg": "red"}, - {"fg": "white", "bg": "blue"}, - ] - } - self.colorTheme = {"colors": [{"red": "#ff0000", "blue": "#0000ff"}]} - self.walTheme = {"colors": ["wal"]} - self.cycleValueTheme = {"defaults": {"fg": ["red", "green", "blue"]}} - self.stateTheme = {"warning": {"fg": "yellow"}, "critical": {"fg": "red"}} - self.overlayTheme = { - "load": {"prefix": "a"}, - "test": {"load": {"prefix": "b"}, "prefix": "x"}, - } +@pytest.fixture +def defaultsTheme(): + return {"defaults": {"fg": "red", "bg": "black"}} - def test_invalid_theme(self): - with self.assertRaises(RuntimeError): - core.theme.Theme(self.invalidThemeName) +@pytest.fixture +def cycleTheme(): + return { + "cycle": [ + {"fg": "red", "bg": "black"}, + {"fg": "black", "bg": "red"}, + {"fg": "white", "bg": "blue"}, + ] + } - def test_valid_theme(self): - theme = core.theme.Theme(self.validThemeName) - self.assertEqual(self.validThemeName, theme.name) +@pytest.fixture +def colorTheme(): + return {"colors": [{"red": "#ff0000", "blue": "#0000ff"}]} - def test_defaults(self): - theme = core.theme.Theme(raw_data=self.defaultsTheme) - self.assertEqual(self.defaultsTheme["defaults"]["fg"], theme.get("fg")) - self.assertEqual(self.defaultsTheme["defaults"]["bg"], theme.get("bg")) +@pytest.fixture +def walTheme(): + return {"colors": ["wal"]} - def test_cycle(self): - theme = core.theme.Theme(raw_data=self.cycleTheme) - self.assertEqual(None, theme.get("prev-bg")) - self.assertEqual(self.cycleTheme["cycle"][0]["fg"], theme.get("fg")) - self.assertEqual(self.cycleTheme["cycle"][0]["bg"], theme.get("bg")) - core.event.trigger("next-widget") - self.assertEqual(self.cycleTheme["cycle"][0]["bg"], theme.get("bg", "previous")) - core.event.trigger("next-widget") - self.assertEqual(self.cycleTheme["cycle"][2]["fg"], theme.get("fg")) - self.assertEqual(self.cycleTheme["cycle"][2]["bg"], theme.get("bg")) +@pytest.fixture +def cycleValueTheme(): + return {"defaults": {"fg": ["red", "green", "blue"]}} - with unittest.mock.patch("core.output.sys.stdout"): - core.event.trigger("draw") - self.assertEqual(self.cycleTheme["cycle"][0]["fg"], theme.get("fg")) - self.assertEqual(self.cycleTheme["cycle"][0]["bg"], theme.get("bg")) +@pytest.fixture +def stateTheme(): + return {"warning": {"fg": "yellow"}, "critical": {"fg": "red"}} - def test_custom_iconset(self): - theme = core.theme.Theme(raw_data=self.defaultsTheme) - self.assertNotEqual("aaa", theme.get("padding")) - theme = core.theme.Theme( - raw_data=self.defaultsTheme, iconset={"defaults": {"padding": "aaa"}} - ) - self.assertEqual("aaa", theme.get("padding")) +@pytest.fixture +def overlayTheme(): + return { + "load": {"prefix": "a"}, + "test": {"load": {"prefix": "b"}, "prefix": "x"}, + } - def test_colors(self): - theme = core.theme.Theme(raw_data=self.defaultsTheme) - self.assertEqual({}, theme.keywords()) - theme = core.theme.Theme(raw_data=self.colorTheme) - self.assertEqual(self.colorTheme["colors"][0], theme.keywords()) +def test_invalid_theme(): + with pytest.raises(RuntimeError): + core.theme.Theme("this-theme-does-not-exist") - def test_wal_colors(self): - with unittest.mock.patch("core.theme.io") as io: - with unittest.mock.patch("core.theme.os") as os: - os.path.isfile.return_value = True - io.open.return_value = unittest.mock.MagicMock() - io.open.return_value.__enter__.return_value.read.return_value = """ - { "colors": { "red": "#ff0000" } } - """ +def test_valid_theme(): + theme = core.theme.Theme("default") + assert theme.name == "default" - theme = core.theme.Theme(raw_data=self.walTheme) - self.assertEqual({"red": "#ff0000"}, theme.keywords()) +def test_defaults(defaultsTheme): + theme = core.theme.Theme(raw_data=defaultsTheme) - def test_wal_special(self): - with unittest.mock.patch("core.theme.io") as io: - with unittest.mock.patch("core.theme.os") as os: - os.path.isfile.return_value = True - io.open.return_value.__enter__.return_value.read.return_value = """ - { "special": { "background": "#ff0000" } } - """ + assert theme.get("fg") == defaultsTheme["defaults"]["fg"] + assert theme.get("bg") == defaultsTheme["defaults"]["bg"] - theme = core.theme.Theme(raw_data=self.walTheme) - self.assertEqual({"background": "#ff0000"}, theme.keywords()) +def test_cycle(mocker, cycleTheme): + theme = core.theme.Theme(raw_data=cycleTheme) - def test_cycle_value(self): - widget = core.widget.Widget() - expected = self.cycleValueTheme["defaults"]["fg"] - theme = core.theme.Theme(raw_data=self.cycleValueTheme) + assert theme.get("bg", "previous") == None + assert theme.get("fg") == cycleTheme["cycle"][0]["fg"] + assert theme.get("bg") == cycleTheme["cycle"][0]["bg"] - for i in range(0, len(expected) * 3): - self.assertEqual(expected[i % len(expected)], theme.get("fg", widget)) - self.assertEqual( - expected[i % len(expected)], theme.get("fg", widget) - ) # ensure multiple invocations are OK - core.event.trigger("draw") + core.event.trigger("next-widget") - def test_state(self): - widget = core.widget.Widget() - theme = core.theme.Theme(raw_data=self.stateTheme) + assert theme.get("bg", "previous") == cycleTheme["cycle"][0]["bg"] - self.assertEqual(None, theme.get("fg", widget)) + core.event.trigger("next-widget") - widget.state = types.MethodType(lambda self: ["warning"], widget) - self.assertEqual(self.stateTheme["warning"]["fg"], theme.get("fg", widget)) + assert theme.get("fg") == cycleTheme["cycle"][2]["fg"] + assert theme.get("bg") == cycleTheme["cycle"][2]["bg"] - widget.state = types.MethodType(lambda self: ["critical"], widget) - self.assertEqual(self.stateTheme["critical"]["fg"], theme.get("fg", widget)) + stdout = mocker.patch("core.output.sys.stdout") - def test_overlay(self): - widget = core.widget.Widget() - module = TestModule(widget) - theme = core.theme.Theme(raw_data=self.overlayTheme) + core.event.trigger("draw") - self.assertEqual( - self.overlayTheme[module.name]["prefix"], theme.get("prefix", widget) - ) + assert theme.get("fg") == cycleTheme["cycle"][0]["fg"] + assert theme.get("bg") == cycleTheme["cycle"][0]["bg"] - widget.state = types.MethodType(lambda self: ["load"], widget) +def test_custom_iconset(defaultsTheme): + theme = core.theme.Theme(raw_data=defaultsTheme) - self.assertEqual( - self.overlayTheme[module.name]["load"]["prefix"], - theme.get("prefix", widget), - ) + assert theme.get("padding") != "aaa" + assert theme.get("fg") != "blue" + + theme = core.theme.Theme( + raw_data=defaultsTheme, iconset={"defaults": {"padding": "aaa", "fg": "blue"}} + ) + + assert theme.get("padding") == "aaa" + assert theme.get("fg") == "blue" # test override + +def test_colors(defaultsTheme, colorTheme): + theme = core.theme.Theme(raw_data=defaultsTheme) + assert theme.keywords() == {} + + theme = core.theme.Theme(raw_data=colorTheme) + assert theme.keywords() == colorTheme["colors"][0] + +def test_wal_colors(mocker, walTheme): + io = mocker.patch("core.theme.io") + os = mocker.patch("core.theme.os") + + os.path.isfile.return_value = True + io.open.return_value = mocker.MagicMock() + io.open.return_value.__enter__.return_value.read.return_value = """ + { "colors": { "red": "#ff0000" } } + """ + + theme = core.theme.Theme(raw_data=walTheme) + + assert theme.keywords() == {"red": "#ff0000"} + +def test_wal_special(mocker, walTheme): + io = mocker.patch("core.theme.io") + os = mocker.patch("core.theme.os") + + os.path.isfile.return_value = True + io.open.return_value.__enter__.return_value.read.return_value = """ + { "special": { "background": "#ff0000" } } + """ + + theme = core.theme.Theme(raw_data=walTheme) + + assert theme.keywords() == {"background": "#ff0000"} + +def test_cycle_value(cycleValueTheme): + widget = core.widget.Widget() + expected = cycleValueTheme["defaults"]["fg"] + theme = core.theme.Theme(raw_data=cycleValueTheme) + + for i in range(0, len(expected) * 3): + assert theme.get("fg", widget) == expected[i%len(expected)] + # ensure multiple invocations are OK + assert theme.get("fg", widget) == expected[i%len(expected)] + core.event.trigger("draw") + +def test_state(stateTheme): + widget = core.widget.Widget() + theme = core.theme.Theme(raw_data=stateTheme) + + assert theme.get("fg", widget) == None + + widget.state = types.MethodType(lambda self: ["warning"], widget) + assert theme.get("fg", widget) == stateTheme["warning"]["fg"] + + widget.state = types.MethodType(lambda self: ["critical"], widget) + assert theme.get("fg", widget) == stateTheme["critical"]["fg"] + +def test_overlay(overlayTheme): + widget = core.widget.Widget() + module = SampleModule(widget) + theme = core.theme.Theme(raw_data=overlayTheme) + + assert theme.get("prefix", widget) == overlayTheme[module.name]["prefix"] + + widget.state = types.MethodType(lambda self: ["load"], widget) + + assert theme.get("prefix", widget) == overlayTheme[module.name]["load"]["prefix"] # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/core/test_widget.py b/tests/core/test_widget.py index 1f5e471..9a51021 100644 --- a/tests/core/test_widget.py +++ b/tests/core/test_widget.py @@ -1,12 +1,11 @@ -import unittest -import unittest.mock +import pytest import core.widget import core.module import core.config -class TestModule(core.module.Module): +class SampleModule(core.module.Module): def __init__(self, widgets, config=core.config.Config([]), theme=None): super().__init__(config, theme, widgets) self.states = [] @@ -19,77 +18,80 @@ class TestModule(core.module.Module): def state(self, widget): return self.states +@pytest.fixture +def widget_a(): + return core.widget.Widget("some random value") -class widget(unittest.TestCase): - def setUp(self): - self.someValue = "some random value" - self.someOtherValue = "some different value" - self.callbackReturnValue = "callback return value" - self.someWidget = core.widget.Widget(full_text=self.someValue) - self.someCallback = unittest.mock.MagicMock( - return_value=self.callbackReturnValue - ) +#class widget(unittest.TestCase): +# def setUp(self): +# self.someValue = "some random value" +# self.someOtherValue = "some different value" +# self.callbackReturnValue = "callback return value" +# self.someWidget = core.widget.Widget(full_text=self.someValue) +# self.someCallback = unittest.mock.MagicMock( +# return_value=self.callbackReturnValue +# ) +# +# self.assertNotEqual(self.someValue, self.someOtherValue) - self.assertNotEqual(self.someValue, self.someOtherValue) +def test_text_fulltext(): + widget = core.widget.Widget(full_text="this is some value") + assert widget.full_text() == "this is some value" - def tearDown(self): - pass +def test_set_fulltext(widget_a): + assert widget_a.full_text() != "new value" + widget_a.full_text("new value") + assert widget_a.full_text() == "new value" - def test_text_fulltext(self): - newWidget = core.widget.Widget(full_text=self.someValue) - self.assertEqual(self.someValue, newWidget.full_text()) +def test_callable_fulltext(mocker): + callback = mocker.MagicMock(return_value="callback returns") + widget = core.widget.Widget(full_text=callback) + assert widget.full_text() == "callback returns" + callback.assert_called_once_with(widget) - def test_set_fulltext(self): - self.assertNotEqual(self.someOtherValue, self.someWidget.full_text()) - self.someWidget.full_text(self.someOtherValue) - self.assertEqual(self.someOtherValue, self.someWidget.full_text()) +def test_set_callable_fulltext(mocker, widget_a): + callback = mocker.MagicMock(return_value="this is a test") + widget_a.full_text(callback) + assert widget_a.full_text() == "this is a test" + callback.assert_called_once_with(widget_a) - def test_callable_fulltext(self): - newWidget = core.widget.Widget(full_text=self.someCallback) - self.assertEqual(newWidget.full_text(), self.callbackReturnValue) - self.someCallback.assert_called_once_with(newWidget) +def test_state_defaults_to_empty(widget_a): + assert widget_a.state() == [] - def test_set_callable_fulltext(self): - self.someWidget.full_text(self.someCallback) - self.assertEqual(self.someWidget.full_text(), self.callbackReturnValue) - self.someCallback.assert_called_once_with(self.someWidget) +def test_single_widget_state(widget_a): + widget_a.set("state", "state1") + assert widget_a.state() == ["state1"] - def test_state_defaults_to_empty(self): - self.assertEqual([], self.someWidget.state()) +def test_multiple_widget_states(widget_a): + widget_a.set("state", ["state1", "state2"]) + assert widget_a.state() == ["state1", "state2"] - def test_single_widget_state(self): - self.someWidget.set("state", "state1") - self.assertEqual(["state1"], self.someWidget.state()) +def test_widget_module_state(widget_a): + module = SampleModule(widgets=widget_a) + widget_a.set("state", ["state1", "state2"]) - def test_multiple_widget_states(self): - self.someWidget.set("state", ["state1", "state2"]) - self.assertEqual(["state1", "state2"], self.someWidget.state()) + module.states = "x" + assert widget_a.state() == ["state1", "state2", "x"] - def test_widget_module_state(self): - module = TestModule(widgets=self.someWidget) - self.someWidget.set("state", ["state1", "state2"]) + module.states = ["a", "b"] + assert widget_a.state() == ["state1", "state2", "a", "b"] - module.states = "x" - self.assertEqual(["state1", "state2", "x"], self.someWidget.state()) - module.states = ["a", "b"] - self.assertEqual(["state1", "state2", "a", "b"], self.someWidget.state()) +def test_multiple_widget_themes(): + widget1 = core.widget.Widget(full_text="a") + widget2 = core.widget.Widget(full_text="b") + widget3 = core.widget.Widget(full_text="c") - def test_multiple_widget_themes(self): - widget1 = core.widget.Widget(full_text="a") - widget2 = core.widget.Widget(full_text="b") - widget3 = core.widget.Widget(full_text="c") + module = SampleModule(widgets=[widget1, widget2, widget3]) + module.set("theme.test", "1,2,3") + module.set("theme.test2", "x") - module = TestModule(widgets=[widget1, widget2, widget3]) - module.set("theme.test", "1,2,3") - module.set("theme.test2", "x") + assert widget1.theme("test") == "1" + assert widget2.theme("test") == "2" + assert widget3.theme("test") == "3" - self.assertEqual("1", widget1.theme("test")) - self.assertEqual("2", widget2.theme("test")) - self.assertEqual("3", widget3.theme("test")) - - self.assertEqual("x", widget1.theme("test2")) - self.assertEqual(None, widget2.theme("test2")) - self.assertEqual(None, widget3.theme("test2")) + assert widget1.theme("test2") == "x" + assert widget2.theme("test2") == None + assert widget3.theme("test2") == None # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/pytests/core/__init__.py b/tests/modules/contrib/__init__.py similarity index 100% rename from pytests/core/__init__.py rename to tests/modules/contrib/__init__.py diff --git a/pytests/modules/contrib/test_kernel.py b/tests/modules/contrib/test_kernel.py similarity index 100% rename from pytests/modules/contrib/test_kernel.py rename to tests/modules/contrib/test_kernel.py diff --git a/pytests/modules/contrib/test_mpd.py b/tests/modules/contrib/test_mpd.py similarity index 100% rename from pytests/modules/contrib/test_mpd.py rename to tests/modules/contrib/test_mpd.py diff --git a/tests/modules/test_kernel.py b/tests/modules/test_kernel.py deleted file mode 100644 index 27b9350..0000000 --- a/tests/modules/test_kernel.py +++ /dev/null @@ -1,21 +0,0 @@ -import unittest - -import core.config -import modules.contrib.kernel - - -class kernel(unittest.TestCase): - def setUp(self): - self.someKernel = "this-is-my-kernel" - self.module = modules.contrib.kernel.Module( - config=core.config.Config([]), theme=None - ) - - def test_full_text(self): - with unittest.mock.patch("modules.contrib.kernel.platform") as platform: - platform.release.return_value = self.someKernel - self.assertEqual(1, len(self.module.widgets())) - self.assertEqual(self.someKernel, self.module.widget().full_text()) - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util/__init__.py b/tests/util/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/util/test_algorithm.py b/tests/util/test_algorithm.py index 8fcc419..617187c 100644 --- a/tests/util/test_algorithm.py +++ b/tests/util/test_algorithm.py @@ -1,42 +1,50 @@ -import unittest +import pytest from util.algorithm import * +@pytest.fixture +def someData(): + return {"a": 100, "b": 200, "c": [1, 2, 3]} -class algorithm(unittest.TestCase): - def setUp(self): - self.someData = {"a": 100, "b": 200, "c": [1, 2, 3]} - self.differentData = {"x": 20, "y": "bla", "z": ["a", "b"]} - self.moreData = {"n": 100} - self.overlapData = {"a": 200, "c": [1, 2, 4]} +@pytest.fixture +def differentData(): + return {"x": 20, "y": "bla", "z": ["a", "b"]} - def test_merge_with_empty(self): - self.assertEqual(self.someData, merge(self.someData, {})) - self.assertEqual(None, merge(self.someData, None)) +@pytest.fixture +def moreData(): + return {"n": 100} - def test_merge_no_overwrite(self): - result = merge(self.someData, self.differentData) - for k in self.someData: - self.assertEqual(result[k], self.someData[k]) +@pytest.fixture +def overlapData(): + return {"a": 200, "c": [1, 2, 4]} + +def test_merge_with_empty(someData): + assert merge(someData, {}) == someData + assert merge(someData, None) == None + + def test_merge_no_overwrite(someData, differentData): + result = merge(someData, differentData) + for k in someData: + assert someData[k] == result[k] for k in self.differentData: - self.assertEqual(result[k], self.differentData[k]) + assert differentData[k] == result[k] - def test_merge_multiple(self): - result = merge(self.someData, self.differentData, self.moreData) - for k in self.someData: - self.assertEqual(result[k], self.someData[k]) - for k in self.differentData: - self.assertEqual(result[k], self.differentData[k]) - for k in self.moreData: - self.assertEqual(result[k], self.moreData[k]) + def test_merge_multiple(someData, differentData, moreData): + result = merge(someData, differentData, moreData) + for k in someData: + assert someData[k] == result[k] + for k in differentData: + assert differentData[k] == result[k] + for k in moreData: + assert moreData[k] == result[k] - def merge_overlap(self): - result = merge(self.someData, self.overlapData) - for k in self.someData: + def merge_overlap(someData, overlapData): + result = merge(someData, overlapData) + for k in someData: if not k in self.overlapData: - self.assertEqual(result[k], self.someData[k]) + assert someData[k] == result[k] for k in self.overlapData: - self.assertEqual(result[k], self.overlapData[k]) + assert overlapData[k] == result[k] # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util/test_cli.py b/tests/util/test_cli.py index 0e4bd5c..b2d8f81 100644 --- a/tests/util/test_cli.py +++ b/tests/util/test_cli.py @@ -1,43 +1,27 @@ -import unittest +import pytest import util.cli +def test_valid_command(): + assert util.cli.execute("echo test") == "test\n" -class cli(unittest.TestCase): - def setUp(self): - self.nonExistentCommand = "i-do-not-exist" - self.validCommand = "echo test" - self.validCommandOutput = "test\n" - self.utfCommand = "echo ÖPmŧß" - self.utfCommandOutput = "ÖPmŧß\n" +def test_utf_command(): + rv = util.cli.execute("echo ÖPmŧß") + assert util.cli.execute("echo ÖPmŧß") == "ÖPmŧß\n" - def test_valid_command(self): - rv = util.cli.execute(self.validCommand) - self.assertEqual(self.validCommandOutput, rv) +def test_invalid_command(): + with pytest.raises(RuntimeError): + util.cli.execute("i-do-not-exist") - def test_utf_command(self): - rv = util.cli.execute(self.utfCommand) - self.assertEqual(self.utfCommandOutput, rv) +def test_command_exit_code(): + with pytest.raises(RuntimeError): + util.cli.execute("cat i-do-not-exist") - def test_invalid_command(self): - with self.assertRaises(RuntimeError): - util.cli.execute(self.nonExistentCommand) +def test_command_exit_code_no_error(): + util.cli.execute("cat i-do-not-exist", ignore_errors=True) - def test_command_exit_code(self): - with self.assertRaises(RuntimeError): - util.cli.execute("cat {}".format(self.nonExistentCommand)) - - def test_command_exit_code_no_error(self): - try: - util.cli.execute( - "cat {}".format(self.nonExistentCommand), ignore_errors=True - ) - except Exception: - self.fail("exception was thrown") - - def test_async(self): - rv = util.cli.execute(self.validCommand, wait=False) - self.assertEqual("", rv) +def test_async(): + assert util.cli.execute("echo test", wait=False) == "" # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util/test_format.py b/tests/util/test_format.py index e50cf00..4dda6e9 100644 --- a/tests/util/test_format.py +++ b/tests/util/test_format.py @@ -1,103 +1,113 @@ -import unittest +import pytest from util.format import * -class format(unittest.TestCase): - def test_int_from_string(self): - self.assertEqual(100, asint("100")) - self.assertEqual(-100, asint("-100")) - self.assertEqual(0, asint("0")) +def test_int_from_string(): + assert asint("100") == 100 + assert asint("-100") == -100 + assert asint("0") == 0 - def test_int_from_none(self): - self.assertEqual(0, asint(None)) - def test_int_from_int(self): - self.assertEqual(100, asint(100)) - self.assertEqual(-100, asint(-100)) - self.assertEqual(0, asint(0)) +def test_int_from_none(): + assert asint(None) == 0 - def test_int_minimum(self): - self.assertEqual(100, asint(100, minimum=10)) - self.assertEqual(100, asint(100, minimum=100)) - self.assertEqual(10, asint(5, minimum=10)) - def test_int_maximum(self): - self.assertEqual(100, asint(100, maximum=200)) - self.assertEqual(100, asint(100, maximum=100)) - self.assertEqual(100, asint(200, maximum=100)) +def test_int_from_int(): + assert asint(100) == 100 + assert asint(-100) == -100 + assert asint(0) == 0 - def test_true_from_str(self): - self.assertTrue(asbool("true")) - self.assertTrue(asbool(True)) - self.assertTrue(asbool("t")) - self.assertTrue(asbool("1")) - self.assertTrue(asbool("yes")) - self.assertTrue(asbool("y")) - self.assertTrue(asbool("on")) - def test_false_from_str(self): - self.assertFalse(asbool("false")) - self.assertFalse(asbool(False)) - self.assertFalse(asbool("f")) - self.assertFalse(asbool("0")) - self.assertFalse(asbool("no")) - self.assertFalse(asbool("n")) - self.assertFalse(asbool("off")) - self.assertFalse(asbool(None)) +def test_int_minimum(): + assert asint(100, minimum=10) == 100 + assert asint(100, minimum=100) == 100 + assert asint(5, minimum=10) == 10 - def test_list_from_None(self): - self.assertEqual([], aslist(None)) - def test_list_from_list(self): - self.assertEqual([1, 2, 3], aslist([1, 2, 3])) +def test_int_maximum(): + assert asint(100, maximum=200) == 100 + assert asint(100, maximum=100) == 100 + assert asint(200, maximum=100) == 100 - def test_list_from_str(self): - self.assertEqual(["12", "13", "14"], aslist("12,13,14")) - def test_byteformat(self): - self.assertEqual("500.00B", byte(500)) - self.assertEqual("1.00KiB", byte(1024)) - self.assertEqual("1KiB", byte(1024, "{:.0f}")) - self.assertEqual("1.50KiB", byte(1024 + 512)) - self.assertEqual("2.50MiB", byte(1024 * 1024 * 2 + 1024 * 512)) - self.assertEqual("4.50GiB", byte(1024 * 1024 * 1024 * 4 + 1024 * 1024 * 512)) - self.assertEqual("2048.00GiB", byte(1024 * 1024 * 1024 * 1024 * 2)) +def test_true_from_str(): + assert asbool("true") == True + assert asbool(True) == True + assert asbool("t") == True + assert asbool("1") == True + assert asbool("yes") == True + assert asbool("y") == True + assert asbool("on") == True - def test_duration(self): - self.assertEqual("04:20:00", duration(4 * 60 * 60 + 20 * 60)) - self.assertEqual("04:20:00h", duration(4 * 60 * 60 + 20 * 60, unit=True)) - self.assertEqual( - "04:20h", duration(4 * 60 * 60 + 20 * 60, compact=True, unit=True) - ) - self.assertEqual("20:00", duration(20 * 60)) - self.assertEqual("20:00m", duration(20 * 60, unit=True)) - self.assertEqual("20:00m", duration(20 * 60, compact=True, unit=True)) +def test_false_from_str(): + assert asbool("false") == False + assert asbool(False) == False + assert asbool("f") == False + assert asbool("0") == False + assert asbool("no") == False + assert asbool("n") == False + assert asbool("off") == False + assert asbool(None) == False - self.assertEqual("00:20", duration(20)) - self.assertEqual("00:20m", duration(20, unit=True)) - self.assertEqual("00:20m", duration(20, compact=True, unit=True)) - self.assertEqual("n/a", duration(-1)) +def test_list_from_None(): + assert aslist(None) == [] - def test_seconds(self): - self.assertEqual(10, seconds(10)) - self.assertEqual(10, seconds("10")) - self.assertEqual(300, seconds("5m")) - self.assertEqual(320, seconds("5m20s")) +def test_list_from_list(): + assert aslist([1, 2, 3] == [1, 2, 3]) - self.assertEqual(4 * 3600, seconds("4h")) - self.assertEqual(4 * 3600 + 5 * 60 + 22, seconds("4h5m22s")) - self.assertEqual(4 * 3600 + 5 * 60, seconds("4h5m")) +def test_list_from_str(): + assert aslist("12,13,14") == ["12", "13", "14"] - def test_temperature(self): - self.assertEqual("10°C", astemperature(10)) - self.assertEqual("10°C", astemperature(10, "metric")) - self.assertEqual("-100°F", astemperature(-100, "imperial")) - self.assertEqual("-100°K", astemperature("-100", "kelvin")) + +def test_byteformat(): + assert byte(500) == "500.00B" + assert byte(1024) == "1.00KiB" + assert byte(1024, "{:.0f}") == "1KiB" + assert byte(1024 + 512) == "1.50KiB" + assert byte(1024 * 1024 * 2 + 1024 * 512) == "2.50MiB" + assert byte(1024 * 1024 * 1024 * 4 + 1024 * 1024 * 512) == "4.50GiB" + assert byte(1024 * 1024 * 1024 * 1024 * 2) == "2048.00GiB" + + +def test_duration(): + assert duration(4 * 60 * 60 + 20 * 60) == "04:20:00" + assert duration(4 * 60 * 60 + 20 * 60, unit=True) == "04:20:00h" + assert duration(4 * 60 * 60 + 20 * 60, compact=True, unit=True) == "04:20h" + + assert duration(20 * 60) == "20:00" + assert duration(20 * 60, unit=True) == "20:00m" + assert duration(20 * 60, compact=True, unit=True) == "20:00m" + + assert duration(20) == "00:20" + assert duration(20, unit=True) == "00:20m" + assert duration(20, compact=True, unit=True) == "00:20m" + + assert duration(-1) == "n/a" + + +def test_seconds(): + assert seconds(10) == 10 + assert seconds("10") == 10 + + assert seconds("5m") == 300 + assert seconds("5m20s") == 320 + + assert seconds("4h") == 4 * 3600 + assert seconds("4h5m22s") == 4 * 3600 + 5 * 60 + 22 + + assert seconds("4h5m") == 4 * 3600 + 5 * 60 + + +def test_temperature(): + assert astemperature(10) == "10°C" + assert astemperature(10, "metric") == "10°C" + assert astemperature(-100, "imperial") == "-100°F" + assert astemperature(-100, "kelvin") == "-100°K" # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util/test_location.py b/tests/util/test_location.py index 5792f95..21dd2e2 100644 --- a/tests/util/test_location.py +++ b/tests/util/test_location.py @@ -1,51 +1,57 @@ -import unittest +import pytest import json -import urllib.request import util.location -class location(unittest.TestCase): - def setUp(self): - patcher = unittest.mock.patch("util.location.urllib.request") - self.addCleanup(patcher.stop) - self.request = patcher.start() - util.location.reset() +@pytest.fixture +def urllib_req(mocker): + util.location.reset() + return mocker.patch("util.location.urllib.request") - self.primary = { - "country": "Middle Earth", - "longitude": "10.0", - "latitude": "20.5", - "ip": "127.0.0.1", - } - self.secondary = { - "country_name": "Rivia", - "longitude": "-10.0", - "latitude": "-23", - "ip": "127.0.0.6", - } - def test_primary_provider(self): - self.request.urlopen.return_value.read.return_value = json.dumps(self.primary) - util.location.country() - self.assertEqual(self.primary["country"], util.location.country()) - self.assertEqual( - (self.primary["latitude"], self.primary["longitude"]), - util.location.coordinates(), - ) - self.assertEqual(self.primary["ip"], util.location.public_ip()) +@pytest.fixture +def primaryLocation(): + return { + "country": "Middle Earth", + "longitude": "10.0", + "latitude": "20.5", + "ip": "127.0.0.1", + } - def test_secondary_provider(self): - urlopen = unittest.mock.MagicMock() - urlopen.read.return_value = json.dumps(self.secondary) - self.request.urlopen.side_effect = [RuntimeError(), urlopen] - self.assertEqual(self.secondary["country_name"], util.location.country()) - self.assertEqual( - (self.secondary["latitude"], self.secondary["longitude"]), - util.location.coordinates(), - ) - self.assertEqual(self.secondary["ip"], util.location.public_ip()) +@pytest.fixture +def secondaryLocation(): + return { + "country_name": "Rivia", + "longitude": "-10.0", + "latitude": "-23", + "ip": "127.0.0.6", + } + + +def test_primary_provider(urllib_req, primaryLocation): + urllib_req.urlopen.return_value.read.return_value = json.dumps(primaryLocation) + + assert util.location.country() == primaryLocation["country"] + assert util.location.coordinates() == ( + primaryLocation["latitude"], + primaryLocation["longitude"], + ) + assert util.location.public_ip() == primaryLocation["ip"] + + +def test_secondary_provider(mocker, urllib_req, secondaryLocation): + urlopen = mocker.MagicMock() + urlopen.read.return_value = json.dumps(secondaryLocation) + urllib_req.urlopen.side_effect = [RuntimeError(), urlopen] + + assert util.location.country() == secondaryLocation["country_name"] + assert util.location.coordinates() == ( + secondaryLocation["latitude"], + secondaryLocation["longitude"], + ) + assert util.location.public_ip() == secondaryLocation["ip"] # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util/test_store.py b/tests/util/test_store.py index 97b1a13..9128edd 100644 --- a/tests/util/test_store.py +++ b/tests/util/test_store.py @@ -1,62 +1,48 @@ -import unittest +import pytest import util.store -class store(unittest.TestCase): - def setUp(self): - self.store = util.store.Store() +@pytest.fixture +def emptyStore(): + return util.store.Store() - self.unusedKey = "someRandomUnusedKey" - self.someKey = "someRandomKey" - self.someOtherKey = "anotherRandomKey" - self.someValue = "someRandomValue" - self.someOtherValue = "anotherRandomValue" - def test_get_of_unset_key(self): - self.assertEqual( - None, self.store.get(self.unusedKey), "default value expected to be None" - ) - self.assertEqual( - self.someValue, - self.store.get(self.unusedKey, self.someValue), - "wrong user-provided default value returned", - ) +@pytest.fixture +def store(): + return util.store.Store() - def test_get_of_set_key(self): - self.assertNotEqual(self.someValue, None) - self.store.set(self.someKey, self.someValue) - self.assertEqual( - self.someValue, - self.store.get(self.someKey), - "unexpected value for existing key", - ) +def test_get_of_unset_key(emptyStore): + assert emptyStore.get("any-key") == None + assert emptyStore.get("any-key", "default-value") == "default-value" - def test_overwrite_set(self): - self.assertNotEqual(self.someValue, None) - self.assertNotEqual(self.someOtherValue, self.someValue) - self.store.set(self.someKey, self.someValue) - self.store.set(self.someKey, self.someOtherValue) - self.assertEqual( - self.someOtherValue, - self.store.get(self.someKey), - "unexpected value for existing key", - ) +def test_get_of_set_key(store): + store.set("key", "value") + assert store.get("key") == "value" - def test_unused_keys(self): - self.assertNotEqual(self.someKey, self.someOtherKey) - self.store.set(self.someKey, self.someValue) - self.store.set(self.someOtherKey, self.someOtherValue) +def test_overwrite_set(store): + store.set("key", "value 1") + store.set("key", "value 2") - self.assertEqual( - sorted(self.store.unused_keys()), sorted([self.someKey, self.someOtherKey]) - ) + assert store.get("key") == "value 2" - self.store.get(self.someKey) - self.assertEqual(self.store.unused_keys(), [self.someOtherKey]) + +def test_unused_keys(store): + store.set("key 1", "value x") + store.set("key 2", "value y") + + assert store.unused_keys() == sorted(["key 1", "key 2"]) + + store.get("key 2") + + assert store.unused_keys() == ["key 1"] + + store.get("key 1") + + assert store.unused_keys() == [] # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4