Introduction
Controllers
Models
Vues
Aller plus loin
Travaux Pratiques
TP : Gestion des animauxRéservé aux membres premiums
57 min
TP : Gestion des photosRéservé aux membres premiums
46 min
TP : Création du système de FollowersRéservé aux membres premiums
52 min
Les gems utiles
Notions avancées

Lorsque l'on crée une application complexe il est important de tester son code afin de s'assurer que tout fonctionne comme attendu, et ce, à chaque étape du projet. Par défaut, Ruby on Rails utilise les tests la librairies MiniTest mais accepte d'autres frameworks de tests comme Rspec par exemple.

MiniTest ou Rspec ?

Concretement les 2 frameworks vont vous permettre de tester votre code, le choix de l'un ou de l'autre va plutôt dépendre de votre style.

MiniTest

# MiniTest
class PostsControllerTest < ActionDispatch::IntegrationTest

  setup do
    @valid_attrs = {
      name: "Title", 
      content: "Lorem ipsum..."
    }
  end

  test "should get index" do
    get posts_url
    assert_response :success
  end

  test "should create post" do
    assert_difference('Post.count') do
      post posts_url, params: { post: @valid_attrs }
    end

    assert_redirected_to post_url(Post.last)
  end
end

Rspec

RSpec.describe PostsController, type: :controller do

  let(:valid_attributes) {
    {
      name: "Title", 
      content: "Lorem ipsum..."
    }
  }

  let(:post) { 
    Post.create! valid_attributes
  }

  describe "GET #index" do
    it "assigns all posts as @posts" do
      get :index, params: {}
      expect(assigns(:posts)).to eq([post])
    end
  end

  describe "POST #create" do
    context "with valid params" do
      before do 
        post :create, params: {post: valid_attributes}
      end

      it "assigns a newly created post as @post" do
        expect(assigns(:post)).to be_a(Post)
        expect(assigns(:post)).to be_persisted
        expect(Post.count).to eq(1)
      end

      it "redirects to the created post" do
        expect(response).to redirect_to(Post.last)
      end
    end
  end

end

Rspec propose une syntaxe plus tournée vers le BDD (behaviour driven development) qui personnellement me convient un peu plus. Mais n'hésitez pas à tester les 2 méthodes avant de faire votre choix.

Rspec + Rails

Pour commencer à utiliser rspec avec Ruby on Rails il suffit d'ajouter la gem rspec-rails à votre fichier Gemfile. Une fois installée il faut générer les fichier nécessaire à la bonne éxécution des tests :

rails g rspec:install

Cette commande permet de générer les fichiers spec_helper et rails_helper qui seront ensuite inclue dans tous vos tests. Et c'est tout ce qu'il y a à faire. Maintenant, lorsque vous générer un controller, un modèle ou n'importe quoi d'autre, les fichiers spec seront automatiquement générés.

Il est aussi possible de générer des fichiers de spec directement avec le générateur

  rspec:controller
  rspec:feature
  rspec:helper
  rspec:install
  rspec:integration
  rspec:job
  rspec:mailer
  rspec:model
  rspec:observer
  rspec:request
  rspec:scaffold
  rspec:view

Afin d'apprendre le fonctionnement des tests de bases je vous conseille de générer un scaffold ce qui vous donnera un large éventail d'exemple. Ensuite, pour aller plus loin n'hésitez pas à regarder la documentation et le site BetterSpecs.org qui donne de très bon conseil concernant la manière d'écrire de bons tests avec Rspec.

Automatiser avec Guard

Lorsque l'on travail sur un projet on veut parfois relancer les tests lors de la modification d'un fichier. La gem guard-rspec permet de générer la configuration nécessaire au relancement automatique des tests. La gem s'installe depuis le gemfile :

 gem 'guard-rspec', require: false

On génère ensuite la configuration guard à l'aide de la commande

bundle exec guard init rspec

Et hop ! Le tour est joué. Vous pouvez maintenant utiliser la commande guard qui surveillera la modification de fichiers ruby et qui lancera les tests correspondants aux fichiers modifiés.

FactoryGirl, pour remplacer les fixtures

Pour certains tests on sera parfois ammener à travailler avec une base de données. Afin d'insérer des données de tests il est possible d'utiliser le système de fixtures de Rails. Malhereusement ce système est un peu rigide et devient rapidement complexe pour de large quantités de données. factory_girl est une gem qui va permettre de générer des objets plus rapidement et plus simplement. Elle s'intègre très bien à Rails gràce à la gem factory_girl_rails.

factory :user, aliases: [:author, :commenter] do
  first_name    "John"
  last_name     "Doe"
  date_of_birth { 18.years.ago }
end

factory :post do
  author
  # instead of
  # association :author, factory: :user
  title "How to read a book effectively"
  body  "There are five steps involved."
end

Il est ensuite possible de générer l'objet de différente manière :

user = build(:user)           # On retourne une simple instance
user = create(:user)          # On retourne une instance persistée en base de données
attrs = attributes_for(:user) # On retourne un hash d'attributs
stub = build_stubbed(:user)   # On retourne une instance avec les attributs stubbés