2. Example Group describe() Defines example group of tests String we pass describes the item we’re testing it() Defines a code example String we pass describes the specific behaviour
3. describe() Method describe “A User” {…} A User describe User {…} User describe User, “with no roles assigned” {…} User with no roles assigned
8. Pending tests (cont.) Each method of marking a test as pending has its usefulness: Add pending examples as you think of stuff to test Disable failing examples without losing track that you need to fix those at some point Wrap failing examples when you want to be notified when changes to the system cause them to pass (bug is fixed, etc)
9. before()/after() method Before/after methods helps you set and/or reset initial state Create a new stack, add one element to it Takes one argument :each Executes this block before each test group executes :all Executes this block once for all tests before the first test is run
11. before(:all) Method is run once and only once for a group of tests Be careful using this method, usually we want each test to have it’s own environment setup Sharing state between examples can cause unexpected things Good examples: Opening a network connection Pre-seeding caches
12. after(:each) method Code is ran after each example Rarely necessary because each example runs in its own scope, and consequently the instance variables in that scope are reset Can be useful to reset global state of things after your test completes after(:each) is guaranteed to run after each example, even if failure or errors are raised
14. after(:all) method This is even more rare than the after(:each) Examples: Close down browsers Close database connections Close sockets Any resource we want to release when we’re done, but not after every individual test
15. around(:each) method Supports APIs that require a block Very rarely, if ever used I have never used this Put your functionality into before/after blocks if at all possible See http://relishapp.com/rspec/rspec-core/v/2-0/dir/hooks/around-hooks if you’re interested
17. Shared Helper Methods If helper methods need to be used across example groups, put them in one or more modules and include modules in example groups we want to have access
18. Shared Examples If we expect instances of more than one class to behave in the same way, a shared example group describes the behavior once and includes it in multiple example groups
20. RSpec::Expectations One goal of BDD is getting the words right Expectations vs. Assertions We are setting an expectation of what should happen rather than what will happen In fact the word should is part of RSpec result.should equal(5) message.should match(/on Sunday/)
21. should, should_not and matchers result.should equal(5) If result is equal to 5, it passes result.should_not equal(5) If result is anything other than 5, it passes General Pattern:result.should ________(value) _______ is a matcher
22. RSpec built in Matchers include(item) prime_numbers.should_not include(8) respond_to(message) list.shouldrespond_to(:length) raise_error(type) lambda { Object.new.explode! }.should raise_error(NameError)
23. 4 ways to be equal a == b Value equality (Most common) a === b Is Object a the same Object as b a.eql?(b) Are a and b values equal and of same type a.equal?(b) Is Object a the same Object as b (General Rule: The longer the method name, the more restrictive the matcher is)
24. Do not use != in expectations actual.should != expected action.should_not == expected Causes issues, explained in detail in the RSpec book
25. Floating Point Calculations “expected 5.25 got 5.251” is frustrating in a failure message RSpec offers a be_close matcher that accepts an expected value and an acceptable delta result.shouldbe_close(5.25, 0.005) Will pass as long as result is within .005 of 5.25
26. Matching Text response.should match(/this expression/) Matches if response has text “this expression” somewhere in its contents response.should =~ /this expression/ Functionally equivalent to the previous one
27. Expect{} Tests that a block of code causes some effect You can also use .to(1) or .from(0).to(1)
28. Predicate Matchers How do we test array.empty? array.empty?.should == true array.shouldbe_empty
29. Predicate matchers (cont.) RSpec gives you other options be_ be_a ted.shouldbe_a_kind_of(Player) => ted.kind_of?(Player) be_an ted.shouldbe_an_instance_of(Player) =>ted.instance_of?(Player) RSpec also lets you write your own matchers
31. specify{} Sometimes RSpec can guess your tests it “should have 32 pieces” do @board.should have(32).piecesend specify { @board.should have(32).pieces } This is used rarely (very simple tests)
33. RSpec Mocks Mocks allow you to fake functionality that isn’t being tested. See the book for more info.
34. rspec command rspec –help List options available to running RSpec rspec spec/simple_math_spec.rb Run only one spec file rspec spec Run all specs in spec/ directory rspec spec --format documentation Makes RSpec more verbose with test output
35. rspec commands (cont.) rspec spec –color Passing is green, pending is yellow, fail is red Store common options in .rspec file --color --format documentation Options stored in ./.rspec take precedence over ~/.rspec, options declared command line win
36. Let’s get started mkdir -p calculator/{lib,spec} cd calculator mate .
Thebe_XXXX test works only if the item you called should on has a XXXX? method.
If the should method doesn’t have an explicit receiver, it will delegate to the declared subject.Read your tests out loud to make sure they sound right. “Specify the subject should be eligible to vote” vs “it should be eligible to vote”.
should_receive will error if :name is not calledstub will not error if :occupation is not called