Slide 1

Slide 1 text

@cmaiacd factory_boy DjangoCon EU 2022 - Porto 󰐨 Camila Maia testing like a pro

Slide 2

Slide 2 text

@cmaiacd You can find this presentation at: speakerdeck.com/cmaiacd

Slide 3

Slide 3 text

@cmaiacd Who am I?

Slide 4

Slide 4 text

@cmaiacd Backend Developer @

Slide 5

Slide 5 text

@cmaiacd Brazilian 󰎙

Slide 6

Slide 6 text

@cmaiacd Living in Berlin 󰎲

Slide 7

Slide 7 text

@cmaiacd Queer 󰝲

Slide 8

Slide 8 text

@cmaiacd 󰘊 󰘋 🐶

Slide 9

Slide 9 text

@cmaiacd Coding since 2010 👵

Slide 10

Slide 10 text

@cmaiacd Python 🐍 and Ruby 💎

Slide 11

Slide 11 text

@cmaiacd Community ❤

Slide 12

Slide 12 text

@cmaiacd Conferences

Slide 13

Slide 13 text

@cmaiacd Open Source ❤

Slide 14

Slide 14 text

@cmaiacd Creator of ScanAPI

Slide 15

Slide 15 text

@cmaiacd +1.5k + 1.2k ⭐

Slide 16

Slide 16 text

@cmaiacd Workshop Tomorrow 4:55 PM 󰠁󰳕

Slide 17

Slide 17 text

@cmaiacd

Slide 18

Slide 18 text

@cmaiacd factory_boy: what is it?

Slide 19

Slide 19 text

@cmaiacd It is a fixtures replacement

Slide 20

Slide 20 text

@cmaiacd Based on factory_bot (Thoughtbot)

Slide 21

Slide 21 text

@cmaiacd First version: Django only Nowadays: framework-independent Unittest, Pytest...

Slide 22

Slide 22 text

@cmaiacd For complex objects: ❌ Fixtures: static, hard to maintain ✅ Factories: easy-to-use

Slide 23

Slide 23 text

@cmaiacd

Slide 24

Slide 24 text

@cmaiacd 🧰 🛠 🔧 ⚙ Sequence Faker Fuzzy attributes LazyFunction LazyAttribute Inheritance Inheritance Params Traits Strategies RelatedFactory / SubFactory

Slide 25

Slide 25 text

@cmaiacd My Experience

Slide 26

Slide 26 text

@cmaiacd +3 years Django Monolith 🐘

Slide 27

Slide 27 text

@cmaiacd +230 tables +2200 relevant files +75k relevant lines

Slide 28

Slide 28 text

@cmaiacd

Slide 29

Slide 29 text

@cmaiacd A poorly designed factory might affect many tests

Slide 30

Slide 30 text

@cmaiacd Implicit errors

Slide 31

Slide 31 text

@cmaiacd The tests are created in a way to fit the factory factory-oriented testing

Slide 32

Slide 32 text

@cmaiacd Factories can get too tied

Slide 33

Slide 33 text

@cmaiacd Developers bump into the same issue again and again

Slide 34

Slide 34 text

@cmaiacd Patterns 👀 Best practices? 🤔

Slide 35

Slide 35 text

@cmaiacd Demo App

Slide 36

Slide 36 text

@cmaiacd Polls

Slide 37

Slide 37 text

@cmaiacd Poll

Slide 38

Slide 38 text

@cmaiacd Results

Slide 39

Slide 39 text

@cmaiacd s

Slide 40

Slide 40 text

@cmaiacd Model - Poll Poll Question Choice n:1 pub_date : DateTimeField premium : BooleanField author : CharField question_text : CharField language : CharField choice_text : CharField votes : IntegerField 1:1

Slide 41

Slide 41 text

@cmaiacd Model - Poll

Slide 42

Slide 42 text

@cmaiacd Model - Poll

Slide 43

Slide 43 text

@cmaiacd Model - Question

Slide 44

Slide 44 text

@cmaiacd Model - Choice

Slide 45

Slide 45 text

@cmaiacd Best Practices

Slide 46

Slide 46 text

@cmaiacd 1. FACTORIES SHOULD REPRESENT THEIR MODELS

Slide 47

Slide 47 text

@cmaiacd Avoid implicit errors

Slide 48

Slide 48 text

@cmaiacd BAD ❌

Slide 49

Slide 49 text

@cmaiacd GOOD ✅

Slide 50

Slide 50 text

@cmaiacd 2. DO NOT RELY ON DEFAULTS FROM FACTORIES

Slide 51

Slide 51 text

@cmaiacd ● If a default value is changed, all tests that depend on it will break ● The setup of a test should contain all the logic to ensure it will always pass ● Explicit better than implicit

Slide 52

Slide 52 text

@cmaiacd BAD ❌

Slide 53

Slide 53 text

@cmaiacd GOOD ✅

Slide 54

Slide 54 text

@cmaiacd 3. FACTORIES SHOULD CONTAIN ONLY THE REQUIRED DATA

Slide 55

Slide 55 text

@cmaiacd If the field is nullable (null=True) the attribute should be under a trait and not as a default value

Slide 56

Slide 56 text

@cmaiacd BAD ❌

Slide 57

Slide 57 text

@cmaiacd GOOD ✅

Slide 58

Slide 58 text

@cmaiacd If we want to have an author, we can use PollFactory(with_author=True) now When are we going to remember to test the case PollFactory(author=None)? We should not assume there is an author when DB actually allows to not have it.

Slide 59

Slide 59 text

@cmaiacd 4. BUILD OVER CREATE

Slide 60

Slide 60 text

@cmaiacd MyFactory.build() creates a local object (memory) MyFactory.create() creates a local object + stores it in the DB

Slide 61

Slide 61 text

@cmaiacd BAD ❌

Slide 62

Slide 62 text

@cmaiacd GOOD ✅

Slide 63

Slide 63 text

@cmaiacd BUILD STRATEGY ========== 14 passed in 1.76 seconds ========== CREATE STRATEGY ========== 14 passed in 3.26 seconds ==========

Slide 64

Slide 64 text

@cmaiacd 5. IF FK IS IN THE TABLE: SUBFACTOR IF FK IS IN THE OTHER TABLE: RELATEDFACTORY + TRAIT

Slide 65

Slide 65 text

@cmaiacd SubFactory: builds/creates the SubFactory during the process of creation of the main factory RelatedFactory: builds/creates the RelatedFactory after creating the main factory

Slide 66

Slide 66 text

@cmaiacd Good ✅

Slide 67

Slide 67 text

@cmaiacd 6. USE FIXTURES TO WRAP FACTORIES TO AVOID DUPLICATION

Slide 68

Slide 68 text

@cmaiacd BAD ❌

Slide 69

Slide 69 text

@cmaiacd GOOD ✅

Slide 70

Slide 70 text

@cmaiacd 7. AVOID SHARING FACTORIES OR FIXTURES AMONG DIFFERENT FILES

Slide 71

Slide 71 text

@cmaiacd Many tests depending on the same factory/fixture

Slide 72

Slide 72 text

@cmaiacd Tends to inflate the factory/fixture

Slide 73

Slide 73 text

@cmaiacd Hard to maintain

Slide 74

Slide 74 text

@cmaiacd Change a factory/fixture… tons of tests breaking

Slide 75

Slide 75 text

@cmaiacd Fixture / Factory oriented testing

Slide 76

Slide 76 text

@cmaiacd Ok, ok, I got it! 😌 Now I know the best practices 💪

Slide 77

Slide 77 text

@cmaiacd So let’s try to fix one first factory… 🤓

Slide 78

Slide 78 text

@cmaiacd

Slide 79

Slide 79 text

@cmaiacd Baby steps 🐣

Slide 80

Slide 80 text

@cmaiacd Código

Slide 81

Slide 81 text

@cmaiacd Official doc 📄 factoryboy.readthedocs.io

Slide 82

Slide 82 text

@cmaiacd Common recipes 󰠉 factoryboy.readthedocs.io/ en/stable/recipes.html

Slide 83

Slide 83 text

@cmaiacd Code github.com/FactoryBoy/ factory_boy

Slide 84

Slide 84 text

@cmaiacd THANK YOU! MUITO OBRIGADA! @cmaiacd camilamaia 󰠁 cmaiacd.com