mirror of
https://github.com/ChristianLight/tutor.git
synced 2024-11-10 15:20:56 +00:00
71ed7a8618
The hooks API had several issues which are summarized in this comment: https://github.com/openedx/wg-developer-experience/issues/125#issuecomment-1313553526 1. "consts" was a bad name 2. "hooks.filters" and "hooks.Filters" could easily be confused 3. docs made it difficult to understand that plugin developers should use the catalog To address these issues, we: 1. move "consts.py" to "catalog.py" 2. Remove "hooks.actions", "hooks.filters", "hooks.contexts" from the API. 3. re-organize the docs and give better usage examples in the catalog. This change is a partial fix for https://github.com/openedx/wg-developer-experience/issues/125
79 lines
2.2 KiB
Python
79 lines
2.2 KiB
Python
import os
|
|
import tempfile
|
|
import typing as t
|
|
import unittest
|
|
import unittest.result
|
|
|
|
from tutor import hooks
|
|
from tutor.commands.context import BaseTaskContext
|
|
from tutor.core.hooks.contexts import enter as enter_context
|
|
from tutor.tasks import BaseTaskRunner
|
|
from tutor.types import Config
|
|
|
|
|
|
class TestTaskRunner(BaseTaskRunner):
|
|
"""
|
|
Mock job runner for unit testing.
|
|
|
|
This runner does nothing except print the service name and command,
|
|
separated by dashes.
|
|
"""
|
|
|
|
def run_task(self, service: str, command: str) -> int:
|
|
print(os.linesep.join([f"Service: {service}", "-----", command, "----- "]))
|
|
return 0
|
|
|
|
|
|
def temporary_root() -> "tempfile.TemporaryDirectory[str]":
|
|
"""
|
|
Context manager to handle temporary test root.
|
|
|
|
This function can be used as follows:
|
|
|
|
with temporary_root() as root:
|
|
config = tutor_config.load_full(root)
|
|
...
|
|
"""
|
|
return tempfile.TemporaryDirectory(prefix="tutor-test-root-")
|
|
|
|
|
|
class TestContext(BaseTaskContext):
|
|
"""
|
|
Click context that will use only test job runners.
|
|
"""
|
|
|
|
def job_runner(self, config: Config) -> TestTaskRunner:
|
|
return TestTaskRunner(self.root, config)
|
|
|
|
|
|
class PluginsTestCase(unittest.TestCase):
|
|
"""
|
|
This test case class clears the hooks created during tests. It also makes sure that
|
|
we don't accidentally load entrypoint/dict plugins from the user.
|
|
"""
|
|
|
|
def setUp(self) -> None:
|
|
self.clean()
|
|
self.addCleanup(self.clean)
|
|
super().setUp()
|
|
|
|
def clean(self) -> None:
|
|
# We clear hooks created in some contexts, such that user plugins are never loaded.
|
|
for context in [
|
|
hooks.Contexts.PLUGINS.name,
|
|
hooks.Contexts.PLUGINS_V0_ENTRYPOINT.name,
|
|
hooks.Contexts.PLUGINS_V0_YAML.name,
|
|
"unittests",
|
|
]:
|
|
hooks.clear_all(context=context)
|
|
|
|
def run(
|
|
self, result: t.Optional[unittest.result.TestResult] = None
|
|
) -> t.Optional[unittest.result.TestResult]:
|
|
"""
|
|
Run all actions and filters with a test context, such that they can be cleared
|
|
from one run to the next.
|
|
"""
|
|
with enter_context("unittests"):
|
|
return super().run(result=result)
|