Back to Repositories

Testing Django South Ghost Migration Handler in thefuck

This test suite validates the Django South ghost migration handling functionality in the thefuck project. It focuses on testing error detection and command correction for ghost migrations in Django applications using South migration framework.

Test Coverage Overview

The test suite provides comprehensive coverage of Django South ghost migration scenarios.

Key areas tested include:
  • Detection of ghost migrations in database
  • Command matching for migration attempts
  • Proper command modification to handle ghost migrations
  • Various input command patterns and their responses

Implementation Analysis

The testing approach uses pytest fixtures to simulate Django South migration errors and verify command corrections. The implementation follows a pattern of separate match and command generation tests, ensuring both error detection and solution generation are validated independently.

Technical patterns include:
  • Fixture-based test data setup
  • Command object validation
  • Error output pattern matching
  • Command string transformation testing

Technical Details

Testing infrastructure includes:
  • pytest as the primary testing framework
  • Custom Command type for input validation
  • Mock migration error outputs
  • Specific test cases for both positive and negative scenarios

Best Practices Demonstrated

The test suite exemplifies several testing best practices for command-line tool validation.

Notable practices include:
  • Comprehensive error case coverage
  • Isolated test functions
  • Clear test case separation
  • Explicit assertion statements
  • Well-structured test data fixtures

nvbn/thefuck

tests/rules/test_django_south_ghost.py

            
import pytest
from thefuck.rules.django_south_ghost import match, get_new_command
from thefuck.types import Command


@pytest.fixture
def output():
    return '''Traceback (most recent call last):
  File "/home/nvbn/work/.../bin/python", line 42, in <module>
    exec(compile(__file__f.read(), __file__, "exec"))
  File "/home/nvbn/work/.../app/manage.py", line 34, in <module>
    execute_from_command_line(sys.argv)
  File "/home/nvbn/work/.../lib/django/core/management/__init__.py", line 443, in execute_from_command_line
    utility.execute()
  File "/home/nvbn/work/.../lib/django/core/management/__init__.py", line 382, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/nvbn/work/.../lib/django/core/management/base.py", line 196, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/home/nvbn/work/.../lib/django/core/management/base.py", line 232, in execute
    output = self.handle(*args, **options)
  File "/home/nvbn/work/.../app/lib/south/management/commands/migrate.py", line 108, in handle
    ignore_ghosts = ignore_ghosts,
  File "/home/nvbn/work/.../app/lib/south/migration/__init__.py", line 193, in migrate_app
    applied_all = check_migration_histories(applied_all, delete_ghosts, ignore_ghosts)
  File "/home/nvbn/work/.../app/lib/south/migration/__init__.py", line 88, in check_migration_histories
    raise exceptions.GhostMigrations(ghosts)
south.exceptions.GhostMigrations: 

 ! These migrations are in the database but not on disk:
    <app1: 0033_auto__...>
    <app1: 0034_fill_...>
    <app1: 0035_rename_...>
    <app2: 0003_add_...>
    <app2: 0004_denormalize_...>
    <app1: 0033_auto....>
    <app1: 0034_fill...>
 ! I'm not trusting myself; either fix this yourself by fiddling
 ! with the south_migrationhistory table, or pass --delete-ghost-migrations
 ! to South to have it delete ALL of these records (this may not be good).
'''  # noqa


def test_match(output):
    assert match(Command('./manage.py migrate', output))
    assert match(Command('python manage.py migrate', output))
    assert not match(Command('./manage.py migrate', ''))
    assert not match(Command('app migrate', output))
    assert not match(Command('./manage.py test', output))


def test_get_new_command():
    assert get_new_command(Command('./manage.py migrate auth', ''))\
        == './manage.py migrate auth --delete-ghost-migrations'