Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing utilities #895

Open
JuroOravec opened this issue Jan 8, 2025 · 2 comments
Open

Testing utilities #895

JuroOravec opened this issue Jan 8, 2025 · 2 comments

Comments

@JuroOravec
Copy link
Collaborator

JuroOravec commented Jan 8, 2025

I was writing up tests for the icon component package, and I realized that I had to address the same issues with testing components as when I'm writing tests in django-components.

So IMO it'd be helpful if django-components had a way to simplify writing tests.

Some issues with testing components are:

  • Component IDs are random, so assertions don't work well
  • Components may be already registered
  • Our cache of Template instances may have leftover entries

So what I did in the icon package was to wrap that all in a TestEnv class, and then call test_env.setup() and test_env.teardown() in respective methods:

test_env = TestEnv()

class BaseTestCase(SimpleTestCase):
    def setUp(self):
        super().setUp()
        test_env.setup()

    def tearDown(self):
        super().tearDown()
        test_env.teardown()

The implementation looks like this, it's taken from django-components from here:

from typing import List, Optional
from unittest.mock import patch

from django.test import SimpleTestCase

from django_components.component_registry import ComponentRegistry, all_registries

class TestEnv:
    def __init__(self, registries: Optional[List[ComponentRegistry]] = None):
        self.registries = registries or all_registries

    def setup(self):
        self._start_gen_id_patch()

    def teardown(self):
        self._stop_gen_id_patch()

        for registry in self.registries:
            registry.clear()

        from django_components.template import template_cache

        # NOTE: There are 1-2 tests which check Templates, so we need to clear the cache
        if template_cache:
            template_cache.clear()

    # Mock the `generate` function used inside `gen_id` so it returns deterministic IDs
    def _start_gen_id_patch(self):
        # Random number so that the generated IDs are "hex-looking", e.g. a1bc3d
        self._gen_id_count = 10599485

        def mock_gen_id(*args, **kwargs):
            self._gen_id_count += 1
            return hex(self._gen_id_count)[2:]

        self._gen_id_patch = patch("django_components.util.misc.generate", side_effect=mock_gen_id)
        self._gen_id_patch.start()

    def _stop_gen_id_patch(self):
        self._gen_id_patch.stop()
        self._gen_id_count = 10599485

Questions

  • Should this be part of the main package, or separate?
  • How should it be imported?

I'm thinking that, since it's just one small class right now, it makes sense to include it in the django_components distribution.

So it could be used e.g. like this:

from django_components.testing import TestEnv

test_env = TestEnv()

...

If it ever gets too large, it could be moved into a separate package, and then exposed via django-components as an optional dependency:

pip install django-components[testing]

Notes

As part of this issues we should also document how to test components, and maybe also point to the icon package as a live example.

@EmilStenstrom
Copy link
Owner

@JuroOravec I think this should be part of the package, available for package builders, and also actually used by the internal tests as well. Could we package our own test logic as a reusable class, use it across tests, and document it as an externally available tool.

@JuroOravec
Copy link
Collaborator Author

100% agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants