Ah yes, flushing, I forgot we did that for lesser DBs. I can think of several solutions: - Run the entire migration set every time you flush the database. This is, obviously, not practicable. - Re-introduce initial_data fixtures; I'd rather not, as these require constant upkeep and interact badly with migrations. - Dump the content of all apps at the start of tests into a file and restore from that after flushes. This is a bit hacky and might use a lot of disk space, but would get the intended effect. - Say that you can't use datamigrations if you have a database without transactions (not ideal)
Nothing here is really a great solution, alas. The fourth one is the easiest solution - tell people to use factories in tests or fixtures if they want that stuff - but slightly undermines the idea of loading initial data in a migration (which is the better way of doing it). Perhaps we should look into deprecating flushing? It's not a behaviour that can be easily replicated any more, as it relied on the old system of one-shot schema and load a single file, but it's also kind of crucial to non-transactional tests... Andrew On Fri, Apr 18, 2014 at 7:56 AM, Christian Schmitt <[email protected] > wrote: > The case is really simple and i think its definitely that would block the > release. > > First off, I have a model: > > from django.db import models > > # Create your models here. > class SimpleModel(models.Model): > name = models.CharField(max_length=10) > > Then I will make some migrations: > # encoding: utf8 > from django.db import models, migrations > > > class Migration(migrations.Migration): > > dependencies = [ > ] > > operations = [ > migrations.CreateModel( > name='SimpleModel', > fields=[ > ('id', models.AutoField(serialize=False, primary_key=True, > verbose_name='ID', auto_created=True)), > ('name', models.CharField(max_length=10)), > ], > options={ > }, > bases=(models.Model,), > ), > ] > Now the second one that loads data: > # encoding: utf8 > from django.db import models, migrations > > > def add_data(apps, schema_editor): > SimpleModel = apps.get_model("new_app", "SimpleModel") > SimpleModel.objects.create(name="simple") > > class Migration(migrations.Migration): > > dependencies = [ > ('new_app', '0001_initial'), > ] > > operations = [ > migrations.RunPython(add_data), > ] > > Now I have a view that makes a get query: > from django.http import HttpResponse > from .models import SimpleModel > > # Create your views here. > def simple(request): > simple = SimpleModel.objects.get(name="simple") > return HttpResponse(simple) > > The urls will have the / url pointing to our view. > > And finally the test: > from django.test import TransactionTestCase > from .models import SimpleModel > > # Create your tests here. > class SimpleTestView(TransactionTestCase): > > def test_data_migration(self): > response = self.client.get('/') > self.assertEqual(response, not False) > > And it will fail. > But it will not fail cause of maybe a bad test, even if my test wouldn’t > be correct it would still fail. > It will fail cause of this: > ====================================================================== > ERROR: test_data_migration (new_app.tests.SimpleTestView) > ---------------------------------------------------------------------- > Traceback (most recent call last): > File "/Users/schmitch/PycharmProjects/testing/new_app/tests.py", line 8, > in test_data_migration > response = self.client.get('/') > File > "/Users/schmitch/PycharmProjects/envisia_erp_server/.venv/lib/python3.4/site-packages/django/test/client.py", > line 467, in get > **extra) > File > "/Users/schmitch/PycharmProjects/envisia_erp_server/.venv/lib/python3.4/site-packages/django/test/client.py", > line 285, in get > return self.generic('GET', path, secure=secure, **r) > File > "/Users/schmitch/PycharmProjects/envisia_erp_server/.venv/lib/python3.4/site-packages/django/test/client.py", > line 355, in generic > return self.request(**r) > File > "/Users/schmitch/PycharmProjects/envisia_erp_server/.venv/lib/python3.4/site-packages/django/test/client.py", > line 437, in request > six.reraise(*exc_info) > File > "/Users/schmitch/PycharmProjects/envisia_erp_server/.venv/lib/python3.4/site-packages/django/utils/six.py", > line 536, in reraise > raise value > File > "/Users/schmitch/PycharmProjects/envisia_erp_server/.venv/lib/python3.4/site-packages/django/core/handlers/base.py", > line 113, in get_response > response = wrapped_callback(request, *callback_args, **callback_kwargs) > File "/Users/schmitch/PycharmProjects/testing/new_app/views.py", line 6, > in simple > simple = SimpleModel.objects.get(name="simple") > File > "/Users/schmitch/PycharmProjects/envisia_erp_server/.venv/lib/python3.4/site-packages/django/db/models/manager.py", > line 92, in manager_method > return getattr(self.get_queryset(), name)(*args, **kwargs) > File > "/Users/schmitch/PycharmProjects/envisia_erp_server/.venv/lib/python3.4/site-packages/django/db/models/query.py", > line 352, in get > self.model._meta.object_name) > new_app.models.DoesNotExist: SimpleModel matching query does not exist. > > > I don’t even need to test the view. i could test another view. The Test > client will always fail if there is a view somewhere that makes some get > queries where the data isn’t there. > > here the next test i made: > def test_another_thing(self): > self.user = User.objects.create_user("testuser", "[email protected]", > "sample_pass") > login = self.client.login(username="testuser", > password="sample_pass") > self.assertEqual(True, True) > > It shouldn’t fail. I mean i didn’t even query the view. i just login a > user and get the same error. > > I don’t think this is the way how tests should run. I also tried > TransactionTestCase and TestCase on PostgreSQL, Sqlite3, and MySQL. Same > results, every database. > > Btw. if I have some more Logic applied around the get it wouldn’t be a > problem, but we have some views where NOBODY could delete these get() > queries, so we rely on them and they will fail, if we try to make tests. > Too bad our application is now too big to think about application design, > i also think its „impractical“ but i don’t think i’m the only one. the same > problems have/had fixtures as well. > > Currently my way to fix it will be to rewrite everything and don’t really > on data that needs to be in the database. or i don’t make integrations > tests via the django client. i mean the application is so big that it takes > up to 5 seconds to create the test database. which is intact a lot. > > > but that has nothing to do with the fact, that data migrations are in the > docs. so we should warn that this will make it harder to test your > application if you rely on that data. especially when you query with get(). > > > > — > Best Regards > > Christian Schmitt > [email protected] > > > > > Am 17.04.2014 um 22:42 schrieb Andrew Godwin <[email protected]>: > > Hi Christian, > > Can you explain your situation more, and perhaps give us some example > files or console output? When you run tests they should run through all the > migrations first, so any initial data should get loaded in before tests > begin. > > Andrew > > > On Thu, Apr 17, 2014 at 1:16 PM, Christian Schmitt < > [email protected]> wrote: > >> Hello, >> >> currently I try to make a TestSuite for a already grown application and >> it is horrible to do so. >> But thats not why I'm writing here. >> >> Our Application has some data migrations, previously we used South, now >> we use the Django 1.7 Migrations with RunPython to do so. >> >> In the Docs there is also a Article how to do it: >> https://docs.djangoproject.com/en/dev/topics/migrations/#data-migrations >> Currently If you load initial data with a RunPython command that your App >> Depends on (there are some cases, not many, but some) you will fail hard. >> Your Unittests starting to fail. And that is not good, so i think we >> should either change something on the Test Suites or we should make it >> clear that Data Migrations for initial data is a bad idea or maybe warn >> about the drawbacks with Test Cases. >> I'm really new to testing and I really needed to figure out whats going >> on first until I realized that this behavior comes from the TestSuite. >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Django developers" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> To post to this group, send email to [email protected]. >> Visit this group at http://groups.google.com/group/django-developers. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/django-developers/768969da-8f75-4402-80a5-c30c27c74997%40googlegroups.com<https://groups.google.com/d/msgid/django-developers/768969da-8f75-4402-80a5-c30c27c74997%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> For more options, visit https://groups.google.com/d/optout. >> > > > -- > You received this message because you are subscribed to the Google Groups > "Django developers" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/django-developers. > To view this discussion on the web visit > https://groups.google.com/d/msgid/django-developers/CAFwN1uqasqm17EKHg1PrL5HbJaE3W2hVn%3DBe3wd45yxKRDR04w%40mail.gmail.com<https://groups.google.com/d/msgid/django-developers/CAFwN1uqasqm17EKHg1PrL5HbJaE3W2hVn%3DBe3wd45yxKRDR04w%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > > For more options, visit https://groups.google.com/d/optout. > > > -- You received this message because you are subscribed to the Google Groups "Django developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/django-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/CAFwN1uriM38iotsEi8s66q_trGQdY2P5F0CioFWbVFe%2BYjmf6w%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
