Skip to content

Commit 0d33c9c

Browse files
committed
tests: finish rspec usage-focused rationalization pass
Trim remaining overlapping RSpec tree specs to common API usage examples and representative behavior checks. Keep exhaustive edge-case and regression scenarios in Test::Unit coverage. Validation: rake lint, rake test:all, rake doc:check.
1 parent 691a7bc commit 0d33c9c

8 files changed

Lines changed: 122 additions & 456 deletions

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Changes section to scan for breaking or behavioral changes.
1111
* Rationalize RSpec coverage for core tree families so specs emphasize common
1212
API usage readability, while exhaustive edge-case and regression coverage
1313
remains in the Test::Unit suite.
14+
* Continue RSpec rationalization across the remaining overlapping tree-family
15+
specs to keep examples usage-oriented and reduce duplicate scenario matrices.
1416
* Add non-breaking API aliases for consistency:
1517
`Tree::AATree#lookup`, `Tree::BTree#lookup`,
1618
`Tree::FenwickTree#query`, `Tree::SegmentTree#query`,

spec/tree/binary_search_tree_node_spec.rb

Lines changed: 19 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -11,84 +11,36 @@ def inorder_contents(node)
1111
result
1212
end
1313

14-
def build_leaf_tree
15-
root = described_class.new('root', 10)
16-
root.insert('n5', 5)
17-
root.insert('n15', 15)
18-
root.insert('n2', 2)
14+
def build_tree(values)
15+
root = described_class.new('root', values.first)
16+
values.drop(1).each_with_index do |value, index|
17+
root.insert("n#{index}", value)
18+
end
1919
root
2020
end
2121

22-
def build_one_child_tree
23-
root = described_class.new('root', 10)
24-
root.insert('n5', 5)
25-
root.insert('n2', 2)
26-
root
27-
end
28-
29-
def build_two_children_tree
30-
root = described_class.new('root', 10)
31-
root.insert('n5', 5)
32-
root.insert('n15', 15)
33-
root.insert('n12', 12)
34-
root.insert('n18', 18)
35-
root.insert('n2', 2)
36-
root
37-
end
38-
39-
def build_root_single_child_tree
40-
root = described_class.new('root', 10)
41-
root.insert('n5', 5)
42-
root
43-
end
44-
45-
def build_root_leaf_tree
46-
described_class.new('root', 10)
47-
end
22+
let(:root) { build_tree([10, 5, 15, 12, 18, 2]) }
4823

4924
it 'orders inserts by key' do
50-
expect(inorder_contents(build_two_children_tree)).to eq([2, 5, 10, 12, 15, 18])
25+
expect(inorder_contents(root)).to eq([2, 5, 10, 12, 15, 18])
5126
end
5227

53-
it 'finds a matching key' do
54-
expect(build_two_children_tree.search(15).name).to eq('n15')
28+
it 'finds matching keys' do
29+
expect(root.search(15).content).to eq(15)
5530
end
5631

57-
it 'returns nil for a missing key' do
58-
expect(build_two_children_tree.search(7)).to be_nil
32+
it 'returns nil for missing keys' do
33+
expect(root.search(7)).to be_nil
5934
end
6035

61-
it 'returns the removed node when deleting a leaf' do
62-
expect(build_leaf_tree.delete(2).content).to eq(2)
63-
end
64-
65-
it 'updates order when deleting a leaf' do
66-
root = build_leaf_tree
67-
root.delete(2)
68-
expect(inorder_contents(root)).to eq([5, 10, 15])
69-
end
70-
71-
it 'updates order when deleting a node with one child' do
72-
root = build_one_child_tree
73-
root.delete(5)
74-
expect(inorder_contents(root)).to eq([2, 10])
75-
end
76-
77-
it 'updates order when deleting a node with two children' do
78-
root = build_two_children_tree
79-
root.delete(15)
80-
expect(inorder_contents(root)).to eq([2, 5, 10, 12, 18])
81-
end
82-
83-
it 'replaces root content when deleting root with one child' do
84-
root = build_root_single_child_tree
85-
root.delete(10)
86-
expect(root.content).to eq(5)
87-
end
36+
describe 'delete usage' do
37+
it 'returns the removed node' do
38+
expect(root.delete(2).content).to eq(2)
39+
end
8840

89-
it 'clears root content when deleting a root leaf' do
90-
root = build_root_leaf_tree
91-
root.delete(10)
92-
expect(root.content).to be_nil
41+
it 'removes deleted keys from traversal results' do
42+
root.delete(15)
43+
expect(inorder_contents(root)).to eq([2, 5, 10, 12, 18])
44+
end
9345
end
9446
end

spec/tree/fenwick_tree_spec.rb

Lines changed: 17 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -9,107 +9,35 @@ def build_tree(values)
99
described_class.new(values.length, values)
1010
end
1111

12-
describe 'initialize' do
13-
it 'applies initial values' do
14-
tree = build_tree([1, 2, 3])
15-
expect(tree.sum(2)).to eq(6)
16-
end
12+
let(:tree) { build_tree([1, 2, 3, 4, 5]) }
1713

18-
it 'raises for invalid size' do
19-
expect { described_class.new(0) }.to raise_error(ArgumentError)
20-
end
14+
it 'supports prefix-sum queries for common usage' do
15+
expect(tree.sum(3)).to eq(10)
2116
end
2217

23-
describe 'update' do
24-
it 'updates prefix sums' do
25-
tree = build_tree([1, 2, 3, 4])
26-
tree.update(2, 5)
27-
expect(tree.sum(2)).to eq(11)
28-
end
18+
it 'supports range-sum queries for common usage' do
19+
expect(tree.range_sum(1, 3)).to eq(9)
2920
end
3021

31-
describe 'sum' do
32-
it 'returns a prefix sum' do
33-
tree = build_tree([1, 2, 3, 4, 5])
34-
expect(tree.sum(3)).to eq(10)
35-
end
22+
it 'supports indexed updates via []=' do
23+
tree[1] = 5
24+
expect(tree[1]).to eq(7)
3625
end
3726

38-
describe 'range_sum' do
39-
it 'returns a range sum' do
40-
tree = build_tree([1, 2, 3, 4, 5])
41-
expect(tree.range_sum(1, 3)).to eq(9)
42-
end
27+
it 'supports enumeration in index order' do
28+
expect(tree.each.to_a).to eq([1, 2, 3, 4, 5])
4329
end
4430

45-
describe '[]' do
46-
it 'returns the value at an index' do
47-
tree = build_tree([1, 2, 3, 4, 5])
48-
expect(tree[4]).to eq(5)
49-
end
31+
it 'supports hash round-trips' do
32+
copy = described_class.from_hash(tree.to_h)
33+
expect(copy.to_a).to eq(tree.to_a)
5034
end
5135

52-
describe '[]=' do
53-
it 'adds a delta at the index' do
54-
tree = build_tree([1, 2, 3])
55-
tree[1] = 5
56-
expect(tree[1]).to eq(7)
57-
end
36+
it 'rejects invalid tree size' do
37+
expect { described_class.new(0) }.to raise_error(ArgumentError)
5838
end
5939

60-
describe 'each' do
61-
it 'yields values in index order' do
62-
tree = build_tree([3, 1, 4])
63-
expect(tree.each.to_a).to eq([3, 1, 4])
64-
end
65-
end
66-
67-
describe 'keys' do
68-
it 'returns indices in order' do
69-
tree = build_tree([1, 2, 3])
70-
expect(tree.keys).to eq([0, 1, 2])
71-
end
72-
end
73-
74-
describe 'values' do
75-
it 'returns values in index order' do
76-
tree = build_tree([2, 4, 6])
77-
expect(tree.values).to eq([2, 4, 6])
78-
end
79-
end
80-
81-
describe 'to_h and from_hash' do
82-
it 'round trips the tree' do
83-
tree = build_tree([1, 3, 5])
84-
copy = described_class.from_hash(tree.to_h)
85-
expect(copy.to_a).to eq([1, 3, 5])
86-
end
87-
end
88-
89-
describe 'as_json' do
90-
it 'returns a hash representation' do
91-
tree = build_tree([1, 2])
92-
expect(tree.as_json).to eq(tree.to_h)
93-
end
94-
end
95-
96-
describe '<=>' do
97-
it 'compares by ordered values' do
98-
left = build_tree([1, 2, 3])
99-
right = build_tree([1, 2, 4])
100-
expect(left < right).to be(true)
101-
end
102-
end
103-
104-
describe '<<' do
105-
it 'is not supported' do
106-
tree = build_tree([1, 2, 3])
107-
expect(tree.respond_to?(:<<)).to be(false)
108-
end
109-
110-
it 'raises when called' do
111-
tree = build_tree([1, 2, 3])
112-
expect { tree << 4 }.to raise_error(NoMethodError)
113-
end
40+
it 'does not support shovel insertion' do
41+
expect(tree.respond_to?(:<<)).to be(false)
11442
end
11543
end

spec/tree/interval_tree_node_spec.rb

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,12 @@
77
RSpec.describe Tree::IntervalTreeNode do
88
def build_tree(intervals)
99
root = described_class.new('root', intervals.first)
10-
intervals.drop(1).each_with_index do |interval, idx|
11-
root.insert("n#{idx}", interval)
10+
intervals.drop(1).each_with_index do |interval, index|
11+
root.insert("n#{index}", interval)
1212
end
1313
root
1414
end
1515

16-
def inorder_keys(node)
17-
result = []
18-
node.inordered_each { |entry| result << entry.key }
19-
result
20-
end
21-
2216
def max_end_valid?(node)
2317
return true unless node&.content
2418

@@ -28,45 +22,24 @@ def max_end_valid?(node)
2822
max_end_valid?(node.left_child) && max_end_valid?(node.right_child)
2923
end
3024

31-
describe 'inserts' do
32-
let(:root) { build_tree([15..20, 10..30, 17..19, 5..20, 12..15, 30..40]) }
33-
34-
it 'keeps in-order traversal sorted' do
35-
expect(inorder_keys(root)).to eq(inorder_keys(root).sort)
36-
end
25+
let(:root) { build_tree([15..20, 10..30, 17..19, 5..20, 12..15, 30..40]) }
3726

38-
it 'maintains max_end across the subtree' do
39-
expect(max_end_valid?(root)).to be(true)
40-
end
27+
it 'supports overlap queries for common usage' do
28+
results = root.search_overlaps(14..16).map(&:content)
29+
expect(results.sort_by(&:begin)).to eq([5..20, 10..30, 12..15, 15..20])
4130
end
4231

43-
describe 'search_overlaps' do
44-
let(:root) { build_tree([15..20, 10..30, 17..19, 5..20, 12..15, 30..40]) }
45-
46-
it 'returns all overlapping intervals' do
47-
results = root.search_overlaps(14..16).map(&:content)
48-
expected = [15..20, 10..30, 5..20, 12..15]
49-
expect(results.sort_by(&:begin)).to eq(expected.sort_by(&:begin))
50-
end
32+
it 'supports point queries for common usage' do
33+
results = root.search_point(17).map(&:content)
34+
expect(results.sort_by(&:begin)).to eq([5..20, 10..30, 15..20, 17..19])
5135
end
5236

53-
describe 'search_point' do
54-
let(:root) { build_tree([15..20, 10..30, 17..19, 5..20, 12..15, 30..40]) }
55-
56-
it 'returns all intervals covering the point' do
57-
results = root.search_point(17).map(&:content)
58-
expected = [15..20, 10..30, 17..19, 5..20]
59-
expect(results.sort_by(&:begin)).to eq(expected.sort_by(&:begin))
60-
end
37+
it 'maintains max_end metadata after inserts' do
38+
expect(max_end_valid?(root)).to be(true)
6139
end
6240

63-
describe 'delete' do
64-
let(:root) { build_tree([15..20, 10..30, 17..19, 5..20, 12..15, 30..40]) }
65-
66-
before { root.delete(10..30) }
67-
68-
it 'maintains max_end across the subtree' do
69-
expect(max_end_valid?(root)).to be(true)
70-
end
41+
it 'maintains max_end metadata after delete' do
42+
root.delete(10..30)
43+
expect(max_end_valid?(root)).to be(true)
7144
end
7245
end

0 commit comments

Comments
 (0)