Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction à RSpec

Introduction à RSpec

I presented RSpec at OpenCode #8.

8c4cee1129bc11fbe9a0b9379dce2cb1?s=128

Rémi Prévost

December 18, 2012
Tweet

Transcript

  1. RSpec Rémi Prévost — OpenCode #8

  2. “ RSpec is a Behaviour-Driven Development tool for Ruby programmers

  3. Teste le comportement et non la finalité des objets

  4. Langage naturel, écrire le moins de texte possible dans nos

    tests
  5. Test::Unit vs. RSpec gem install rspec

  6. require "test/unit" class ProductTest < Test::Unit::TestCase def test_initial_quantity assert_equal 4,

    Product.new.initial_quantity end end describe Product do subject { Product.new } its(:initial_quantity) { should eq 4 } end
  7. Matchers Goodbye asserts!

  8. describe Array do subject { [1, 2, 3, 4] }

    # Teste subject.size its(:size) { should eq 4 } # Teste subject.empty? it { should_not be_empty } # Teste subject.size, subject.clear et subject.size encore it do expect { subject.clear }.to change(subject, :size).to(0) end end
  9. % rspec array_spec.rb ... Finished in 0.00454 seconds 3 examples,

    0 failures
  10. % rspec array_spec.rb --format documentation --colour Array should not be

    empty should change size size should eq 4 Finished in 0.00316 seconds 3 examples, 0 failures
  11. describe Array do subject { [1, 2, 3, 4] }

    # Teste subject.size its(:size) { should eq 3 } end
  12. % rspec array_spec.rb --format documentation --colour Array size should eq

    3 (FAILED - 1) Failures: 1) Array size Failure/Error: its(:size) { should eq 3 } expected: 3 got: 4 (compared using ==) Finished in 0.0009 seconds 1 example, 1 failure Failed examples: rspec ./array_spec.rb:7 # Array size
  13. "foo".should eq "foo" # "foo" == "foo" Product.new.should be_available #

    Product.new.available? == true Product.new.should be_instance_of(Product) # Product.new.instance_of?(Product) "foo".should respond_to(:upcase) # "foo".respond_to?(:upcase) { :foo => "bar" }.should have_key(:foo) # { :foo => "bar" }.has_key?(:foo) [1, 2, 3].should have(3).items # [1, 2, 3].size == 3
  14. expect { 42/0 }.to raise_error(ZeroDivisionError) # &block.call rescue ZeroDivisionError @a

    = [1, 2, 3, 4] expect { @a.clear }.to change{ @a.length }.from(4).to(0) # &block.call == 4 # &expectation.call # &block.call == 0 @a = [1, 2, 3, 4] expect { @a.clear }.to change(@a, :length).from(4).to(0) # @a.length == 4 # &expectation.call # @a.length == 0
  15. Contextes

  16. describe Product do context "without supply" do subject { Product.new(:quantity_left

    => 0) } it { should be_sold_out } end context "with supply" do subject { Product.new(:quantity_left => 10) } it { should_not be_sold_out } end end
  17. describe Product do describe :build do context "as admin user"

    do before { @user = User.new(:roles => [:admin]) } context "without scope" do subject { Product.build(:as => @user) } its(:owner) { should eq @user } it { should_not be_available } end context "with available scope" do subject { Product.available.build(:as => @user) } its(:owner) { should eq @user } it { should be_available } end end end end
  18. Variables

  19. describe Product do describe :similar_products do context "without supply" do

    subject { Product.new } it "returns the next sold out product" do subject.similar_products(10).first.should be_sold_out end end context "with supply" do subject { Product.new(:quantity_left => 5) } it "returns the next available product" do subject.similar_products(10).first.should_not be_sold_out end end end end
  20. describe Product do describe :similar_products do let(:next_product) { subject.similar_products(10).first }

    context "without supply" do subject { Product.new } specify { next_product.should be_sold_out } end context "with supply" do subject { Product.new(:quantity_left => 5) } specify { next_product.should_not be_sold_out } end end end
  21. Rails gem install rspec-rails gem install shoulda

  22. Modèles

  23. describe Product do describe :Associations do # TODO end describe

    :Validations do # TODO end describe :Callbacks do # TODO end describe :InstanceMethods do # TODO end describe :ClassMethods do # TODO end end
  24. describe Product do describe :Associations do it { should belong_to(:brand)

    } it { should have_many(:pictures) } end end class Product < ActiveRecord::Base belongs_to :brand has_many :pictures end
  25. describe Product do describe :Validations do it { should validate_presence_of(:name)

    } it { should ensure_inclusion_of(:state).in(%w{visible hidden}) } it { should_not allow_value("_$#!").for(:sku) } end end class Product < ActiveRecord::Base validates :name, :presence => true validates :state, :inclusion => { :in => %w{visible hidden} } validates :sku, :rosette_sku => true end
  26. describe Product do describe :Callbacks do describe :adjust_sold_out_flag do subject

    { Product.new(:sold_out => false) } specify do subject.quantity_left = 0 expect { subject.save! }.to change(subject, :sold_out?).from(false).to(true) end end end end class Product < ActiveRecord::Base before_save :adjust_sold_out_flag, :if => proc { self.quantity_left_changed? and self.quantity_left == 0 } end
  27. describe Product do describe :Callbacks do describe :adjust_sold_out_flag do subject

    { Product.new(:sold_out => false) } before { subject.quantity_left = 0 } specify do subject.should_receive(:adjust_sold_out_flag).once subject.save! end end end end class Product < ActiveRecord::Base before_save :adjust_sold_out_flag, :if => proc { self.quantity_left_changed? and self.quantity_left == 0 } end
  28. Contrôleurs

  29. describe ProductsController do # POST /products describe :create do end

    # GET /products describe :index do end # PUT /products/:id describe :update do end # GET /products/:id describe :show do end # DELETE /products/:id describe :destroy do end end
  30. describe ProductsController do # POST /products describe :create do before

    do post :create, :product => { :name => "Foo" } end it { should redirect_to(products_path) } it { should set_the_flash[:notice].to("Yay!") } end end class ProductsController < ApplicationController def create if Product.create(params[:product]) flash[:notice] = "Yay!" redirect_to products_path end end end
  31. class ProductsController < ApplicationController def create if Product.create(params[:product]) flash[:notice] =

    "Yay!" redirect_to products_path else flash[:error] = "Nope!" end end end
  32. describe ProductsController do # POST /products describe :create do let

    :create_product! { post :create, :product => attrs } context "with valid attributes" do let(:attrs) { { :name => "Foo" } } before { create_product! } it { should redirect_to(products_path) } it { should set_the_flash[:notice].to("Yay!") } end context "with invalid attributes" do let(:attrs) { { :name => "" } } before { create_product! } it { should render_template("products/create") } it { should set_the_flash[:error].to("Nope!") } end end end
  33. describe ProductsController do # GET /products describe :index do before

    do @product = stub_model(Product) Product.stub(:all).returns([@product]) get :index end it { should respond_with(:success) } it { should render_template("products/index") } it { should assign_to(:products).with([@product]) } end end class ProductsController < ApplicationController def index @products = Product.all end end
  34. describe "products/index" do before do assign(:products, [stub_model(Product, :name => "Foo")])

    render end it { expect(rendered).to include("Foo") } end <%= @products.each do |product| %> <h1><%= product.name %></h1> <% end %> Vues
  35. describe "GET /products" do it do expect(:get => "/products").to route_to(

    :controller => "products", :action => "index" ) end end resources :products Routes
  36. describe ProductsHelper do describe :format_price do subject do helper.format_price(stub_model(Product, :price

    => 1200)) end it { should eq "$12.00" } end end module ProductsHelper def format_price(product) Money.new(product.price).format end end Helpers
  37. Merci! Questions? Commentaires?