File: ordering_spec.rb

package info (click to toggle)
ruby-rspec 3.13.0c0e0m0s1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,856 kB
  • sloc: ruby: 70,868; sh: 1,423; makefile: 99
file content (171 lines) | stat: -rw-r--r-- 5,924 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
module RSpec
  module Core
    module Ordering
      RSpec.describe Identity do
        it "does not affect the ordering of the items" do
          expect(Identity.new.order([1, 2, 3])).to eq([1, 2, 3])
        end
      end

      RSpec.describe Random do
        describe '.order' do
          subject { described_class.new(configuration) }

          def item(n)
            instance_double(Example, :id => "./some_spec.rb[1:#{n}]")
          end

          let(:configuration)  { RSpec::Core::Configuration.new }
          let(:items)          { 10.times.map { |n| item(n) } }
          let(:shuffled_items) { subject.order items }

          it 'shuffles the items randomly' do
            expect(shuffled_items).to match_array items
            expect(shuffled_items).to_not eq items
          end

          context 'given multiple calls' do
            it 'returns the items in the same order' do
              expect(subject.order(items)).to eq shuffled_items
            end
          end

          def order_with(seed)
            configuration.seed = seed
            subject.order(items)
          end

          it 'has a good distribution', :slow do
            orderings = 1.upto(1000).map do |seed|
              order_with(seed)
            end.uniq

            # Here we are making sure that our hash function used for  ordering has a
            # good distribution. Each seed produces a deterministic order and we want
            # 99%+ of 1000 to be different.
            expect(orderings.count).to be > 990
          end

          context "when given a subset of a list that was previously shuffled with the same seed" do
            it "orders that subset the same as it was ordered before" do
              all_items = 20.times.map { |n| item(n) }

              all_shuffled = subject.order(all_items)
              expect(all_shuffled).not_to eq(all_items)

              last_half = all_items[10, 10]
              last_half_shuffled = subject.order(last_half)
              last_half_from_all_shuffled = all_shuffled.select { |i| last_half.include?(i) }

              expect(last_half_from_all_shuffled.map(&:id)).to eq(last_half_shuffled.map(&:id))
            end
          end

          context 'given randomization has been seeded explicitly' do
            before { @seed = srand }
            after  { srand @seed }

            it "does not affect the global random number generator" do
              srand 123
              val1, val2 = rand(1_000), rand(1_000)

              subject

              srand 123
              subject.order items
              expect(rand(1_000)).to eq(val1)
              subject.order items
              expect(rand(1_000)).to eq(val2)
            end
          end
        end
      end

      RSpec.describe RecentlyModified do
        before do
          allow(File).to receive(:mtime).with('./file_1.rb').and_return(::Time.new)
          allow(File).to receive(:mtime).with('./file_2.rb').and_return(::Time.new + 1)
        end

        it 'orders list by file modification time' do
          file_1 = instance_double(Example, :metadata => { :absolute_file_path => './file_1.rb' })
          file_2 = instance_double(Example, :metadata => { :absolute_file_path => './file_2.rb' })
          strategy = RecentlyModified.new

          expect(strategy.order([file_1, file_2])).to eq([file_2, file_1])
        end
      end

      RSpec.describe Custom do
        it 'uses the block to order the list' do
          strategy = Custom.new(proc { |list| list.reverse })

          expect(strategy.order([1, 2, 3, 4])).to eq([4, 3, 2, 1])
        end
      end

      RSpec.describe Delayed do
        let(:registry) { Registry.new(Configuration.new) }

        it 'looks up a strategy to order the list later on' do
          strategy = Delayed.new(registry, :reverse)
          expect { strategy.order([1, 2, 3, 4]) }.to raise_error("Undefined ordering strategy :reverse")

          registry.register(:reverse, Custom.new(proc { |list| list.reverse }))
          expect(strategy.order([1, 2, 3, 4])).to eq([4, 3, 2, 1])
        end
      end

      RSpec.describe Registry do
        let(:configuration) { Configuration.new }
        subject(:registry) { Registry.new(configuration) }

        describe "#used_random_seed?" do
          it 'returns false if the random orderer has not been used' do
            expect(registry.used_random_seed?).to be false
          end

          it 'returns false if the random orderer has been fetched but not used' do
            expect(registry.fetch(:random)).to be_a(Random)
            expect(registry.used_random_seed?).to be false
          end

          it 'returns true if the random orderer has been used' do
            registry.fetch(:random).order([RSpec.describe, RSpec.describe])
            expect(registry.used_random_seed?).to be true
          end
        end

        describe "#fetch" do
          it "gives the registered ordering when called with a symbol" do
            ordering = Object.new
            subject.register(:falcon, ordering)

            expect(subject.fetch(:falcon)).to be ordering
          end

          context "when given an unrecognized symbol" do
            it 'invokes the given block and returns its value' do
              expect(subject.fetch(:falcon) { :fallback }).to eq(:fallback)
            end

            it 'raises an error if no block is given' do
              expect {
                subject.fetch(:falcon)
              }.to raise_error(IndexError)
            end
          end
        end

        describe "#has_strategy?(name)" do
          it "returns true if the strategy was registered" do
            expect {
              registry.register(:reverse, Custom.new(proc { |list| list.reverse }))
            }.to change { registry.has_strategy?(:reverse) }.from(false).to(true)
          end
        end

      end
    end
  end
end