Skip to content

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

@jrobichaud

Description

@jrobichaud

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions