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

[guides] Testing - how to set up rom-factories #275

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions source/4.0/guides/index.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: Guides
sections:
- sql-quick-start
- testing
- sql-how-to
---

Expand Down
140 changes: 140 additions & 0 deletions source/4.0/guides/testing/factories.html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
chapter: Testing
title: Factories
---

When using ROM, you will need to test your code, and testing your code implies generating entities and use Factories to
create records on your database. To do all of that, you can use `rom-factory`, which provides more or less same
functionnalities as `FactoryBot`.

### Install RomFactory

In your gemfile:

```ruby
gem 'rom-factory'
```

### Setup ROMFactory

Then on your spec root file (like `spec_helper`), you have to initialize your factory:

```ruby
# Build database configuration
db_config = {
adapter: 'mysql2',
database: 'db_name',
host: 'database.host.io',
username: 'username',
password: 'password',
port: 3306
}

# Init your ROM container
rom = ROM.container(:sql, db_config)do |config|
# Register ROM related files, especially Relations
config.auto_registration('../app/') # if your sources are in app folder
end

# Declare your factory
YourFactory = ROM::Factory.configure do |config|
config.rom = rom
end

# Load your factories' files
Dir[App.root + '/spec/factories/**/*.rb'].each { |f| require f } # if you plan to put your factory files `spec/factories`
```

### Define your factory

Then you can define your factories:

```ruby
YourFactory.define(:user) do |f|
f.sequence(:name) { |n| "User#{n}" }
f.website 'http://personal.website'
f.some_integer 42
f.created_at Time.now.utc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make generating the time a block, so each created record has a new timestamp. This is more realistic in testing since records created later in the spec will have an increasing created_at

end
```

You can define multiple builders on the same factory.
In this example, the relation `users` (ie builder name pluralized) must exist in your ROM::RelationRegistry`.

### Use your factory

In your tests, you can either get an instance from your factory only in memory, or in memory but that has been
persisted on your database.

Let's suppose that `UserRepo` is your Users' repository and it has a relation to `users` SQL table.

```ruby
user1 = YourFactory[:user]
p user1
#=> #<ROM::Struct::User id=84 name="User1" website="http://personnal.website" some_integer=42 created_at=2019-04-02 08:50:34 +0000>

p UserRepo.users.by_pk(user1.id).one
#=> #<ROM::Struct::User id=84 name="User1" website="http://personnal.website" some_integer=42 created_at=2019-04-02 08:50:34 +0000>

user2 = YourFactory.structs[:user]
p user2
#=> #<ROM::Struct::User id=85 name="User2" website="http://personnal.website" some_integer=42 created_at=2019-04-02 08:50:46 +0000>

p UserRepo.users.by_pk(user2.id).one
#=> nil

user3 = YourFactory.structs[:user, name: "toto", website: nil]
p user3
#=> #<ROM::Struct::User id=85 name="toto" website=nil some_integer=42 created_at=2019-04-02 08:51:20 +0000>
```

### Going further

#### Associations

RomFactory supports associations that you declared in your Relations.
```ruby
YourFactory.define(:user) do |f|
# this will use :team builder to create a team for a user
f.association(:team)

# this will create 2 posts for a user using :post builder
f.association(:posts, count: 2)
end
```

#### Faker

ROMFactory comes with Faker gem:

```ruby
YourFactory.define(:foo) do |f|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename YourFactory to Factory

f.bar { fake(:number, :between, 10, 100) }
end
```

#### Traits

ROMFactory supports traits:

```ruby
YourFactory.define(:user) do |f|
f.registered true

f.trait :not_registered do |t|
t.registered false
end
end

p YourFactory[:user, :not_registered]
#=> #<ROM::Struct::User id=130 registered=false>
```

### Inheritance
You can extend existing builders, see [Rom Factory annoncement](https://rom-rb.org/blog/announcing-rom-factory/) for an
example.


### Read more:
* [Rom Factory annoncement](https://rom-rb.org/blog/announcing-rom-factory/)
* [Rom Factory repository](https://github.com/rom-rb/rom-factory/)
7 changes: 7 additions & 0 deletions source/4.0/guides/testing/index.html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
chapter: SQL How To
sections:
- factories
---

In this section you can learn some tricks to test your code when using ROM.
1 change: 1 addition & 0 deletions source/5.0/guides/index.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Guides
sections:
- sql-quick-start
- sql-how-to
- testing
---

Guides are a collection of short articles explaining how to achieve common tasks
Expand Down
140 changes: 140 additions & 0 deletions source/5.0/guides/testing/factories.html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
chapter: Testing
title: Factories
---

When using ROM, you will need to test your code, and testing your code implies generating entities and use Factories to
create records on your database. To do all of that, you can use `rom-factory`, which provides more or less same
functionnalities as `FactoryBot`.

### Install RomFactory

In your gemfile:

```ruby
gem 'rom-factory'
```

### Setup ROMFactory

Then on your spec root file (like `spec_helper`), you have to initialize your factory:

```ruby
# Build database configuration
db_config = {
adapter: 'mysql2',
database: 'db_name',
host: 'database.host.io',
username: 'username',
password: 'password',
port: 3306
}

# Init your ROM container
rom = ROM.container(:sql, db_config)do |config|
# Register ROM related files, especially Relations
config.auto_registration('../app/') # if your sources are in app folder
end

# Declare your factory
YourFactory = ROM::Factory.configure do |config|
config.rom = rom
end

# Load your factories' files
Dir[App.root + '/spec/factories/**/*.rb'].each { |f| require f } # if you plan to put your factory files `spec/factories`
```

### Define your factory

Then you can define your factories:

```ruby
YourFactory.define(:user) do |f|
f.sequence(:name) { |n| "User#{n}" }
f.website 'http://personal.website'
f.some_integer 42
f.created_at Time.now.utc
end
```

You can define multiple builders on the same factory.
In this example, the relation `users` (ie builder name pluralized) must exist in your ROM::RelationRegistry`.

### Use your factory

In your tests, you can either get an instance from your factory only in memory, or in memory but that has been
persisted on your database.

Let's suppose that `UserRepo` is your Users' repository and it has a relation to `users` SQL table.

```ruby
user1 = YourFactory[:user]
p user1
#=> #<ROM::Struct::User id=84 name="User1" website="http://personnal.website" some_integer=42 created_at=2019-04-02 08:50:34 +0000>

p UserRepo.users.by_pk(user1.id).one
#=> #<ROM::Struct::User id=84 name="User1" website="http://personnal.website" some_integer=42 created_at=2019-04-02 08:50:34 +0000>

user2 = YourFactory.structs[:user]
p user2
#=> #<ROM::Struct::User id=85 name="User2" website="http://personnal.website" some_integer=42 created_at=2019-04-02 08:50:46 +0000>

p UserRepo.users.by_pk(user2.id).one
#=> nil

user3 = YourFactory.structs[:user, name: "toto", website: nil]
p user3
#=> #<ROM::Struct::User id=85 name="toto" website=nil some_integer=42 created_at=2019-04-02 08:51:20 +0000>
```

### Going further

#### Associations

RomFactory supports associations that you declared in your Relations.
```ruby
YourFactory.define(:user) do |f|
# this will use :team builder to create a team for a user
f.association(:team)

# this will create 2 posts for a user using :post builder
f.association(:posts, count: 2)
end
```

#### Faker

ROMFactory comes with Faker gem:

```ruby
YourFactory.define(:foo) do |f|
f.bar { fake(:number, :between, 10, 100) }
end
```

#### Traits

ROMFactory supports traits:

```ruby
YourFactory.define(:user) do |f|
f.registered true

f.trait :not_registered do |t|
t.registered false
end
end

p YourFactory[:user, :not_registered]
#=> #<ROM::Struct::User id=130 registered=false>
```

### Inheritance
You can extend existing builders, see [Rom Factory annoncement](https://rom-rb.org/blog/announcing-rom-factory/) for an
example.


### Read more:
* [Rom Factory annoncement](https://rom-rb.org/blog/announcing-rom-factory/)
* [Rom Factory repository](https://github.com/rom-rb/rom-factory/)
7 changes: 7 additions & 0 deletions source/5.0/guides/testing/index.html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
chapter: SQL How To
sections:
- factories
---

In this section you can learn some tricks to test your code when using ROM.