cordery / django-countries-plus

Django model & fixture representing all top level country data from Geonames.org
MIT License
45 stars 23 forks source link

Provide factories for tests #3

Closed blueyed closed 2 years ago

blueyed commented 9 years ago

Since data migrations are problematic in tests, and it may be faster to not rely on them (e.g. with pytest-django's --reuse-db), it would be helpful to have factories for this.

I am using factory-boy myself. Do you think it makes sense to provide factories through django-countries-plus itself?

(the same applies to django-languages-plus)

For example:

class CountryFactory(factory.django.DjangoModelFactory):
    """Factory for a Country"""
    class Meta:
        model = 'countries_plus.models.Country'
        django_get_or_create = ('name', 'iso')

    name = factory.Sequence(lambda n: "Country %d" % n)
    iso = factory.Sequence(lambda n: str(n))
    iso3 = factory.Sequence(lambda n: str(n))
    iso_numeric = factory.Sequence(lambda n: n)
cordery commented 9 years ago

The test structure (including data migrations) has been refactored. Countries plus no longer uses data migrations. I considered using factories, but frankly the model does virtually no work so unless the current tests are insufficient, I don't think this is required.

blueyed commented 9 years ago

Cool. What's the suggested method for your own tests then, where data from countries_plus is used? Calling the update_countries_plus management command?

cordery commented 9 years ago

I apologize, I hadn't really thought about it from the point of view of providing a factory so other apps can use it during testing. I can see how this would be useful. I suppose its similar to the RequestFactory built into django. If you'd like to submit a PR adding this I'd appreciate it.

As no object relationships were being tested in the internal tests, no factory was needed (didn't really speed anything up vs creating a couple test objects manually). In the tests.py file you'll see that it uses a few different strategies, depending on what's tested: creating a country or two manually, loading fixtures using the fixtures =['fixture'] property on the test, and by directly calling the update_countries_plus function. I'd say skip the last two as they will slow down your tests unless you really need them.

blueyed commented 9 years ago

I suppose its similar to the RequestFactory built into django. If you'd like to submit a PR adding this I'd appreciate it.

I am using the one from the original comment, which is based on factory_boy.

I am using it like this in a test, where I want to check that a method sets a specific Country for an object:

germany = CountryFactory(name='Germany', iso='DE', iso3='DEU',
                         iso_numeric=276)

There's no real benefit compared to Country.objects.get_or_create() in this simple case though, so I'm not sure if shipping the factory would be useful.

(the factory becomes useful when you want to auto-generate multiple countries etc)