Skip to content

Commit 66e834e

Browse files
committed
Merge pull request #590 from estolfo/crud-tests
RUBY-873 Implement CRUD YAML tests
2 parents 3dd8c7f + d22dc0f commit 66e834e

19 files changed

+1523
-0
lines changed

spec/mongo/crud_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
require 'spec_helper'
2+
3+
describe 'CRUD' do
4+
5+
CRUD_TESTS.each do |file|
6+
7+
spec = Mongo::CRUD::Spec.new(file)
8+
9+
context(spec.description) do
10+
11+
spec.tests.each do |test|
12+
13+
context(test.description) do
14+
15+
before(:each) do
16+
authorized_collection.find.delete_many
17+
end
18+
19+
after(:each) do
20+
authorized_collection.find.delete_many
21+
end
22+
23+
let(:results) do
24+
test.run(authorized_collection)
25+
end
26+
27+
it "returns the correct result" do
28+
skip 'Test results only match with server version >= 2.6' if test.requires_2_6?(write_command_enabled?,
29+
authorized_collection)
30+
expect(results).to eq(test.result)
31+
end
32+
33+
it 'has the correct data in the collection' do
34+
skip 'Test results only match with server version >= 2.6' if test.requires_2_6?(write_command_enabled?,
35+
authorized_collection)
36+
expect(test.run(authorized_collection)).to match_collection_data(test)
37+
end
38+
end
39+
end
40+
end
41+
end
42+
end

spec/spec_helper.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
require 'support/server_discovery_and_monitoring'
2626
require 'support/server_selection_rtt'
2727
require 'support/server_selection'
28+
require 'support/crud'
2829

2930
Mongo::Logger.logger = Logger.new($stdout)
3031
Mongo::Logger.logger.level = Logger::INFO
@@ -66,6 +67,7 @@
6667
SERVER_DISCOVERY_TESTS = Dir.glob("#{CURRENT_PATH}/support/sdam/**/*.yml")
6768
SERVER_SELECTION_RTT_TESTS = Dir.glob("#{CURRENT_PATH}/support/server_selection/rtt/*.yml")
6869
SERVER_SELECTION_TESTS = Dir.glob("#{CURRENT_PATH}/support/server_selection/selection/**/*.yml")
70+
CRUD_TESTS = Dir.glob("#{CURRENT_PATH}/support/crud_tests/**/*.yml")
6971

7072
# Determine whether the test clients are connecting to a standlone.
7173
#

spec/support/crud.rb

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
# Copyright (C) 2014-2015 MongoDB, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Matcher for determining if the results of the opeartion match the
16+
# test's expected results.
17+
#
18+
# @since 2.0.0
19+
20+
# Matcher for determining if the collection's data matches the
21+
# test's expected collection data.
22+
#
23+
# @since 2.0.0
24+
RSpec::Matchers.define :match_collection_data do |test|
25+
26+
match do |actual|
27+
test.compare_collection_data
28+
end
29+
end
30+
31+
require 'support/crud/read'
32+
require 'support/crud/write'
33+
34+
module Mongo
35+
module CRUD
36+
37+
# Represents a CRUD specification test.
38+
#
39+
# @since 2.0.0
40+
class Spec
41+
42+
# @return [ String ] description The spec description.
43+
#
44+
# @since 2.0.0
45+
attr_reader :description
46+
47+
# Instantiate the new spec.
48+
#
49+
# @example Create the spec.
50+
# Spec.new(file)
51+
#
52+
# @param [ String ] file The name of the file.
53+
#
54+
# @since 2.0.0
55+
def initialize(file)
56+
@spec = YAML.load(ERB.new(File.new(file).read).result)
57+
@description = File.basename(file)
58+
@data = @spec['data']
59+
@crud_tests = @spec['tests']
60+
end
61+
62+
# Get a list of CRUDTests for each test definition.
63+
#
64+
# @example Get the list of CRUDTests.
65+
# spec.tests
66+
#
67+
# @return [ Array<CRUDTest> ] The list of CRUDTests.
68+
#
69+
# @since 2.0.0
70+
def tests
71+
@crud_tests.collect do |test|
72+
Mongo::CRUD::CRUDTest.new(@data, test)
73+
end
74+
end
75+
end
76+
77+
# Represents a single CRUD test.
78+
#
79+
# @since 2.0.0
80+
class CRUDTest
81+
82+
# The test description.
83+
#
84+
# @return [ String ] description The test description.
85+
#
86+
# @since 2.0.0
87+
attr_reader :description
88+
89+
# Instantiate the new CRUDTest.
90+
#
91+
# @example Create the test.
92+
# CRUDTest.new(data, test)
93+
#
94+
# @param [ Array<Hash> ] data The documents the collection
95+
# must have before the test runs.
96+
# @param [ Hash ] test The test specification.
97+
#
98+
# @since 2.0.0
99+
def initialize(data, test)
100+
@data = data
101+
@description = test['description']
102+
@operation = Operation.get(test['operation'])
103+
@outcome = test['outcome']
104+
end
105+
106+
# Run the test.
107+
#
108+
# @example Run the test.
109+
# test.run(collection)
110+
#
111+
# @param [ Collection ] collection The collection the test
112+
# should be run on.
113+
#
114+
# @return [ Result, Array<Hash> ] The result(s) of running the test.
115+
#
116+
# @since 2.0.0
117+
def run(collection)
118+
@collection = collection
119+
@collection.insert_many(@data)
120+
@operation.execute(collection)
121+
end
122+
123+
# The expected result of running the test.
124+
#
125+
# @example Get the expected result of running the test.
126+
# test.result
127+
#
128+
# @return [ Array<Hash> ] The expected result of running the test.
129+
#
130+
# @since 2.0.0
131+
def result
132+
@operation.has_results? ? @outcome['result'] : []
133+
end
134+
135+
# Compare the existing collection data and the expected collection data.
136+
#
137+
# @example Compare the existing and expected collection data.
138+
# test.compare_collection_data
139+
#
140+
# @return [ true, false ] The result of comparing the existing and expected
141+
# collection data.
142+
#
143+
# @since 2.0.0
144+
def compare_collection_data
145+
actual_collection_data == outcome_collection_data
146+
end
147+
148+
# Whether this test requires server version >= 2.6 for its results to match
149+
# the expected results.
150+
#
151+
# @example If this test requires >= 2.6.
152+
# test.requires_2_6?(collection)
153+
#
154+
# @param [ true, false ] If write commands are enabled on the server.
155+
# @param [ Collection ] The collection the test is run on.
156+
#
157+
# @return [ true, false ] Whether the test requires server >= 2.6.
158+
#
159+
# @since 2.0.0
160+
def requires_2_6?(write_command_enabled, collection)
161+
!write_command_enabled && @operation.requires_2_6?(collection)
162+
end
163+
164+
private
165+
166+
def outcome_collection_data
167+
@outcome['collection']['data'] if @outcome['collection']
168+
end
169+
170+
def actual_collection_data
171+
if @outcome['collection']
172+
collection_name = @outcome['collection']['name'] || @collection.name
173+
@collection.database[collection_name].find.to_a
174+
end
175+
end
176+
end
177+
178+
# Helper module for instantiating either a Read or Write test operation.
179+
#
180+
# @since 2.0.0
181+
module Operation
182+
extend self
183+
184+
# Get a new Operation.
185+
#
186+
# @example Get the operation.
187+
# Operation.get(spec)
188+
#
189+
# @param [ Hash ] spec The operation specification.
190+
#
191+
# @return [ Operation::Write, Operation::Read ] The Operation object.
192+
#
193+
# @since 2.0.0
194+
def get(spec)
195+
if Write::OPERATIONS.keys.include?(spec['name'])
196+
Write.new(spec)
197+
else
198+
Read.new(spec)
199+
end
200+
end
201+
end
202+
end
203+
end

0 commit comments

Comments
 (0)