Skip to content
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
8 changes: 5 additions & 3 deletions docs/rails/on_boarding/01_base/chapter_III.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ These topics are still the most basic so you don't need to build or model a very

# Let's do some basic code

> create a simple rails application MVC
> open a git repository and give access to your tutor
> IF you have time deploy it, you can choose the platform (render.com, heroku.com)
> Create a simple Rails application MVC, preferably with Postgres as the database

> Open a Git repository and give access to your tutor

> If you have time deploy it, you can choose the platform (render.com, heroku.com)

Let's build an application from scratch. The application will have as its theme the sale of ebooks online. A virtual store where you will have sellers and buyers. You won't have to implement the cart's logic, but some functionalities related to some actions that are performed when buying an item.

Expand Down
62 changes: 62 additions & 0 deletions docs/rails/on_boarding/02_rspec/chapter_I.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Chapter I
`(avr. time for this chapter: TBD)`

Tests are a important aspect of any project, serving as a vital checkpoint to ensure that everything functions as intended while preventing any unforeseen issues that may arise when introducing new features.

As such, the quality of a project is heavily influenced by the quality of its tests.

In this chapter, you will acquire a comprehensive understanding of RSpec, a testing tool designed specifically for Ruby and rooted in the principles of Behavior Driven Development (BDD). RSpec equips you with a rich array of features that facilitate a flexible and easily comprehensible syntax for your tests.

You will also learn about some useful gems that enhance RSpec's capabilities in specific situations, such as FactoryBot, VCR, Timecop and others.

>Before starting, ensure that you have completed the RSpec course [Testing Ruby with RSpec: The Complete Guide](https://www.udemy.com/course/testing-ruby-with-rspec/) as well as the `01_base` section.

>If you have any questions or require access credentials, do not hesitate to reach out to your mentor.

## Factories

[FactoryBot](https://github.com/thoughtbot/factory_bot) proves to be an useful gem, enabling you to define prototypes for models that can be seamlessly integrated into your specs.

This is very helpful for enhancing the organization of your specs, as it consolidates the creation process for any object related to a particular model.

For more comprehensive insights into FactoryBot and its practical implementation, consult their documentation available in their [wiki](https://github.com/thoughtbot/factory_bot/wiki).

As a practical step, create factories for `Book`, `Order`, and `User` models.

## Models

Model tests are very important because they will ensure your models keep respecting all the rules you have defined for them.

These tests should be comprehensive, addressing any and all restrictive behaviors associated with the model's attributes.

Create the necessary specs to validate the behavior of all your models.

## Requests

Every route that the server accepts should be tested for both the error and success conditions and their results.

This includes testing several aspects of the server's routes, including but not limited to authentication, parameter validation, and operational success constraints.

Create the necessary specs to validate all routes of your project server open for communication.

## Routing

A good practice for testing a project is to verify its capability to correctly route each declared route to the corresponding controller methods.

Create the necessary specs to validate your project routing to their corresponding controllers.

## Aggregating failures

When incorporating multiple expectations within a single spec, there is an option to aggregate failures, meaning that all expectations are executed, providing a comprehensive view of all potential issues rather than halting at the first failure.

This aggregation of failures offers the advantage of more informative error messages, which can be particularly helpful during troubleshooting. However it comes at a high cost of performance.

> Considering the small size of this project, it is in our best interest to aggregate all failures. This approach simplifies the process of identifying problems and their respective solutions at the start of the project, ensuring a smoother testing and debugging experience.

## Coumpound expectations

There are often situations where you'll find the need to set expectations multiple times for the same object.

In such cases, it's considered a best practice to employ compound expectations. This not only helps in reducing the size of your specs but also enhances their readability.

With this in mind use coumpound expectations for any specs you seem fit.
66 changes: 66 additions & 0 deletions docs/rails/on_boarding/02_rspec/chapter_II.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Chapter II
`(avr. time for this chapter: TBD)`

While creating specs, you may encounter certain constraints that limit the capabilities of RSpec. For example, these constraints could include factors like testing time limitations or the need to handle external API requests.

In this chapter, you'll get to know some gems that can be integrated with RSpec to overcome such limitations.

## VCR

External API requests can often be a liability for your specs. You can't control the data they provide and any changes made to its response contents may break your specs.

[VCR](https://github.com/vcr/vcr) is a gem which allows you to record HTTP interactions and reply them during future test runs for fast, deterministic, accurate tests.

The code snippet below replicates an external API call designed to retrieve book reviews.

Add it to your Books Controller and then create the necessary specs you seem fit to test this method.

> After the inclusion of the provided code snippet, you may need to create migration to ensure its proper functionality. This is necessary as you may not have all the required columns in place.

```
# GET /books/ratings
def refresh_ratings
# make a request to the api
# get the ratings and the book title & author
require 'open-uri'
# the following url simulates a service call that returns 5 fake user objects
url = 'https://random-data-api.com/api/users/random_user?size=5'
json = get(url)
json.each do |element|
user = User.create(
name: element['username'],
email: element['email'],
password: 'password',
confirmed_at: Time.zone.now
)

book = Book.find_or_create_by(
id: element['id'],
title: element['address']['street_name'],
content: element['address']['street_address'],
user: user,
publisher: user.name
)

book.rating = element['address']['coordinates']['lng'].to_i.abs
book.save!
end
render json: Book.all
end

private

def get(url)
JSON.load(URI.parse(url))
rescue
raise 'Unknown'
end
```

## Timecop

[Timecop](https://github.com/travisjeffery/timecop) is a useful gem which is used for time manipulation to help you create specs.

Add a validation to the method `publish_if_live` in the Book model which ensures that no publications can be made during the weekends.

Create the necessary specs you seem fit to test this functionality.
24 changes: 24 additions & 0 deletions docs/rails/on_boarding/02_rspec/chapter_III.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Chapter III
`(avr. time for this chapter: TBD)`

Certain applications are expected to handle large loads of network traffic and therefore comes the need to test how the system behaves under such conditions.

There are several possible solutions to this problem such as locking the database when a record is being updated or establishing a queue to process requests avoiding concurrency altogether.

In this chapter, we'll focus on the most common solution for concurrency tests, locking database operations when a transaction is uncommitted.

## Preparation

Let's imagine our e-book shop decides to cater to people who appreciate a physical copy of a book.

Physical copies require a stock value which can never go below 0.

A user may also want to purchase more than 1 physical copy at a time, which is impossible for e-books.

Make the necessary changes to the project you see fit to implement this feature.

## Testing

[Threading](https://guides.rubyonrails.org/threading_and_code_execution.html) is a great way to implement concurrency in specs.

Create any tests you see fit to test physical book purchases with the system under the stress of multiple requests.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Chapter I
`(avr. time for this chapter: 1 to 2 days)`
`(avr. time for this chapter: 2 to 3 days)`

The goal of this exercise is to automatize the process of validating your code, a process known by the name Continuous Integration. Among several other benefits, this will help you reduce the risk of introducing new bugs to your project and allows you to have your project in a state always ready to be deployed.

Expand Down
2 changes: 1 addition & 1 deletion docs/rails/on_boarding/04_continuous_delivery/chapter_I.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Chapter I
`(avr. time for this chapter: 2 days)`
`(avr. time for this chapter: 1 to 2 days)`

Now that you have your project being validated automatically through Continuous Integration let's automate his deployment.

Expand Down