Open 3ynm opened 7 years ago
Indeed: factory.Faker.override_default_locale()
is a decorator and context manager: you can only use it as:
with factory.Faker.override_default_locale('es_ES'):
e1 = ExampleFactory()
Or:
@factory.Faker.override_default_locale('es_ES')
def test_foo(self):
e1 = ExampleFactory()
The idea is that changing the default locale is mostly used for a few specific tests while the whole suite doesn't care; hence, having a decorator/context manager ensures that the default locale is restored once those tests have run.
However, this is not very clear in the docs; I think we should improve them. Alternatively, we could add an extra entrypoint to set the global, initial configuration for Faker (including adding extra providers).
Indeed I think allowing to set a global language is a must, thanks :)
By the way, global configuration for additional provider does work.
I agree with @Hacktivista that an easy (and preferably randomizable) way to change the locale would be a major advantage. Right now I am considering using vanilla faker via a custom fake
fixture that does just that. It would be nice to have something similar with factory_boy's otherwise lovely faker integration.
If thats something you would be interested in getting a PR please let me know.
This is something I'd also find useful. I also think it might be useful to be able to attach an existing faker generator, so I filed a ticket: https://github.com/FactoryBoy/factory_boy/issues/554
I was about to create a new issue. But found this one. Even with some feedback from me :)
I looked into it once again. There are basically 2 ways.
As one might find out, the default locale is taken from faker
. But setting the default locale is not covered by the faker
's documentation. The good news is that with faker
it's probably not that important, since usually you specify the locale once, when you instantiate the generator (e.g. Faker(locale='...')
). I tried looking into changing faker
's default, but first, faker
's and factory-boy
's default locales are default in different ways. Second, I couldn't easily find a way such that I'd be sure I don't introduce issues.
Another option is to do:
factory.Faker._DEFAULT_LOCALE = '...'
after importing factory
. And apparently before declaring factories. This one will probably work out. But I don't like this underscore in front of the name. And the fact that it's not documented.
@rbarrois Do you think the second way can be considered official (except for underscore)? Or do you have any better suggestions?
UPD But considering that Django project may contain several applications. It doesn't seem right to change the default locale in just one of the them. Some centralized way would probably be preferable.
So, let's look at the different situations where one might want to change the default locale:
with override_default_locale():
@override_default_locale()
@override_default_locale()
might not be enough hereFor the last two cases, we'll have to look into the program setup:
with override_default_locale()
within the program's main()
functionFor Django, I believe that the recommended mode is to:
DiscoverRunner
run_tests
function, to wrap the initial method inside a with override_default_locale()
TEST_RUNNER
to your class:# settings.py
TEST_RUNNER = 'myproject.testing.MyTestRunner'
# myproject/testing.py
import factory
from django.conf import settings
from django.util import translation
import django.test.runner
class MyTestRunner(django.test.runner.DiscoverRunner):
def run_tests(self, test_labels, extra_tests=None, **kwargs):
with factory.Faker.override_default_locale(translation.to_locale(settings.LANGUAGE_CODE)):
return super().run_tests(test_labels, extra_tests=extra_tests, **kwargs)
@rbarrois Oh, it appears I've got my case covered. Do you think we can document it? Supposedly by adding a common recipe?
For pytest django I just put it in conftest.py since that loads before any tests start:
import faker.config
faker.config.DEFAULT_LOCALE = "en_NZ"
Works a charm, if you check the Faker class, it populates _DEFAULT_LOCALE from there.
Indeed, just importing factory
or faker
doesn't make use of the faker.config.DEFAULT_LOCALE
value. So sounds safe.
Although I'd like to point out at a slight distinction between factory-boy
's and faker
's default locales. For factory-boy
the default locale is a locale used when no locale is specified. That is true for faker
as well. But in addition faker
falls back to the default locale if a provider doesn't support the locale you demanded and doesn't provide its own fallback. For now the only unlocalized provider that doesn't support en_US
is the bank
provider, but it provides a fallback.
In other words, changing factory-boy
's and faker
's default locales might have different effects.
How can I set the default locale in Python's factory_boy for all of my Factories?
In docs says that one should set it with factory.Faker.override_default_locale but that does nothing to my fakers...