Re: Migrations in Django 1.7 make unit testing models harder

2019-09-14 Thread Adam Johnson
Hi Dylan,

In my experience, high availability deployments often need to commit model
changes without migration changes. For example, when removing a (nulable)
field, the best approach is to:

   1. Remove the field from Django
   2. Test
   3. Deploy
   4. Run makemigrations to generate the migration file that removes it
   from the database
   5. Test
   6. Deploy

The test run in step 2 should *not* have any automated migrations built.
The tests should confirm that removing the field from Django without
removing it from the DB safe.

If you want to build your suggested behaviour (makemigrations before every
test run) you can do it by:

   1. Creating a custom test runner that subclasses DiscoverRunner
   2. Overriding its setup_databases() method to do
   call_command('makemigrations') before super()
   3. Catching the names of those made migrations, and
   overriding teardown_databases() to delete them (or maybe not?)

I'd be interested to know how that works! I suspect it will be fine for
smaller projects, but for larger projects that care about preventing
downtime during deployment, it will backfire.

As an extra benefit, it makes testing between branches *so much* easier
> because you don't have to worry about rolling back migrations on the
> test_db (a PITA as far as I can see).
>

If you're using the default behaviour, the test DB is generated on every
run. The `--keepdb` flag is optional and can be used to speed up test runs
on the same branch but you should run tests without it after switching. I
agree it can be a pain.

Maybe we could have a guard on that flag: detect if git is used, and the
branch has changed since last run, and then warn or just hard recreate? If
you'd be interested in exploring this, it can also be tested by subclassing
the migrate command. Maybe make a ticket?

Regarding the last, is there a flag to make migrate target the test_db(s)?
>

Not that I know of but I did something similar on one project where I had a
management command to create a test runner and call its setup_databases()
method. That should be sufficient!

Thanks,

Adam

On Fri, 13 Sep 2019 at 19:04, Dylan Young 
wrote:

> This is an old issue that (as far as I can see) was never resolved.
>
> My proposed solution would be a flag to the test command to automatically
> `makemigrations && migrate`.  When this behaviour is enabled, it would also
> roll back any generated migrations at the end of the test run.   The flag
> might not be necessary (could be default behaviour of `test`)
>
> This way you get the benefits of all worlds:
> 1) uncommitted migration files will be clearly visible after the test run
> (for those inclined to forget to makemigrations).
> 2) The extraneous non-migration creation code can be removed from Django
> (probably already has been at this point).
> 3) Tests are always run against the current state of models
> 4) Tests are always run at current state of migrations (because it
> generates the migrations).
>
> As an extra benefit, it makes testing between branches *so much* easier
> because you don't have to worry about rolling back migrations on the
> test_db (a PITA as far as I can see).
>
> Regarding the last, is there a flag to make migrate target the test_db(s)?
>
> Best,
>
> Casey
>
> On Tuesday, 25 March 2014 14:21:51 UTC-3, Bernie Sumption wrote:
>>
>> Hi Django devs,
>>
>> I've just started a new project in 1.7b, and the development experience
>> working with unit tests on models is more complicated than it was in 1.6.
>> It's all down to how the throwaway test databases are created. In 1.6, the
>> create_test_db function "Creates a new test database and runs syncdb
>> against it." In 1.7, it runs "migrate".
>>
>> While generally speaking, migrate is the new syncdb, this behaviour is
>> not ideal for tests. In 1.6 "syncdb" created a database reflecting the
>> current state of the models in models.py. "migrate" creates a database
>> reflecting the state of the models at the last time makemigrations was run.
>> If you're doing TDD and constantly making small changes to your models then
>> runnning unit tests, you have to run makemigrations before each test run to
>> get your tests to work. You therefore end up with many tiny migration files
>> representing the minute-by-minute history of development.
>>
>> I came up with a pretty effective workaround that is working for me, but
>> I thought I'd post this here as others are sure to encounter this issue,
>> and I think that it makes more sense for the behaviour produced by this
>> workaround to be the default for running tests.
>>
>> If makemigrations has not yet been run, the "migrate" command treats an
>> app as unmigrated, and creates tables directly from the models just like
>> syncdb did in 1.6. I defined a new settings module just for unit tests
>> called "settings_test.py", which imports * from the main settings module
>> and adds this line:
>>
>> MIGRATION_MODULES = {"myapp": "myapp.migrations_not_used_in_tests"}
>>
>> Then I

Re: PEP 484 type hinting in Django

2019-09-14 Thread Maxim Kurnikov
I actually used MonkeyType to generate first version of `django-stubs` back
in the day.

Best regards,
Maxim Kurnikov.


On Thu, Sep 12, 2019 at 11:25 PM Lukas Meier  wrote:

> I'm writing here with the risk of you guys obviously already knowing about
> it
>
> there is a project called monkeytype written by instagram that does
> analysis similar to what  @Maxim said
>
> they actually have specific answers to django related questions here
> https://monkeytype.readthedocs.io/en/stable/faq.html
>
>
>
> On Monday, 26 August 2019 07:05:19 UTC-5, Maxim Kurnikov wrote:
>>
>> Hi, I'm the original creator of
>> https://github.com/typeddjango/django-stubs.
>>
>> I guess it's my duty to start writing a DEP, so here is some preliminary
>> thoughts/questions to gather early feedback:
>>
>> Main discussion points:
>> 1. There's two ways to make Django compatible with type hinting and
>> PEP484:
>> - Separate repo with `.pyi` files and mypy plugin (how it's done
>> currently with django-stubs).
>>
>> Pros:
>> - no backwards-incompatible changes. Only required change from
>> Django is adding the `__class_getitem__` method to `QuerySet`
>> https://docs.python.org/3/reference/datamodel.html#object.__class_getitem__
>> to support generic parameters in 3.7+
>> - could be released separately
>> - no type hints code clutter
>> Cons:
>> - (as of now) there's no way to use type hints to typecheck
>> Django codebase itself. I think the official answer to that is to use
>> retype tool https://github.com/ambv/retype (
>> https://github.com/python/mypy/issues/5028#issuecomment-495942769), but
>> so far I didn't have any positive experience with that
>>
>> - Inline type hints in the codebase.
>>
>> Pros/Cons are exact reverse.
>>
>> 2. Whether to use Django own machinery to extract info for the
>> models/fields, or not.
>>
>> Current implementation of django-stubs utilises `Apps` registry of Django
>> itself to extract some data for models/fields.
>>  So, basically it executes codes first, then performs static analysis of
>> it.
>>
>> Pros:
>> - lots of models/fields introspection could be extracted from the
>> `_meta` API => lower maintenance burden, more accurate types. In the
>> pre-1.0.0 versions of the django-stubs it was all done statically, and it
>> was very painful to implement.
>>
>> Cons:
>> - mypy daemon mode (dmypy) is broken. It could be fixed, but it
>> requires some changes to mypy itself, and as `django.setup()` could not run
>> incrementally, it's not clear whether dmypy would provide any real benefits
>> over plain incremental mode.
>> - there could be some side effects in `django.setup()` invocation
>> - cannot typecheck invalid code
>> - slower to execute
>>
>> Carlton, is it possible to move discussion to Github somehow?
>>
>> On Wednesday, December 12, 2018 at 7:06:16 PM UTC+3, Carlton Gibson wrote:
>>>
>>> Hi all.
>>>
>>>
>>> Where are we with this Type Hinting work?
>>>
>>>
>>> I just closed https://code.djangoproject.com/ticket/30019 as needsinfo
>>> pointing back to this thread.
>>>
>>>
>>> As far as I can see:
>>>
>>> * There's keenness for this.
>>> * There's a number of people who are prepared to put in the effort.
>>> * But we just need a strategy.
>>>
>>> It looks then like a coordination problem. Do we just need to get said
>>> people in a (virtual) room...?
>>>
>>> Maybe one of you — anyone — opening a DEP to begin the conversation
>>> would be enough..
>>> (That's just an idea.)
>>>
>>> Looking here:
>>> https://github.com/django/deps/blob/master/final/0001-dep-process.rst#dep-submission-workflow
>>> I'd guess "Forming the Team" is relevant.
>>>
>>> Happy to help if I can.
>>> (I recall Frank mentioned it no too long ago...)
>>>
>>> Kind Regards,
>>>
>>> Carlton
>>>
>>> --
> You received this message because you are subscribed to a topic in the
> Google Groups "Django developers (Contributions to Django itself)" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/django-developers/trTEbURFhEY/unsubscribe
> .
> To unsubscribe from this group and all its topics, send an email to
> django-developers+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-developers/2273ec96-8ad8-4ae3-9802-1e0663bdd9b6%40googlegroups.com
> 
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAOGcyS_AC-CsuVK%2Br52zrWV2WXZQoMfz1BiKpfnpncYJDE5hKA%40mail.gmail.com.


Re: Migrations in Django 1.7 make unit testing models harder

2019-09-14 Thread Dylan Young
Thanks for the tips; I'll take a look at those code paths.

I'm interested in your use case: why do you need the model changes without
the migrations? I.e. why would you want to be in a state that's
inconsistent between the ORM and the DB?  Is it just so you can recover
more easily if something goes wrong?

Recent versions of Django make it easier to modify the test command,  so I
may take a look at spinning up an external package for this.

Le sam. 14 sept. 2019 5:36 a.m., Adam Johnson  a écrit :

> Hi Dylan,
>
> In my experience, high availability deployments often need to commit model
> changes without migration changes. For example, when removing a (nulable)
> field, the best approach is to:
>
>1. Remove the field from Django
>2. Test
>3. Deploy
>4. Run makemigrations to generate the migration file that removes it
>from the database
>5. Test
>6. Deploy
>
> The test run in step 2 should *not* have any automated migrations built.
> The tests should confirm that removing the field from Django without
> removing it from the DB safe.
>
> If you want to build your suggested behaviour (makemigrations before every
> test run) you can do it by:
>
>1. Creating a custom test runner that subclasses DiscoverRunner
>2. Overriding its setup_databases() method to do
>call_command('makemigrations') before super()
>3. Catching the names of those made migrations, and
>overriding teardown_databases() to delete them (or maybe not?)
>
> I'd be interested to know how that works! I suspect it will be fine for
> smaller projects, but for larger projects that care about preventing
> downtime during deployment, it will backfire.
>
> As an extra benefit, it makes testing between branches *so much* easier
>> because you don't have to worry about rolling back migrations on the
>> test_db (a PITA as far as I can see).
>>
>
> If you're using the default behaviour, the test DB is generated on every
> run. The `--keepdb` flag is optional and can be used to speed up test runs
> on the same branch but you should run tests without it after switching. I
> agree it can be a pain.
>
> Maybe we could have a guard on that flag: detect if git is used, and the
> branch has changed since last run, and then warn or just hard recreate? If
> you'd be interested in exploring this, it can also be tested by subclassing
> the migrate command. Maybe make a ticket?
>
> Regarding the last, is there a flag to make migrate target the test_db(s)?
>>
>
> Not that I know of but I did something similar on one project where I had
> a management command to create a test runner and call its setup_databases()
> method. That should be sufficient!
>
> Thanks,
>
> Adam
>
> On Fri, 13 Sep 2019 at 19:04, Dylan Young 
> wrote:
>
>> This is an old issue that (as far as I can see) was never resolved.
>>
>> My proposed solution would be a flag to the test command to automatically
>> `makemigrations && migrate`.  When this behaviour is enabled, it would also
>> roll back any generated migrations at the end of the test run.   The flag
>> might not be necessary (could be default behaviour of `test`)
>>
>> This way you get the benefits of all worlds:
>> 1) uncommitted migration files will be clearly visible after the test run
>> (for those inclined to forget to makemigrations).
>> 2) The extraneous non-migration creation code can be removed from Django
>> (probably already has been at this point).
>> 3) Tests are always run against the current state of models
>> 4) Tests are always run at current state of migrations (because it
>> generates the migrations).
>>
>> As an extra benefit, it makes testing between branches *so much* easier
>> because you don't have to worry about rolling back migrations on the
>> test_db (a PITA as far as I can see).
>>
>> Regarding the last, is there a flag to make migrate target the test_db(s)?
>>
>> Best,
>>
>> Casey
>>
>> On Tuesday, 25 March 2014 14:21:51 UTC-3, Bernie Sumption wrote:
>>>
>>> Hi Django devs,
>>>
>>> I've just started a new project in 1.7b, and the development experience
>>> working with unit tests on models is more complicated than it was in 1.6.
>>> It's all down to how the throwaway test databases are created. In 1.6, the
>>> create_test_db function "Creates a new test database and runs syncdb
>>> against it." In 1.7, it runs "migrate".
>>>
>>> While generally speaking, migrate is the new syncdb, this behaviour is
>>> not ideal for tests. In 1.6 "syncdb" created a database reflecting the
>>> current state of the models in models.py. "migrate" creates a database
>>> reflecting the state of the models at the last time makemigrations was run.
>>> If you're doing TDD and constantly making small changes to your models then
>>> runnning unit tests, you have to run makemigrations before each test run to
>>> get your tests to work. You therefore end up with many tiny migration files
>>> representing the minute-by-minute history of development.
>>>
>>> I came up with a pretty effective wor

Re: Migrations in Django 1.7 make unit testing models harder

2019-09-14 Thread Ryan Hiebert
On Sat, Sep 14, 2019 at 10:09 AM Dylan Young 
wrote:

> why do you need the model changes without the migrations? I.e. why would
> you want to be in a state that's inconsistent between the ORM and the DB?
> Is it just so you can recover more easily if something goes wrong?
>

I expect that its to allow for shipping the ORM code changes separately
from the database migrations. That was my use-case anyway. If the migration
needed to run first, then I wanted to deploy the migrations by themselves,
then the ORM changes. Sometimes I'd want to ship the ORM changes first, and
the migrations later (though usually just running them after deploy was
effective).

Then when Heroku added release phase, which can automatically run
migrations immediately before a release is deployed, I really wanted to do
something better. So we created django-safemigrate (
https://github.com/aspiredu/dango-safemigrate), which allows you to mark
your deploys as safe to run before, after, or at any time relative to the
code changes to the ORM they match. This allows my team to avoid splitting
up the ORM changes from the migrations, which keeps matching things
together in the commit history. It's been working fairly well for us,
barring the occasional human error mis-marking the migrations. Feel free to
give it a try, to see if its also a good workflow for you!

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CABpHFHT0OZmKQ%2BfH7%3DSgGCugwVW56QdJ2%2Bgi5ZPXPCH1E%2BF7OA%40mail.gmail.com.


Re: Migrations in Django 1.7 make unit testing models harder

2019-09-14 Thread Adam Johnson
>
> I'm interested in your use case: why do you need the model changes without
> the migrations? I.e. why would you want to be in a state that's
> inconsistent between the ORM and the DB?  Is it just so you can recover
> more easily if something goes wrong?
>

It's not that one *wants* to be in that state, it's just inevitable with
the goal of zero downtime. With reasonable traffic on even one webserver,
it's inevitable there's a gap between the running of migrations and the
updating of the webserver to the new code. In this case it's best to make
sure both old and new code versions are compatible with the new version of
the database.

There's plenty out there on the topic. A post I found useful recently was
this one from Braintree covering the different ways to help zero downtime
deployments PostgreSQL:
https://medium.com/braintree-product-technology/postgresql-at-scale-database-schema-changes-without-downtime-20d3749ed680

Thanks,

Adam

On Sat, 14 Sep 2019 at 16:09, Dylan Young 
wrote:

> Thanks for the tips; I'll take a look at those code paths.
>
> I'm interested in your use case: why do you need the model changes without
> the migrations? I.e. why would you want to be in a state that's
> inconsistent between the ORM and the DB?  Is it just so you can recover
> more easily if something goes wrong?
>
> Recent versions of Django make it easier to modify the test command,  so I
> may take a look at spinning up an external package for this.
>
> Le sam. 14 sept. 2019 5:36 a.m., Adam Johnson  a écrit :
>
>> Hi Dylan,
>>
>> In my experience, high availability deployments often need to commit
>> model changes without migration changes. For example, when removing a
>> (nulable) field, the best approach is to:
>>
>>1. Remove the field from Django
>>2. Test
>>3. Deploy
>>4. Run makemigrations to generate the migration file that removes it
>>from the database
>>5. Test
>>6. Deploy
>>
>> The test run in step 2 should *not* have any automated migrations built.
>> The tests should confirm that removing the field from Django without
>> removing it from the DB safe.
>>
>> If you want to build your suggested behaviour (makemigrations before
>> every test run) you can do it by:
>>
>>1. Creating a custom test runner that subclasses DiscoverRunner
>>2. Overriding its setup_databases() method to do
>>call_command('makemigrations') before super()
>>3. Catching the names of those made migrations, and
>>overriding teardown_databases() to delete them (or maybe not?)
>>
>> I'd be interested to know how that works! I suspect it will be fine for
>> smaller projects, but for larger projects that care about preventing
>> downtime during deployment, it will backfire.
>>
>> As an extra benefit, it makes testing between branches *so much* easier
>>> because you don't have to worry about rolling back migrations on the
>>> test_db (a PITA as far as I can see).
>>>
>>
>> If you're using the default behaviour, the test DB is generated on every
>> run. The `--keepdb` flag is optional and can be used to speed up test runs
>> on the same branch but you should run tests without it after switching. I
>> agree it can be a pain.
>>
>> Maybe we could have a guard on that flag: detect if git is used, and the
>> branch has changed since last run, and then warn or just hard recreate? If
>> you'd be interested in exploring this, it can also be tested by subclassing
>> the migrate command. Maybe make a ticket?
>>
>> Regarding the last, is there a flag to make migrate target the test_db(s)?
>>>
>>
>> Not that I know of but I did something similar on one project where I had
>> a management command to create a test runner and call its setup_databases()
>> method. That should be sufficient!
>>
>> Thanks,
>>
>> Adam
>>
>> On Fri, 13 Sep 2019 at 19:04, Dylan Young 
>> wrote:
>>
>>> This is an old issue that (as far as I can see) was never resolved.
>>>
>>> My proposed solution would be a flag to the test command to
>>> automatically `makemigrations && migrate`.  When this behaviour is enabled,
>>> it would also roll back any generated migrations at the end of the test
>>> run.   The flag might not be necessary (could be default behaviour of
>>> `test`)
>>>
>>> This way you get the benefits of all worlds:
>>> 1) uncommitted migration files will be clearly visible after the test
>>> run (for those inclined to forget to makemigrations).
>>> 2) The extraneous non-migration creation code can be removed from Django
>>> (probably already has been at this point).
>>> 3) Tests are always run against the current state of models
>>> 4) Tests are always run at current state of migrations (because it
>>> generates the migrations).
>>>
>>> As an extra benefit, it makes testing between branches *so much* easier
>>> because you don't have to worry about rolling back migrations on the
>>> test_db (a PITA as far as I can see).
>>>
>>> Regarding the last, is there a flag to make migrate target the
>>> test_db(s)?
>>>
>>> Best,
>

Re: Migrations in Django 1.7 make unit testing models harder

2019-09-14 Thread Adam Johnson
(Fixed Ryan's link: https://github.com/aspiredu/django-safemigrate )

On Sat, 14 Sep 2019 at 17:12, Adam Johnson  wrote:

> I'm interested in your use case: why do you need the model changes without
>> the migrations? I.e. why would you want to be in a state that's
>> inconsistent between the ORM and the DB?  Is it just so you can recover
>> more easily if something goes wrong?
>>
>
> It's not that one *wants* to be in that state, it's just inevitable with
> the goal of zero downtime. With reasonable traffic on even one webserver,
> it's inevitable there's a gap between the running of migrations and the
> updating of the webserver to the new code. In this case it's best to make
> sure both old and new code versions are compatible with the new version of
> the database.
>
> There's plenty out there on the topic. A post I found useful recently was
> this one from Braintree covering the different ways to help zero downtime
> deployments PostgreSQL:
> https://medium.com/braintree-product-technology/postgresql-at-scale-database-schema-changes-without-downtime-20d3749ed680
>
> Thanks,
>
> Adam
>
> On Sat, 14 Sep 2019 at 16:09, Dylan Young 
> wrote:
>
>> Thanks for the tips; I'll take a look at those code paths.
>>
>> I'm interested in your use case: why do you need the model changes
>> without the migrations? I.e. why would you want to be in a state that's
>> inconsistent between the ORM and the DB?  Is it just so you can recover
>> more easily if something goes wrong?
>>
>> Recent versions of Django make it easier to modify the test command,  so
>> I may take a look at spinning up an external package for this.
>>
>> Le sam. 14 sept. 2019 5:36 a.m., Adam Johnson  a écrit :
>>
>>> Hi Dylan,
>>>
>>> In my experience, high availability deployments often need to commit
>>> model changes without migration changes. For example, when removing a
>>> (nulable) field, the best approach is to:
>>>
>>>1. Remove the field from Django
>>>2. Test
>>>3. Deploy
>>>4. Run makemigrations to generate the migration file that removes it
>>>from the database
>>>5. Test
>>>6. Deploy
>>>
>>> The test run in step 2 should *not* have any automated migrations built.
>>> The tests should confirm that removing the field from Django without
>>> removing it from the DB safe.
>>>
>>> If you want to build your suggested behaviour (makemigrations before
>>> every test run) you can do it by:
>>>
>>>1. Creating a custom test runner that subclasses DiscoverRunner
>>>2. Overriding its setup_databases() method to do
>>>call_command('makemigrations') before super()
>>>3. Catching the names of those made migrations, and
>>>overriding teardown_databases() to delete them (or maybe not?)
>>>
>>> I'd be interested to know how that works! I suspect it will be fine for
>>> smaller projects, but for larger projects that care about preventing
>>> downtime during deployment, it will backfire.
>>>
>>> As an extra benefit, it makes testing between branches *so much* easier
 because you don't have to worry about rolling back migrations on the
 test_db (a PITA as far as I can see).

>>>
>>> If you're using the default behaviour, the test DB is generated on every
>>> run. The `--keepdb` flag is optional and can be used to speed up test runs
>>> on the same branch but you should run tests without it after switching. I
>>> agree it can be a pain.
>>>
>>> Maybe we could have a guard on that flag: detect if git is used, and the
>>> branch has changed since last run, and then warn or just hard recreate? If
>>> you'd be interested in exploring this, it can also be tested by subclassing
>>> the migrate command. Maybe make a ticket?
>>>
>>> Regarding the last, is there a flag to make migrate target the
 test_db(s)?

>>>
>>> Not that I know of but I did something similar on one project where I
>>> had a management command to create a test runner and call its
>>> setup_databases() method. That should be sufficient!
>>>
>>> Thanks,
>>>
>>> Adam
>>>
>>> On Fri, 13 Sep 2019 at 19:04, Dylan Young 
>>> wrote:
>>>
 This is an old issue that (as far as I can see) was never resolved.

 My proposed solution would be a flag to the test command to
 automatically `makemigrations && migrate`.  When this behaviour is enabled,
 it would also roll back any generated migrations at the end of the test
 run.   The flag might not be necessary (could be default behaviour of
 `test`)

 This way you get the benefits of all worlds:
 1) uncommitted migration files will be clearly visible after the test
 run (for those inclined to forget to makemigrations).
 2) The extraneous non-migration creation code can be removed from
 Django (probably already has been at this point).
 3) Tests are always run against the current state of models
 4) Tests are always run at current state of migrations (because it
 generates the migrations).

 As an extra benefit, it makes testin

Re: Migrations in Django 1.7 make unit testing models harder

2019-09-14 Thread Ryan Hiebert
On Sat, Sep 14, 2019, 12:44 Adam Johnson  wrote:

> (Fixed Ryan's link: https://github.com/aspiredu/django-safemigrate )
>

Doh. Thanks.

>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CABpHFHTKwxXPsZ-9A%3Dx0tLVc2uOgXrALsNjq4NwZHGqwsk7FMg%40mail.gmail.com.


Re: Migrations in Django 1.7 make unit testing models harder

2019-09-14 Thread Dylan Young
Thanks all!  I remember reading about the zero downtime deployments many
months back and just needed a refresher. I appreciate it.

To sum up for myself: we need to test at every step of the change that the
model changes are in fact backwards compatible with the old state of the
DB.

Makes sense.

Thanks again!

Le sam. 14 sept. 2019 2:44 p.m., Adam Johnson  a écrit :

> (Fixed Ryan's link: https://github.com/aspiredu/django-safemigrate )
>
> On Sat, 14 Sep 2019 at 17:12, Adam Johnson  wrote:
>
>> I'm interested in your use case: why do you need the model changes
>>> without the migrations? I.e. why would you want to be in a state that's
>>> inconsistent between the ORM and the DB?  Is it just so you can recover
>>> more easily if something goes wrong?
>>>
>>
>> It's not that one *wants* to be in that state, it's just inevitable with
>> the goal of zero downtime. With reasonable traffic on even one webserver,
>> it's inevitable there's a gap between the running of migrations and the
>> updating of the webserver to the new code. In this case it's best to make
>> sure both old and new code versions are compatible with the new version of
>> the database.
>>
>> There's plenty out there on the topic. A post I found useful recently was
>> this one from Braintree covering the different ways to help zero downtime
>> deployments PostgreSQL:
>> https://medium.com/braintree-product-technology/postgresql-at-scale-database-schema-changes-without-downtime-20d3749ed680
>>
>> Thanks,
>>
>> Adam
>>
>> On Sat, 14 Sep 2019 at 16:09, Dylan Young 
>> wrote:
>>
>>> Thanks for the tips; I'll take a look at those code paths.
>>>
>>> I'm interested in your use case: why do you need the model changes
>>> without the migrations? I.e. why would you want to be in a state that's
>>> inconsistent between the ORM and the DB?  Is it just so you can recover
>>> more easily if something goes wrong?
>>>
>>> Recent versions of Django make it easier to modify the test command,  so
>>> I may take a look at spinning up an external package for this.
>>>
>>> Le sam. 14 sept. 2019 5:36 a.m., Adam Johnson  a écrit :
>>>
 Hi Dylan,

 In my experience, high availability deployments often need to commit
 model changes without migration changes. For example, when removing a
 (nulable) field, the best approach is to:

1. Remove the field from Django
2. Test
3. Deploy
4. Run makemigrations to generate the migration file that removes
it from the database
5. Test
6. Deploy

 The test run in step 2 should *not* have any automated migrations
 built. The tests should confirm that removing the field from Django without
 removing it from the DB safe.

 If you want to build your suggested behaviour (makemigrations before
 every test run) you can do it by:

1. Creating a custom test runner that subclasses DiscoverRunner
2. Overriding its setup_databases() method to do
call_command('makemigrations') before super()
3. Catching the names of those made migrations, and
overriding teardown_databases() to delete them (or maybe not?)

 I'd be interested to know how that works! I suspect it will be fine for
 smaller projects, but for larger projects that care about preventing
 downtime during deployment, it will backfire.

 As an extra benefit, it makes testing between branches *so much* easier
> because you don't have to worry about rolling back migrations on the
> test_db (a PITA as far as I can see).
>

 If you're using the default behaviour, the test DB is generated on
 every run. The `--keepdb` flag is optional and can be used to speed up test
 runs on the same branch but you should run tests without it after
 switching. I agree it can be a pain.

 Maybe we could have a guard on that flag: detect if git is used, and
 the branch has changed since last run, and then warn or just hard recreate?
 If you'd be interested in exploring this, it can also be tested by
 subclassing the migrate command. Maybe make a ticket?

 Regarding the last, is there a flag to make migrate target the
> test_db(s)?
>

 Not that I know of but I did something similar on one project where I
 had a management command to create a test runner and call its
 setup_databases() method. That should be sufficient!

 Thanks,

 Adam

 On Fri, 13 Sep 2019 at 19:04, Dylan Young 
 wrote:

> This is an old issue that (as far as I can see) was never resolved.
>
> My proposed solution would be a flag to the test command to
> automatically `makemigrations && migrate`.  When this behaviour is 
> enabled,
> it would also roll back any generated migrations at the end of the test
> run.   The flag might not be necessary (could be default behaviour of
> `test`)
>
> This way you get the benefit

Re: Migrations in Django 1.7 make unit testing models harder

2019-09-14 Thread Dan Davis
There is no such flag, at least not in 1.11.  I wrote my own "migratetest"
and "cleandb" commands because my DBAs don't let me drop and recreate
databases.   It is a simple matter if you use the testsuite, but it would
probably be better development to call create_test_db manually and such.


On Fri, Sep 13, 2019 at 2:04 PM Dylan Young 
wrote:

> This is an old issue that (as far as I can see) was never resolved.
>
> My proposed solution would be a flag to the test command to automatically
> `makemigrations && migrate`.  When this behaviour is enabled, it would also
> roll back any generated migrations at the end of the test run.   The flag
> might not be necessary (could be default behaviour of `test`)
>
> This way you get the benefits of all worlds:
> 1) uncommitted migration files will be clearly visible after the test run
> (for those inclined to forget to makemigrations).
> 2) The extraneous non-migration creation code can be removed from Django
> (probably already has been at this point).
> 3) Tests are always run against the current state of models
> 4) Tests are always run at current state of migrations (because it
> generates the migrations).
>
> As an extra benefit, it makes testing between branches *so much* easier
> because you don't have to worry about rolling back migrations on the
> test_db (a PITA as far as I can see).
>
> Regarding the last, is there a flag to make migrate target the test_db(s)?
>
> Best,
>
> Casey
>
> On Tuesday, 25 March 2014 14:21:51 UTC-3, Bernie Sumption wrote:
>>
>> Hi Django devs,
>>
>> I've just started a new project in 1.7b, and the development experience
>> working with unit tests on models is more complicated than it was in 1.6.
>> It's all down to how the throwaway test databases are created. In 1.6, the
>> create_test_db function "Creates a new test database and runs syncdb
>> against it." In 1.7, it runs "migrate".
>>
>> While generally speaking, migrate is the new syncdb, this behaviour is
>> not ideal for tests. In 1.6 "syncdb" created a database reflecting the
>> current state of the models in models.py. "migrate" creates a database
>> reflecting the state of the models at the last time makemigrations was run.
>> If you're doing TDD and constantly making small changes to your models then
>> runnning unit tests, you have to run makemigrations before each test run to
>> get your tests to work. You therefore end up with many tiny migration files
>> representing the minute-by-minute history of development.
>>
>> I came up with a pretty effective workaround that is working for me, but
>> I thought I'd post this here as others are sure to encounter this issue,
>> and I think that it makes more sense for the behaviour produced by this
>> workaround to be the default for running tests.
>>
>> If makemigrations has not yet been run, the "migrate" command treats an
>> app as unmigrated, and creates tables directly from the models just like
>> syncdb did in 1.6. I defined a new settings module just for unit tests
>> called "settings_test.py", which imports * from the main settings module
>> and adds this line:
>>
>> MIGRATION_MODULES = {"myapp": "myapp.migrations_not_used_in_tests"}
>>
>> Then I run tests like this:
>>
>> DJANGO_SETTINGS_MODULE="myapp.settings_test" python manage.py test
>>
>> This fools migrate into thinking that the app is unmigrated, and so every
>> time a test database is created it reflects the current structure of
>> models.py.
>>
>> So my feature request is as follows:
>>
>> If the new behaviour is by design and considered desirable, then it is a
>> big change from the previous version and should be prominently documented
>> in the migrations and testing pages, along with the workaround. I'm happy
>> to write this documentation if that's the way you want to go.
>>
>> However, if the new behaviour is not by design but just a by-product of
>> the new migrations feature, I suggest making the workaround the default
>> behaviour. I don't (yet!) know enough about Django internals to volunteer
>> for this however.
>>
>> Thanks for your time,
>>
>> Bernie :o)
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "Django developers (Contributions to Django itself)" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to django-developers+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-developers/2aee60d5-e96b-4c96-8f87-150d9de46215%40googlegroups.com
> 
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
htt