---
# System prepended metadata

title: Factory Boy

---

# Factory Boy

## What is it?

Factory boy allows us to create factories that will generate fixtures from models using default or provided arguments.

```python=
@dataclass
class Person:
    email: str
    name: str
    phone: str

class PersonFactory(factory.Factory):
    class Meta:
        model = Person

    email = "johnwick@parabellum.net"
    name = "John Wick"
    phone = "555-2077"
```
```shell
(pdb) PersonFactory()
```
```python=
Person(
    email='johnwick@parabellum.net',
    name='John Wick',
    phone='555-2077'
)
```

```shell
(pdb) PersonFactory(name="Jacob Wright")
```
```python=
Person(
    email='johnwick@parabellum.net',
    name='Jacob Wright',
    phone='555-2077'
)
```

```shell
(pdb) PersonFactory(name="Jacob Wright", phone="555-2021")
```
```python=
Person(
    email='johnwick@parabellum.net',
    name='Jacob Wright',
    phone='555-2021'
)
```

Using this we could seriously cut down on our fixture creation files to the bare essentials being changed. This helps with keeping fixtures concise, easy to read, clearer to see what is different between fixtures and overall they are nicer to work with except...

## There's something wrong with it

FactoryBoy isn't perfectly suited to our needs. Ideally on the ROS-Service we would be able to generate our fixtures entirely through factories created by FactoryBoy but this proves to be difficult for several reasons:

### 1) We can't easily convert them to a dict.

FactoryBoy has a feature where you can convert your nice factory into an equally nice dict representation.

```python=
@dataclass
class Person:
    email: str
    name: str
    phone: str

class PersonFactory(factory.Factory):
    class Meta:
        model = Person

    email = "johnwick@parabellum.net"
    name = "John Wick"
    phone = "555-2077"
```

```shell
(pdb) PersonFactory()
```
```python=
Person(
    email='johnwick@parabellum.net',
    name='John Wick',
    phone='555-2077'
)
```

```shell
(pdb) factory.build(dict, FACTORY_CLASS=PersonFactory)
```
```json=
{
    'email': 'johnwick@parabellum.net',
    'name': 'John Wick',
    'phone': '555-2077'
}
```

:chef-ok:

However this functionality seems to break down when it comes to subfactories (Using the above User/UserFactory).

```python=
@dataclass
class Employee:
    uuid: UUID
    person: Person
    
class EmployeeFactory(factory.Factory):
    class Meta:
        model = Employee

    uuid = uuid4()
    person = factory.SubFactory(PersonFactory)
```

```shell
(pdb) EmployeeFactory()
```

```python=
Employee(
    uuid=UUID('10ffd94c-4b6b-4608-ab13-f3b3523c331c'),
    person=Person(
        email='johnwick@parabellum.net',
        name='John Wick',
        phone='555-2077'
    )
)
```
```shell
(pdb) factory.build(dict, FACTORY_CLASS=EmployeeFactory)
```
```json=
{
    'uuid': UUID('10ffd94c-4b6b-4608-ab13-f3b3523c331c'),
    'person': Person(
        email='johnwick@parabellum.net',
        name='John Wick',
        phone='555-2077'
    )
}
```

At first glance the above may look okay but it has some problems.

```shell
(Pdb) import json
(Pdb) json.dumps(factory.build(dict, FACTORY_CLASS=EmployeeFactory))
*** TypeError: Object of type UUID is not JSON serializable

# After making uuid an int
(Pdb) json.dumps(factory.build(dict, FACTORY_CLASS=EmployeeFactory))
*** TypeError: Object of type Person is not JSON serializable
```

1) Our Person class cannot be json serialized through the factory.
2) UUIDs cant be parsed into valid json using the stock json parser.

This means that, while we can use FactoryBoy for input objects, we can't use it to generate our json assertion objects that tests the output responses. 

If we are able to monkey-patch support for these, it would really cut down on a lot of fixture generation.

## What can we do to fix this

Problem one - Converting subfactories to a dict

Problem two - UUIDs and other objects aren't valid json

- We could use another parser that converts uuids to strings, or we could make one ourselves by overriding the default json parser.


### 2) Sequences sort of suck
