diff --git a/README.md b/README.md index d75b8581..4730337e 100644 --- a/README.md +++ b/README.md @@ -172,3 +172,7 @@ sudo reboot It will take about a minute after the Pi is powered on for the GUI to launch -- be patient! _Reminder: If you used option #2, [return the guide](docs/usb_relay.md) to remove the internet access over USB configuration._ + + +## Run the tests +see: [tests/README.md](tests/README.md) diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..de19c9f0 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +testpaths = tests \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..66fa1c99 --- /dev/null +++ b/setup.py @@ -0,0 +1,26 @@ +import setuptools + +with open("README.md", "r", encoding="utf-8") as fh: + long_description = fh.read() + +setuptools.setup( + name="seedsigner", + version="0.4.1", + author="SeedSigner", + author_email="author@example.com", + description="Build an offline, airgapped Bitcoin signing device for less than $50!", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://github.com/SeedSigner/seedsigner", + project_urls={ + "Bug Tracker": "https://github.com/SeedSigner/seedsigner/issues", + }, + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], + package_dir={"": "src"}, + packages=setuptools.find_packages(where="src"), + python_requires=">=3.6", +) \ No newline at end of file diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..aa79d2a7 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,26 @@ +# Running Tests + +You must install the test-runner dependencies: +``` +pip3 install -r tests/requirements.txt +``` + +Then make the `seedsigner` python module visible/importable to the tests by installing it: +``` +pip3 install -e . +``` + +Run the whole test suite: +``` +pytest +``` + +Run a specific test file: +``` +pytest tests/test_this_file.py +``` + +Run a specific test: +``` +pytest tests/test_this_file.py::test_this_specific_test +``` diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 00000000..7f265749 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,2 @@ +pytest==6.2.4 +mock==4.0.3 \ No newline at end of file diff --git a/tests/test_controller.py b/tests/test_controller.py new file mode 100644 index 00000000..001002d1 --- /dev/null +++ b/tests/test_controller.py @@ -0,0 +1,42 @@ +import configparser +import pytest +from mock import MagicMock +from seedsigner.controller import Controller + + + +def test_singleton_init_fails(): + """ The Controller should not allow any code to instantiate it via Controller() """ + with pytest.raises(Exception): + c = Controller() + +def test_singleton_get_instance_without_configure_fails(): + """ Calling get_instance() without first calling configure_instance() should fail """ + with pytest.raises(Exception): + c = Controller.get_instance() + +def test_singleton_get_instance_preserves_state(): + """ Changes to the Controller singleton should be preserved across calls to get_instance() """ + settings = """ + [system] + DEBUG = True + DEFAULT_LANGUAGE = en + + [display] + BACKGROUND_COLOR = #000 + TEXT_COLOR = orange + """ + config = configparser.ConfigParser() + config.read_string(settings) + + # Initialize the instance and verify that it read the config settings + Controller.configure_instance(config) + controller = Controller.get_instance() + assert controller.display_settings["text_color"] == "orange" + + # Change a value in the instance... + controller.display_settings["text_color"] = "purple" + + # ...get a new copy of the instance and confirm change + controller = Controller.get_instance() + assert controller.display_settings["text_color"] == "purple"