Skip to content

Instantly share code, notes, and snippets.

@rafbm
Forked from remi/reports_controller_spec.rb
Last active December 14, 2015 03:19
Show Gist options
  • Save rafbm/5019918 to your computer and use it in GitHub Desktop.
Save rafbm/5019918 to your computer and use it in GitHub Desktop.
describe ReportsController do
describe :create do
before do
@payload = { :version => "1.0.0" }
end
it "succeeds with present serial" do
@payload[:serial] = "123abc"
post reports_path, @payload.to_json
last_response.should be_ok
last_response.status.should eq 200
end
it "fails with missing serial" do
@payload[:serial] = nil
post reports_path, @payload.to_json
last_response.should_not be_ok
last_response.status.should eq 400
end
end
end
@remi
Copy link

remi commented Feb 23, 2013

Ce que j’aime moins avec ça, c’est que ça inclut plusieurs expectations dans un même exmple.

Là c’est moins problématique parce que ok? et status == 200 (il manque status dans ton code :P) sont intimement relié. Mais si tu avais à tester plusieurs expectations différentes pour un même contexte, certaines expectations ne seraient pas testées.

it "fails with missing serial" do
  @payload[:serial] = nil
  post reports_path, @payload.to_json

  last_response.should_not be_ok
  last_response.status.should eq 400
  JSON.parse(last_response.body)["errors"].should include?("Missing serial number")
end

Si ton status n’est pas 400, l’exemple fail immédiatement et la ligne d’après (qui teste le body de la réponse) n’est jamais évaluée. Tu fixes le code d’erreur, et l’exemple peut encore failer, parce que maintenant RSpec va vérifier si le message d’erreur est présent.

C’est pour cette raison que j’aime bien séparer chaque expectation dans un exemple différent. Quand j’ai 5 exemples qui ne passent pas, c’est parce que j’ai exactement 5 expectations qui ne sont pas remplies. Pas plus.

@remi
Copy link

remi commented Feb 23, 2013

Si tu voulais mettre une expectation par exemple, tu pourrais le faire comme ça, mais avec beaucoup de répétition de code (et de descriptions d’exemple) parce que subject n’est pas utilisé :

context "with missing serial" do
  before do
    @payload[:serial] = nil
    post reports_path, @payload.to_json
  end

  it "returns an erroneous response" do
    last_response.should_not be_ok
  end

  it "returns a 400 status code" do
    last_response.status.should eq 400
  end

  it "returns an error message" do
    JSON.parse(last_response.body)["errors"].should include?("Missing serial number")
  end
end

@rafbm
Copy link
Author

rafbm commented Feb 23, 2013

Mmh je comprends. Ça ne m’a jamais agacé qu’un test qui fail arrête d’évaluer les autres expectations. Je trouve que ça a parfaitement du sens que certains tests contiennent plusieurs expectations.

    before { post reports_path, payload.to_json }

    context "with present serial" do
      let(:serial) { "123abc" }

      it { should be_ok }
      its(:status) { should eq 200 }
    end

Dans cet exemple, est-ce que RSpec roule le before avant le it et avant le its ?

@rafbm
Copy link
Author

rafbm commented Feb 23, 2013

…srait le fun que les comments de gists s’updatent automagiquement comme les issues…

@rafbm
Copy link
Author

rafbm commented Feb 23, 2013

Toujours possible de faire ça si t’as une shitload d’expectations :

it "fails with missing serial" do
  @payload[:serial] = nil
  post reports_path, @payload.to_json

  last_response.instance_eval do
    should_not be_ok
    status.should eq 400
    JSON.parse(body)["errors"].should include?("Missing serial number")
  end
end

__evil laugh**

@remi
Copy link

remi commented Feb 23, 2013

Dans cet exemple, est-ce que RSpec roule le before avant le it et avant le its ?

Yep. Le before est exécuté une fois avant le it et une fois avant le its.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment