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

Cannot have multiple test functions in the same class inheriting from MigratorTestCase #467

Open
jrobichaud opened this issue Jul 17, 2024 · 3 comments

Comments

@jrobichaud
Copy link

jrobichaud commented Jul 17, 2024

The way MigratorTestCase is implemented it is only possible to setup test data in the prepare function which is called during setUp. Because of that there is no way to setup different data for different test functions.

In order to be able to support multiple test functions MigratorTestCase could be implemented this way:

@tag(MIGRATION_TEST_MARKER)
class MigratorTestCase(TransactionTestCase):
    """Used when using raw ``unitest`` library for test."""

    database_name: ClassVar[Optional[str]] = None
    old_state: ProjectState
    new_state: ProjectState

    #: Part of the end-user API. Used to tell what migrations we are using.
    migrate_from: ClassVar[MigrationSpec]
    migrate_to: ClassVar[MigrationSpec]

    auto_migrate: bool = True  # <-------------- Add an option to disable automatic migration

    def setUp(self) -> None:
        """
        Regular ``unittest`` styled setup case.

        What it does?
          - It starts with defining the initial migration state
          - Then it allows to run custom method
            to prepare some data before the migration will happen
          - Then it applies the migration and saves all states

        """
        super().setUp()
        self._migrator = Migrator(self.database_name)
        self.old_state = self._migrator.apply_initial_migration(
            self.migrate_from,
        )
        self.prepare()
        if self.auto_migrate:   # <-------------- check if auto_migrate is activated
            self.migrate()   # <-------------- call the extracted the method

    # v-------------- do the migration
    def migrate(self) -> None:
        assert not hasattr(self, "new_state"), "migrate must be called only once"
        self.new_state = self._migrator.apply_tested_migration(self.migrate_to)

it would allow to add multiple test scenarios like this:

class Test1234(MigratorTestCase):
    migrate_from = ...
    migrate_to = ...

    auto_migrate = False

    def prepare(self):
        ... # prepare common stuff here
    
    def test_scenario_1(self):
        ... # instantiate stuff here using old state
        self.migrate()
        ... # validate migration here using new state

    def test_scenario_2(self):
        ... # instantiate stuff here using old state
        self.migrate()
        ... # validate migration here using new state
@jrobichaud
Copy link
Author

jrobichaud commented Jul 17, 2024

The workaround for the moment is to create a custom MigratorTestCase.

from django_test_migrations.contrib.unittest_case import MigratorTestCase
from django_test_migrations.migrator import Migrator


class ManualMigratorTestCase(MigratorTestCase):
    def setUp(self) -> None:
        self._migrator = Migrator(self.database_name)
        self.old_state = self._migrator.apply_initial_migration(
            self.migrate_from,
        )
        self.prepare()

    def migrate(self) -> None:
        assert not hasattr(self, "new_state"), "migrate must be called only once"
        self.new_state = self._migrator.apply_tested_migration(self.migrate_to)

@sobolevn
Copy link
Member

Maybe we should design a new API instead? We can come up with a better one and deprecate the existing one.

@jrobichaud
Copy link
Author

Before using django-test-migrations, I was using django_migration_testcase and it is how it was working.

django-test-migrations is much more robust in my opinion but I still miss this behaviour of that library.

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