From 11e04c52c8098060efdec08c56ba4cb1ab47cf7a Mon Sep 17 00:00:00 2001 From: Laura Paakkinen Date: Mon, 25 Apr 2016 16:42:51 +0200 Subject: [PATCH] Finish match_result_set rspec matchers --- .rubocop_u2i.yml | 5 ++ examples/spec/query_spec.rb | 28 +++------ lib/rspec/hive.rb | 1 + lib/rspec/hive/matchers.rb | 28 +++++++++ spec/lib/rspec/hive/matchers_spec.rb | 94 ++++++++++++++++++++++++++++ 5 files changed, 138 insertions(+), 18 deletions(-) create mode 100644 lib/rspec/hive/matchers.rb create mode 100644 spec/lib/rspec/hive/matchers_spec.rb diff --git a/.rubocop_u2i.yml b/.rubocop_u2i.yml index 0e30d42..b4df6bc 100644 --- a/.rubocop_u2i.yml +++ b/.rubocop_u2i.yml @@ -54,3 +54,8 @@ Metrics/MethodLength: RSpec/FilePath: Exclude: - spec/routing/**/*_routing_spec.rb + +RSpec/DescribeClass: + Exclude: + - spec/lib/rspec/hive/matchers_spec.rb + diff --git a/examples/spec/query_spec.rb b/examples/spec/query_spec.rb index 2a09cf0..18c692b 100644 --- a/examples/spec/query_spec.rb +++ b/examples/spec/query_spec.rb @@ -2,13 +2,6 @@ require_relative '../lib/query' require 'rspec/hive/query_builder_helper' -RSpec::Matchers.define :match_hive_array do |expected| - match do |actual| - actual == expected - end -end - - RSpec.describe Query do include RSpec::Hive::WithHiveConnection include RSpec::Hive::QueryBuilderHelper @@ -34,25 +27,24 @@ query = "SELECT * FROM `#{subject.table_name}` WHERE amount > 3.2" query_result = connection.fetch(query) - expected_row = [ - a_string_matching('Wojtek'), - a_string_matching('Cos'), - a_string_matching(/3\.7.*/), + expected_result_set = [ + [a_string_matching('Wojtek'), 'Cos', a_string_matching(/3\.7.*/)] ] - expect(query_result).to match_hive_array(expected_row) + expect(query_result).to match_result_set(expected_result_set) end it 'query returns one row 2' do query = "SELECT * FROM `#{subject.table_name}` WHERE amount < 3.2" - query_result = connection.fetch(query).first.values + query_result = connection.fetch(query) - expected_row = [ - a_string_matching('Mikolaj'), - a_string_matching('Cos'), - a_string_matching(/1\.2.*/) + expected_result_set = [ + {name: 'Mikolaj', + address: 'Cos', + amount: a_string_matching(/1\.2.*/) + } ] - expect(query_result).to contain_exactly(*expected_row) + expect(query_result).to match_result_set(expected_result_set) end end diff --git a/lib/rspec/hive.rb b/lib/rspec/hive.rb index 08b39e8..7e23f0a 100644 --- a/lib/rspec/hive.rb +++ b/lib/rspec/hive.rb @@ -5,6 +5,7 @@ require 'rspec/hive/connector' require 'rspec/hive/with_hive_connection' require 'rspec/hive/query_builder' +require 'rspec/hive/matchers' module RSpec module Hive diff --git a/lib/rspec/hive/matchers.rb b/lib/rspec/hive/matchers.rb new file mode 100644 index 0000000..a4e2bd0 --- /dev/null +++ b/lib/rspec/hive/matchers.rb @@ -0,0 +1,28 @@ +require 'rspec/matchers' + +RSpec::Matchers.define :match_result_set do |expected| + match do |actual| + return false if expected.size != actual.size + + expected.each.with_index.all? do |expected_row, i| + if expected_row.respond_to?(:each_pair) + if @partial_match + values_match?(expected_row.values, actual[i].values_at(*expected_row.keys)) + else + values_match?(expected_row, actual[i]) + end + elsif expected_row.respond_to?(:each) + raise ArgumentError, "Can't use partially matcher with Arrays" if @partial_match + values_match?(expected_row, actual[i].values) + else + raise ArgumentError, 'Unknown type' + end + end + end + + chain :partially do + @partial_match = true + end + + diffable +end diff --git a/spec/lib/rspec/hive/matchers_spec.rb b/spec/lib/rspec/hive/matchers_spec.rb new file mode 100644 index 0000000..7d4ad21 --- /dev/null +++ b/spec/lib/rspec/hive/matchers_spec.rb @@ -0,0 +1,94 @@ +require 'spec_helper' +require 'rspec/hive/query_builder_helper' + +RSpec.describe 'match_result_set' do + include RSpec::Hive::QueryBuilderHelper + + let(:john) { {first_name: 'John', last_name: 'Lennon'} } + let(:paul) { {first_name: 'Paul', last_name: 'McCartney'} } + + let(:full_match) { expect(actual_rows).to match_result_set(expected_rows) } + let(:partial_match) { expect(actual_rows).to match_result_set(expected_rows).partially } + let(:full_match_fails) { expect(actual_rows).not_to match_result_set(expected_rows) } + let(:partial_match_fails) { expect(actual_rows).not_to match_result_set(expected_rows).partially } + + context 'when the expected set has only one row' do + context 'but the actual set has more rows' do + let(:actual_rows) { [john, paul] } + + context 'when the row is given as an array' do + let(:expected_rows) { [john.values] } + + specify { full_match_fails } + specify { partial_match_fails } + end + + context 'when the row is given as a hash' do + let(:expected_rows) { [john] } + + specify { full_match_fails } + specify { partial_match_fails } + end + end + + context 'and the actual set has one row' do + let(:actual_rows) { [john] } + + context 'when the row is given as an array' do + context 'when the number of columns differs' do + let(:expected_rows) { [john.values << 'yoko'] } + + specify { full_match_fails } + end + + context 'when the actual and expected have are different' do + let(:expected_rows) { [paul.values] } + + specify { full_match_fails } + end + + context 'when the actual and expected rows are equal' do + let(:expected_rows) { [john.values] } + + specify { full_match } + end + + context 'when the actual and expected rows are equal with rspec matchers' do + let(:expected_rows) { [[a_string_matching('John'), a_string_matching(/lennon/i)]] } + + specify { full_match } + end + end + + context 'when the row is given as a hash' do + context 'when the number of columns differs' do + let(:expected_rows) { [john.dup.tap { |j| j[:ono] = 'yoko' }] } + + specify { full_match_fails } + specify { partial_match_fails } + end + + context 'when the actual and expected have are different' do + let(:expected_rows) { [john.dup.tap { |j| j[:first_name] = 'yoko' }] } + + specify { full_match_fails } + specify { partial_match_fails } + end + + context 'when the actual and expected rows are equal' do + let(:expected_rows) { [john] } + + specify { full_match } + specify { partial_match } + end + + context 'when matching a subset of columns' do + let(:expected_rows) { [{first_name: john[:first_name]}] } + + specify { full_match_fails } + specify { partial_match } + end + end + end + end +end