70

I have a test like so:

it "should not indicate backwards jumps if the checker position is not a king" do
    board = Board.new
    game_board = board.create_test_board
    board.add_checker(game_board, :red, 3, 3)
    x_coord = 3
    y_coord = 3
    jump_locations = {}
    jump_locations["upper_left"]  = true 
    jump_locations["upper_right"] = false 
    jump_locations["lower_left"]  = false
    jump_locations["lower_right"] = true
    adjusted_jump_locations = @bs.adjust_jump_locations_if_not_king(game_board, x_coord, y_coord, jump_locations)
    adjusted_jump_locations["upper_left"].should == true 
    adjusted_jump_locations["upper_right"].should == false 
    adjusted_jump_locations["lower_left"].should == false
    adjusted_jump_locations["lower_right"].should == false
  end 

which, I know, is verbose. Is there a more concise way to state my expectations? I've looked at the docs but I can't see where to compress my expectations. Thanks.

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
steve_gallagher
  • 3,778
  • 8
  • 33
  • 51

4 Answers4

118

It works for hashes too:

expect(jump_locations).to include(
  "upper_left"  => true,
  "upper_right" => false,
  "lower_left"  => false,
  "lower_right" => true
)

Source: include matcher @ relishapp.com

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
David Chelimsky
  • 8,920
  • 2
  • 38
  • 30
38

Just wanna add to @David's answer. You could nest and use matchers in your include hash. For example:

# Pass
expect({
  "num" => 5, 
  "a" => { 
    "b" => [3, 4, 5] 
  }
}).to include({
  "num" => a_value_between(3, 10), 
  "a" => {
    "b" => be_an(Array)
  }
})

A caveat: a nested include hash must test all keys or the test will fail, e.g.:

# Fail
expect({
  "a" => { 
    "b" => 1,
    "c" => 2
  }
}).to include({
  "a" => {
    "b" => 1
  }
})
Benjamin Cheah
  • 1,401
  • 17
  • 23
  • 8
    You can solve your caveat by using nested includes: ```expect({ "a" => { "b" => 1, "c" => 2 } }).to include({ "a" => include({ "b" => 1 }) })``` – AngelCabo Sep 15 '16 at 21:37
  • 2
    most matchers have both "verb" and longer "noun" aliases, the latter might read better when nesting: `expect({ "a" => { "b" => 1, "c" => 2 } }).to include({ "a" => a_hash_including({ "b" => 1 }) })`. http://timjwade.com/2016/08/01/testing-json-apis-with-rspec-composable-matchers.html is a good blog post on this. – Beni Cherniavsky-Paskin Jul 13 '17 at 09:34
  • @AngelCabo your comment should be the accepted answer. Helps in so many scenarios. – manpreet singh Sep 29 '21 at 22:22
6

Syntax has changed for RSpec 3, but include matcher is still the one:

expect(jump_locations).to include(
  "upper_left" => true,
  "upper_right" => false,
  "lower_left" => false,
  "lower_right" => true
)

See built-in-matchers#include-matcher.

Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
Marko Avlijaš
  • 1,579
  • 13
  • 27
5

Another easy way to test if the whole content is a Hash is to checkout if the content is the Hash Object itself:

it 'is to be a Hash Object' do
    workbook = {name: 'A', address: 'La'}
    expect(workbook.is_a?(Hash)).to be_truthy
end

For the question above we can check as follow:

expect(adjusted_jump_locations).to match(hash_including('upper_left' => true))
Kiry Meas
  • 1,200
  • 13
  • 26