Why is test suite accessing model(s) long since removed via migrations?

The following simple test,

from django.test import TestCase
    
    class TestSetup(TestCase):   
        def test_setUp(self):
            pdb.set_trace()
            # Code here deleted, it made no difference to the error.

throws the errors:

> Destroying old test database for alias 'default'... Traceback (most
> recent call last):   File
> "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py",
> line 1957, in get_prep_value
>     return float(value) ValueError: could not convert string to float: ''
> 
> The above exception was the direct cause of the following exception:
> 
> Traceback (most recent call last):   File "manage.py", line 22, in
> <module>
>     main()   File "manage.py", line 18, in main
>     execute_from_command_line(sys.argv)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/core/management/__init__.py",
> line 442, in execute_from_command_line
>     utility.execute()   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/core/management/__init__.py",
> line 436, in execute
>     self.fetch_command(subcommand).run_from_argv(self.argv)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/core/management/commands/test.py",
> line 24, in run_from_argv
>     super().run_from_argv(argv)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/core/management/base.py",
> line 412, in run_from_argv
>     self.execute(*args, **cmd_options)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/core/management/base.py",
> line 458, in execute
>     output = self.handle(*args, **options)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/core/management/commands/test.py",
> line 68, in handle
>     failures = test_runner.run_tests(test_labels)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/test/runner.py",
> line 1054, in run_tests
>     old_config = self.setup_databases(   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/test/runner.py",
> line 950, in setup_databases
>     return _setup_databases(   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/test/utils.py",
> line 221, in setup_databases
>     connection.creation.create_test_db(   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/backends/base/creation.py",
> line 78, in create_test_db
>     call_command(   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/core/management/__init__.py",
> line 194, in call_command
>     return command.execute(*args, **defaults)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/core/management/base.py",
> line 458, in execute
>     output = self.handle(*args, **options)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/core/management/base.py",
> line 106, in wrapper
>     res = handle_func(*args, **kwargs)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/core/management/commands/migrate.py",
> line 356, in handle
>     post_migrate_state = executor.migrate(   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/migrations/executor.py",
> line 135, in migrate
>     state = self._migrate_all_forwards(   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/migrations/executor.py",
> line 167, in _migrate_all_forwards
>     state = self.apply_migration(   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/migrations/executor.py",
> line 252, in apply_migration
>     state = migration.apply(state, schema_editor)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/migrations/migration.py",
> line 132, in apply
>     operation.database_forwards(   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/migrations/operations/fields.py",
> line 235, in database_forwards
>     schema_editor.alter_field(from_model, from_field, to_field)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/backends/base/schema.py",
> line 830, in alter_field
>     self._alter_field(   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/backends/postgresql/schema.py",
> line 287, in _alter_field
>     super()._alter_field(   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/backends/base/schema.py",
> line 1025, in _alter_field
>     new_default = self.effective_default(new_field)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/backends/base/schema.py",
> line 429, in effective_default
>     return field.get_db_prep_save(self._effective_default(field), self.connection)   File
> "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py",
> line 954, in get_db_prep_save
>     return self.get_db_prep_value(value, connection=connection, prepared=False)   File
> "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py",
> line 947, in get_db_prep_value
>     value = self.get_prep_value(value)   File "/var/www/ptech/venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py",
> line 1959, in get_prep_value
>     raise e.__class__( ValueError: Field 'amount' expected a number but got ''.

The field ‘amount’ does exist, but in a model that isn’t loaded for any tests:

models.py
    
class Appointment(models.Model):
    amount = models.FloatField(blank=True, default=0.0)

But just in case it’s instantiating that model in the process of creating the test database, I migrated “default=0.0” to "default=‘0.0’ " (Single quotes around the value). Same error.

I also tried deleting the postgresql test database manually with psql.

I’m initiating the test with

python manage.py test

and also by specifying the app_name:

python manage.py test giraffe

from the project directory.

Relevant migrations, in sequential order:

# Generated by Django 4.1.3 on 2023-01-10 22:58
from django.db import migrations, models   

class Migration(migrations.Migration):
    dependencies = [
        ('giraffe', '0014_appointment_notes'),
    ]
    operations = [
        migrations.AlterField(
            model_name='appointment',
            name='amount',
            field=models.FloatField(blank=True, default=''),
        ),
    ]

and

class Migration(migrations.Migration):
    dependencies = [
        ('giraffe', '0015_alter_appointment_amount'),
    ]
    operations = [
        migrations.AlterField(
            model_name='appointment',
            name='amount',
            field=models.FloatField(blank=True),
        ),
    ]

and

class Migration(migrations.Migration):
    dependencies = [
        ('giraffe', '0016_alter_appointment_amount'),
    ]
    operations = [
        migrations.AlterField(
            model_name='appointment',
            name='amount',
            field=models.FloatField(blank=True, default=0.0),
        ),
    ]

And some earlier migrations pertaining to a model with an ‘amount’ field, but a model which was deleted, but still shows up in the test database.

...migrations.CreateModel(
            name='UnreimbursedMileage',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('mileage_rate_category', models.CharField(choices=[('FB22a', 'Federal Business Rate, Qtr. 1&2 2022'), ('FB22b', 'Federal Business Rate, Qtr. 3&4, 2022'), ('FB23', 'Federal Business Rate 2023')], default='FB22a', max_length=5)),
                ('num_miles', models.FloatField(blank=True, default=0)),
                ('amount', models.FloatField(blank=True, null=True)),
                ('for_appointment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, to='giraffe.appointment')),
            ],
            options={
                'verbose_name_plural': 'Unreimbursed Mileage',
            },
        ),

class Migration(migrations.Migration):
    dependencies = [
        ('giraffe', '0054_rename_to_do_next_time_todonexttime_and_more'),
    ]
    operations = [
        migrations.RemoveField(
            model_name='unreimbursedmileage',
            name='for_appointment',
        ),
        migrations.DeleteModel(
            name='Dummy',
        ),
        migrations.DeleteModel(
            name='UnreimbursedMileage',
        ),
    ]

This question was also posted on StackOverflow. Please let me know if that’s a no-no. I’ll post any successful answer received here.

My hypothesis based on a comment in StackOverflow is that unit test was accessing a migration in the “migrations/pycache” folder that caused it to fail. Perhaps just deleting that folder, which reconstitutes itself, would have been enough? But I did a full reset of migrations and generation of a fake __initial, which solved the problem.

Any further insights are welcome.