Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fuzzy decimal using decimals #849

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

melvyn-apryl
Copy link

Add FuzzyDecimalDec: a random decimal generator that is bound by decimals.

Use cases:

  • bounds are set by model fields that have decimal values, such as generating the amount used of a budget (easy of use)
  • bounds are assumed to be precise and part of complex calculations, which can result in incorrect test results, due to rounding (accuracy)

Implementation:

  • Converts bounds arguments to decimals before calculating the value
  • Reimplements random.Random().uniform() to avoid the TypeError caused by random.Random().random() returning floats.

Convert high and low to float explicitly, before passing them to
Random().uniform() as it does a calculation there with float values. If
a Decimal is passed in as argument (for example from a Django decimal or
money field), then this will fail.

This isn't the best solution, but it's the least invasive.

The better would be to reimplement Random().uniform as
factory.random.decimal_uniform and cast everything to Decimals. This
would retain input accuracy, but tests monkey patching uniform() would
have to be changed and this reimplementation must be kept in line with
its counterpart in the Python Standard Library.
Introduce a second FuzzyDecimal type and leave the old one alone, as it
works for most cases.

Add another and reimplement Random.uniform() within the library. Add a
testcase illustrating the issue with the standard FuzzyDecimal.
@francoisfreitag
Copy link
Member

Hi, thanks for the patch.

The project has been pushing the generation of values to the Faker library.

Most fuzzy attributes are deprecated, replaced by their Faker alternatives, see the note at the beginning of https://factoryboy.readthedocs.io/en/latest/fuzzy.html#module-factory.fuzzy.

The recommended way to add support for decimal is to add decimal generation to Faker, then use factory.Faker in your project.

@melvyn-apryl
Copy link
Author

melvyn-apryl commented Apr 26, 2021

OK, so why is Fuzzy still in after almost 5 years? Is there even a branch yet to investigate what its removal would entail?

P.S.: I also think Fuzzy and Faker solve a different problem. Faker generates domain-specific data, localized and all. Fuzzy is about providing values which are either too specific to be useful to other applications or where you don't care about the values as long as they are within the specified range. But if Faker is willing to expand its horizon, I'd be happy to contribute.

@francoisfreitag
Copy link
Member

OK, so why is Fuzzy still in after almost 5 years? Is there even a branch yet to investigate what its removal would entail?

Removing the fuzzy fields will cause breakage in projects relying on them. The main reason is probably because the fuzzy fields aren’t a huge maintenance burden and breaking many projects is not worth it. Newer projects should prefer Faker and at least some fuzzy fields may eventually be removed, but there’s no rush.

Replacing the implementation of fuzzy fields with their Faker equivalent has been discussed privately. I think most of the maintainers agree that should be done, but no one has worked on it for a long time.

If you are interested in such a contribution, I believe #271 (comment) and #756 are good reads.

The deprecation of fuzzy fields is a signal that FactoryBoy does not intend on generating “good” random values for fields. If you want to generate random data, Faker is the recommended approach. That also means providers of random data should preferably be added to Faker.

I also think Fuzzy and Faker solve a different problem. Faker generates domain-specific data, localized and all.

It is able to do all that, but also to simply generate “simple” python types. Look at the Python provider. It seems Faker already knows how to generate a Python Decimal:
https://faker.readthedocs.io/en/master/providers/faker.providers.python.html#faker.providers.python.Provider.pydecimal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants