This comes from Python's parsing rules.
Why?
When you write this:
class UserFactory(factory.django.DjangoModelFactory):
⋮
traffic_source = random.choice(['XYZ', 'ABC', '123', '456'])
Python will execute the following steps:
Read the class declaration body;
Reach the line
traffic_source = random.choice(['XYZ', 'ABC', '123', '456']);Evaluate the call to
random.choice, which might return'ABC';Once each line of the class body has been read (and its function calls evaluated), create the class:
UserFactory = type( name='UserFactory', bases=[factory.django.DjangoModelFactory], {'traffic_source': 'ABC', … }, )
As you can see, the call to random.choice is performed only once, when parsing the class declaration.
This is, basically, the reason for all the factory.XXX declarations: they yield an object that will only execute its specific rules when building an instance from the factory.
So, what should you do?
Here, you should use:
- Either
factory.Fakerusing Faker's random_element provider; - Or
factory.fuzzy.FuzzyChoice:
class UserFactory(factory.django.DjangoModelFactory):
⋮
traffic_source = factory.Faker('random_element', elements=['XYZ', 'ABC', '123', '456'])
alt_traffic_source = factory.fuzzy.FuzzyChoice(['XYZ', 'ABC', '123', '456'])
The main difference between factory.Faker('random_choices') and factory.fuzzy.FuzzyChoices is that factory.fuzzy.FuzzyChoices supports lazily evaluating generators; this is useful if you want to choose from a queryset:
factory.Faker('random_element', elements=Company.objects.all())will perform a DB query at import time;factory.fuzzy.FuzzyChoice(Company.objects.all())will only query the DB the first timeUserFactory.create()is called.
This comes from Python's parsing rules.
Why?
When you write this:
class UserFactory(factory.django.DjangoModelFactory):
⋮
traffic_source = random.choice(['XYZ', 'ABC', '123', '456'])
Python will execute the following steps:
Read the class declaration body;
Reach the line
traffic_source = random.choice(['XYZ', 'ABC', '123', '456']);Evaluate the call to
random.choice, which might return'ABC';Once each line of the class body has been read (and its function calls evaluated), create the class:
UserFactory = type( name='UserFactory', bases=[factory.django.DjangoModelFactory], {'traffic_source': 'ABC', … }, )
As you can see, the call to random.choice is performed only once, when parsing the class declaration.
This is, basically, the reason for all the factory.XXX declarations: they yield an object that will only execute its specific rules when building an instance from the factory.
So, what should you do?
Here, you should use:
- Either
factory.Fakerusing Faker's random_element provider; - Or
factory.fuzzy.FuzzyChoice:
class UserFactory(factory.django.DjangoModelFactory):
⋮
traffic_source = factory.Faker('random_element', elements=['XYZ', 'ABC', '123', '456'])
alt_traffic_source = factory.fuzzy.FuzzyChoice(['XYZ', 'ABC', '123', '456'])
The main difference between factory.Faker('random_choices') and factory.fuzzy.FuzzyChoices is that factory.fuzzy.FuzzyChoices supports lazily evaluating generators; this is useful if you want to choose from a queryset:
factory.Faker('random_element', elements=Company.objects.all())will perform a DB query at import time;factory.fuzzy.FuzzyChoice(Company.objects.all())will only query the DB the first timeUserFactory.create()is called.
While not truly random, the effect you're looking for when choosing from among a set of pre-existing records can also be achieved by using FactoryBoy's Iterator, which can also work with a QuerySet. For example, here I wanted every object to be created by someone different from the set of existing fake users:
from django.contrib.auth import get_user_model
...
# Then, within a factory class, for one of the fields:
created_by = factory.Iterator(get_user_model().objects.all())
Since Faker v6.3.0, the following 2 methods should do the trick:
faker.helpers.arrayElement(doc)faker.helpers.arrayElements(doc)
You can generate a number between 0 and the number of words you have and access the words using an array
const words = ["foo", "bar", "baz"]
const randomNumber = faker.datatype.number({
'min': 0,
'max': words.length - 1
});
console.log(words[randomNumber])
You'll not need a FuzzyAttribute.
You can either restrict the values possible and only give the int value of each product type to FuzzyChoice by doing something like this:
from factory import fuzzy
PRODUCT_IDS = [x[0] for x in IceCreamProduct.PRODUCT_TYPES]
class IceCreamProductFactory(factory.django.DjangoModelFactory):
class Meta:
model = IceCreamProduct
type = fuzzy.FuzzyChoice(PRODUCT_IDS)
It should do the work.
Please be aware that fuzzy module has been deprecated recently, see Fuzzy Attributes Documentation, you may want to use a LazyFunction instead.
You can do as easy as this
class IceCreamProductFactory(factory.django.DjangoModelFactory):
icecream_flavour = factory.Faker(
'random_element', elements=[x[0] for x in IceCreamProduct.PRODUCT_TYPES]
)
class Meta:
model = IceCreamProduct
PS. Don't use type as attribute, it is a bad practice to use a built-in function name as an attribute
Update 2023 for v8
Now moved to https://github.com/faker-js/faker, they changed it again:
faker.number.int(options: number | {
max: number,
min: number
} = {}): number
faker.number.int() // 2900970162509863
faker.number.int(100) // 52
faker.number.int({ min: 1000000 }) // 2900970162509863
faker.number.int({ max: 100 }) // 42
faker.number.int({ min: 10, max: 100 }) // 57
source: https://fakerjs.dev/api/number.html#int
Update 2021
Latest versions changed location of the function from faker.random.number to faker.datatype.number, https://github.com/Marak/faker.js/issues/1156
Original answer
You need to give an object to the function:
faker.datatype.number({
'min': 10,
'max': 50
});
So if you just pass a number, it will set it as the max value. The min value is 0 by default.
This is the implementation of the number function :
this.number = function (options) {
if (typeof options === "number") {
options = {
max: options
};
}
options = options || {};
if (typeof options.min === "undefined") {
options.min = 0;
}
if (typeof options.max === "undefined") {
options.max = 99999;
}
if (typeof options.precision === "undefined") {
options.precision = 1;
}
// Make the range inclusive of the max value
var max = options.max;
if (max >= 0) {
max += options.precision;
}
var randomNumber = options.precision * Math.floor(
mersenne.rand(max / options.precision, options.min / options.precision));
return randomNumber;
}
From Fakerjs github
Whole Number faker. random.number(min,max) Random number between 0 and "range".
faker.random.number(100); //returns 92
faker.random.number({min:5, max:10}); //returns 9
Decimal number faker. finance.amount(min,max,decimal places) Random number between "min" and "max" including decimals to X digits.
faker.finance.amount(9000,10000,4); //returns 9948.8363
Boolean faker. random.boolean()
faker.random.boolean(); //returns true
Array Element faker. random.arrayElement(array[]) Selects a random element from an array of possible values. This function is useful to create custom lists of possibilities.
faker.random.arrayElement(["one","two","three","four"]); //returns "two"
var phTyp = faker.random.arrayElement(["cell","work","home"]); //returns "work"
Object Element faker. random.objectElement(object{}) Selects a random element from an object, selects the value not the keys. This function is useful to create custom lists of possibilities.
faker.random.objectElement({one: 1, two: 2, three: 3}); //returns 3