flores 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Makefile CHANGED
@@ -3,25 +3,6 @@ VERSION=$(shell awk -F\" '/spec.version/ { print $$2 }' $(GEMSPEC))
3
3
  NAME=$(shell awk -F\" '/spec.name/ { print $$2 }' $(GEMSPEC))
4
4
  GEM=$(NAME)-$(VERSION).gem
5
5
 
6
- .PHONY: test
7
- test:
8
- sh notify-failure.sh ruby test/all.rb
9
-
10
- .PHONY: testloop
11
- testloop:
12
- while true; do \
13
- $(MAKE) test; \
14
- $(MAKE) wait-for-changes; \
15
- done
16
-
17
- .PHONY: serve-coverage
18
- serve-coverage:
19
- cd coverage; python -mSimpleHTTPServer
20
-
21
- .PHONY: wait-for-changes
22
- wait-for-changes:
23
- -inotifywait --exclude '\.swp' -e modify $$(find $(DIRS) -name '*.rb'; find $(DIRS) -type d)
24
-
25
6
  .PHONY: package
26
7
  package: | $(GEM)
27
8
 
@@ -1,3 +1,20 @@
1
+ # This file is part of ruby-flores.
2
+ # Copyright (C) 2015 Jordan Sissel
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #
17
+ # encoding: utf-8
1
18
  require "randomized"
2
19
  require "rspec/stress_it"
3
20
 
@@ -1,3 +1,20 @@
1
+ # This file is part of ruby-flores.
2
+ # Copyright (C) 2015 Jordan Sissel
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #
17
+ # encoding: utf-8
1
18
  require "randomized"
2
19
  require "socket"
3
20
  require "rspec/stress_it"
@@ -6,6 +23,10 @@ RSpec.configure do |c|
6
23
  c.extend RSpec::StressIt
7
24
  end
8
25
 
26
+ # A factory for encapsulating behavior of a tcp server and client for the
27
+ # purposes of testing.
28
+ #
29
+ # This is probably not really a "factory" in a purist-sense, but whatever.
9
30
  class TCPIntegrationTestFactory
10
31
  def initialize(port)
11
32
  @listener = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
@@ -33,7 +54,6 @@ class TCPIntegrationTestFactory
33
54
 
34
55
  @client.syswrite(text)
35
56
  @client.close
36
- #expect(client.syswrite(text)).to(be == text.bytesize)
37
57
  server.read
38
58
  ensure
39
59
  @client.close unless @client.closed?
@@ -42,32 +62,12 @@ class TCPIntegrationTestFactory
42
62
  end
43
63
 
44
64
  describe "TCPServer+TCPSocket" do
45
- let(:port) { Randomized.number(1024..65535) }
46
- let(:text) { Randomized.text(1..10000) }
65
+ let(:port) { Randomized.integer(1024..65535) }
66
+ let(:text) { Randomized.text(1..2000) }
47
67
  subject { TCPIntegrationTestFactory.new(port) }
48
-
49
- #describe "using before/after and stress_it2" do
50
- #before do
51
- #begin
52
- #subject.setup
53
- #rescue Errno::EADDRINUSE
54
- ## We chose a random port that was already in use, let's skip this test.
55
- #skip("Port #{port} is in use by another process, skipping")
56
- #end
57
- #end
58
-
59
- #after do
60
- #subject.teardown
61
- #end
62
-
63
- #stress_it2 "should send data correctly" do
64
- #received = subject.send_and_receive(text)
65
- #expect(received).to(be == text)
66
- #end
67
- #end
68
68
 
69
69
  describe "using stress_it" do
70
- stress_it "should send data correctly" do
70
+ analyze_it "should send data correctly", [:port, :text] do
71
71
  begin
72
72
  subject.setup
73
73
  rescue Errno::EADDRINUSE
@@ -76,6 +76,7 @@ describe "TCPServer+TCPSocket" do
76
76
 
77
77
  begin
78
78
  received = subject.send_and_receive(text)
79
+ expect(received.encoding).to(be == text.encoding)
79
80
  expect(received).to(be == text)
80
81
  ensure
81
82
  subject.teardown
@@ -1,3 +1,20 @@
1
+ # This file is part of ruby-flores.
2
+ # Copyright (C) 2015 Jordan Sissel
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #
17
+ # encoding: utf-8
1
18
  require "randomized"
2
19
  require "socket"
3
20
  require "rspec/stress_it"
@@ -12,7 +29,7 @@ describe TCPServer do
12
29
  after { socket.close }
13
30
 
14
31
  context "on a random port" do
15
- let(:port) { Randomized.number(-100000..100000) }
32
+ let(:port) { Randomized.integer(-100_000..100_000) }
16
33
  analyze_it "should bind successfully", [:port] do
17
34
  socket.bind(sockaddr)
18
35
  expect(socket.local_address.ip_port).to(be == port)
@@ -1,3 +1,20 @@
1
+ # This file is part of ruby-flores.
2
+ # Copyright (C) 2015 Jordan Sissel
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #
17
+ # encoding: utf-8
1
18
  require "randomized"
2
19
  require "socket"
3
20
  require "rspec/stress_it"
@@ -13,7 +30,7 @@ describe TCPServer do
13
30
  proc do |m, *args|
14
31
  begin
15
32
  m.call(*args)
16
- rescue Errno::EADDRINUSE
33
+ rescue Errno::EADDRINUSE # rubocop:disable Lint/HandleExceptions
17
34
  # ignore
18
35
  end
19
36
  end
@@ -24,14 +41,14 @@ describe TCPServer do
24
41
  end
25
42
 
26
43
  context "on privileged ports" do
27
- let(:port) { Randomized.number(1..1023) }
44
+ let(:port) { Randomized.integer(1..1023) }
28
45
  stress_it "should raise Errno::EACCESS" do
29
46
  expect { socket.bind(sockaddr) }.to(raise_error(Errno::EACCES))
30
47
  end
31
48
  end
32
49
 
33
50
  context "on unprivileged ports" do
34
- let(:port) { Randomized.number(1025..65535) }
51
+ let(:port) { Randomized.integer(1025..65535) }
35
52
  stress_it "should bind on a port" do
36
53
  # EADDRINUSE is expected since we are picking ports at random
37
54
  # Let's ignore this specific exception
data/flores.gemspec CHANGED
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |spec|
2
- files = %x{git ls-files}.split("\n")
2
+ files = %x(git ls-files).split("\n")
3
3
 
4
4
  spec.name = "flores"
5
- spec.version = "0.0.1"
5
+ spec.version = "0.0.2"
6
6
  spec.summary = "Fuzz, randomize, and stress your tests"
7
7
  spec.description = <<-DESCRIPTION
8
8
  Add fuzzing, randomization, and stress to your tests.
@@ -20,4 +20,3 @@ Gem::Specification.new do |spec|
20
20
  spec.authors = ["Jordan Sissel"]
21
21
  spec.email = ["jls@semicomplete.com"]
22
22
  end
23
-
data/lib/randomized.rb CHANGED
@@ -1,5 +1,42 @@
1
+ # This file is part of ruby-flores.
2
+ # Copyright (C) 2015 Jordan Sissel
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #
17
+ # encoding: utf-8
18
+
1
19
  # A collection of methods intended for use in randomized testing.
2
20
  module Randomized
21
+ # A selection of UTF-8 characters
22
+ #
23
+ # I'd love to generate this, but I don't yet know enough about how unicode
24
+ # blocks are allocated to do that. For now, hardcode a set of possible
25
+ # characters.
26
+ CHARACTERS = [
27
+ # Basic Latin
28
+ *(32..126).map(&:chr),
29
+
30
+ # hand-selected CJK Unified Ideographs Extension A
31
+ "㐤", "㐨", "㐻", "㑐",
32
+
33
+ # hand-selected Hebrew
34
+ "א", "ב", "ג", "ד", "ה",
35
+
36
+ # hand-selected Cyrillic
37
+ "Є", "Б", "Р", "н", "я"
38
+ ]
39
+
3
40
  # Generates text with random characters of a given length (or within a length range)
4
41
  #
5
42
  # * The length can be a number or a range `x..y`. If a range, it must be ascending (x < y)
@@ -8,30 +45,23 @@ module Randomized
8
45
  # @param length [Fixnum or Range] the length of text to generate
9
46
  # @return [String] the
10
47
  def self.text(length)
11
- if length.is_a?(Range)
12
- raise ArgumentError, "Requires ascending range, you gave #{length}." if length.end < length.begin
13
- raise ArgumentError, "A negative length is not permitted, I received range #{length}" if length.begin < 0
14
-
15
- length = integer(length)
16
- else
17
- raise ArgumentError, "A negative length is not permitted, I received #{length}" if length < 0
18
- end
48
+ return text_range(length) if length.is_a?(Range)
19
49
 
50
+ raise ArgumentError, "A negative length is not permitted, I received #{length}" if length < 0
20
51
  length.times.collect { character }.join
21
52
  end # def text
22
53
 
54
+ def self.text_range(range)
55
+ raise ArgumentError, "Requires ascending range, you gave #{range}." if range.end < range.begin
56
+ raise ArgumentError, "A negative range values are not permitted, I received range #{range}" if range.begin < 0
57
+ text(integer(range))
58
+ end
59
+
23
60
  # Generates a random character (A string of length 1)
24
61
  #
25
62
  # @return [String]
26
63
  def self.character
27
- # TODO(sissel): Add support to generate valid UTF-8. I started reading
28
- # Unicode 7 (http://www.unicode.org/versions/Unicode7.0.0/) and after much
29
- # reading, I realized I wasn't in my house anymore but had somehow lost
30
- # track of time and was alone in a field. Civilization had fallen centuries
31
- # ago. :P
32
-
33
- # Until UTF-8 is supported, just return a random lower ASCII character
34
- integer(32..127).chr
64
+ return CHARACTERS[integer(0...CHARACTERS.length)]
35
65
  end # def character
36
66
 
37
67
  # Return a random integer value within a given range.
@@ -64,4 +94,4 @@ module Randomized
64
94
  integer(range).times
65
95
  end
66
96
  end # def iterations
67
- end
97
+ end # module Randomized
@@ -1,6 +1,31 @@
1
+ # This file is part of ruby-flores.
2
+ # Copyright (C) 2015 Jordan Sissel
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #
1
17
  # encoding: utf-8
2
18
  require "rspec/core"
3
19
 
20
+ # RSpec helpers for stress testing examples
21
+ #
22
+ # Setting it up in rspec:
23
+ #
24
+ # RSpec.configure do |c|
25
+ # c.extend RSpec::StressIt
26
+ # end
27
+ #
28
+ # TODO(sissel): Show an example of stress_it and analyze_it
4
29
  module RSpec::StressIt
5
30
  DEFAULT_ITERATIONS = 1..5000
6
31
 
@@ -10,11 +35,11 @@ module RSpec::StressIt
10
35
  # of APIs to help find edge cases and weird behavior.
11
36
  #
12
37
  # The default number of iterations is randomly selected between 1 and 1000 inclusive
13
- def stress_it(name, options={}, &block)
14
- __iterations = Randomized.iterations(options.delete(:stress_iterations) || DEFAULT_ITERATIONS)
38
+ def stress_it(name, options = {}, &block)
39
+ stress__iterations = Randomized.iterations(options.delete(:stress_iterations) || DEFAULT_ITERATIONS)
15
40
  it(name, options) do
16
41
  # Run the block of an example many times
17
- __iterations.each do |i|
42
+ stress__iterations.each do
18
43
  # Run the block within 'it' scope
19
44
  instance_eval(&block)
20
45
 
@@ -34,10 +59,10 @@ module RSpec::StressIt
34
59
  # it "should be less than 100" do
35
60
  # expect(number).to(be < 100)
36
61
  # end
37
- def stress_it2(name, options={}, &block)
38
- __iterations = Randomized.iterations(options.delete(:stress_iterations) || DEFAULT_ITERATIONS)
39
- __iterations.each do |i|
40
- it(example_name + " [#{i}]", *args) do
62
+ def stress_it2(name, options = {}, &block)
63
+ stress__iterations = Randomized.iterations(options.delete(:stress_iterations) || DEFAULT_ITERATIONS)
64
+ stress__iterations.each do |i|
65
+ it(name + " [#{i}]", *args) do
41
66
  instance_eval(&block)
42
67
  end # it ...
43
68
  end # .times
@@ -57,18 +82,17 @@ module RSpec::StressIt
57
82
  # end
58
83
  #
59
84
  # Example report:
60
- def analyze_it(name, variables, &block)
85
+ def analyze_it(name, variables, &block) # rubocop:disable Metrics/AbcSize
61
86
  it(name) do
62
- results = Hash.new { |h,k| h[k] = [] }
63
- iterations = Randomized.iterations(DEFAULT_ITERATIONS)
64
- iterations.each do |i|
87
+ results = Hash.new { |h, k| h[k] = [] }
88
+ Randomized.iterations(DEFAULT_ITERATIONS).each do
65
89
  state = Hash[variables.collect { |l| [l, __send__(l)] }]
66
90
  begin
67
91
  instance_eval(&block)
68
92
  results[:success] << [state, nil]
69
93
  rescue => e
70
94
  results[e.class] << [state, e]
71
- rescue Exception => e
95
+ rescue Exception => e # rubocop:disable Lint/RescueException
72
96
  results[e.class] << [state, e]
73
97
  end
74
98
 
@@ -76,20 +100,19 @@ module RSpec::StressIt
76
100
  __memoized.clear
77
101
  end
78
102
 
79
- if results[:success] != iterations
80
- raise Analysis.new(results)
81
- end
103
+ raise StandardError, Analysis.new(results) if results.any? { |k, _| k != :success }
82
104
  end
83
- end
105
+ end # def analyze_it
84
106
 
107
+ # A formatter to show analysis of an `analyze_it` example.
85
108
  class Analysis < StandardError
86
109
  def initialize(results)
87
110
  @results = results
88
- end
111
+ end # def initialize
89
112
 
90
113
  def total
91
- @results.reduce(0) { |m, (k,v)| m + v.length }
92
- end
114
+ @results.reduce(0) { |m, (_, v)| m + v.length }
115
+ end # def total
93
116
 
94
117
  def success_count
95
118
  if @results.include?(:success)
@@ -97,33 +120,54 @@ module RSpec::StressIt
97
120
  else
98
121
  0
99
122
  end
100
- end
123
+ end # def success_count
101
124
 
102
125
  def percent(count)
103
126
  return (count + 0.0) / total
104
- end
127
+ end # def percent
105
128
 
106
129
  def percent_s(count)
107
- return sprintf("%.2f%%", percent(count) * 100)
108
- end
130
+ return format("%.2f%%", percent(count) * 100)
131
+ end # def percent_s
109
132
 
110
133
  def to_s
111
134
  # This method is crazy complex for a formatter. Should refactor this significantly.
112
135
  report = ["#{percent_s(success_count)} tests successful of #{total} tests"]
113
- if success_count < total
114
- report << "Failure analysis:"
115
- report += @results.sort_by { |k,v| -v.length }.reject { |k,v| k == :success }.collect do |k, v|
116
- sample = v.sample(5).collect { |v| v.first }.join(", ")
117
- [
118
- " #{percent_s(v.length)} -> [#{v.length}] #{k}",
119
- " Sample exception:",
120
- v.sample(1).first[1].to_s.gsub(/^/, " "),
121
- " Samples causing #{k}:",
122
- *v.sample(5).collect { |state, _exception| " #{state}" }
123
- ]
124
- end.flatten
125
- end
136
+ report += failure_summary if success_count < total
126
137
  report.join("\n")
127
- end
128
- end
138
+ end # def to_s
139
+
140
+ # TODO(sissel): All these report/summary/to_s things are an indication that the
141
+ # report formatting belongs in a separate class.
142
+ def failure_summary
143
+ report = ["Failure analysis:"]
144
+ report += @results.sort_by { |_, v| -v.length }.collect do |group, instances|
145
+ next if group == :success
146
+ error_report(group, instances)
147
+ end.reject(&:nil?).flatten
148
+ report
149
+ end # def failure_summary
150
+
151
+ def error_report(error, instances)
152
+ report = error_summary(error, instances)
153
+ report += error_sample_states(error, instances) if instances.size > 1
154
+ report
155
+ end # def error_report
156
+
157
+ def error_summary(error, instances)
158
+ sample = instances.sample(1)
159
+ [
160
+ " #{percent_s(instances.length)} -> [#{instances.length}] #{error}",
161
+ " Sample exception for #{sample.first[0]}",
162
+ sample.first[1].to_s.gsub(/^/, " ")
163
+ ]
164
+ end # def error_summary
165
+
166
+ def error_sample_states(error, instances)
167
+ [
168
+ " Samples causing #{error}:",
169
+ *instances.sample(5).collect { |state, _exception| " #{state}" }
170
+ ]
171
+ end # def error_sample_states
172
+ end # class Analysis
129
173
  end # module RSpec::StressIt
@@ -1,3 +1,20 @@
1
+ # This file is part of ruby-flores.
2
+ # Copyright (C) 2015 Jordan Sissel
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as
6
+ # published by the Free Software Foundation, either version 3 of the
7
+ # License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #
17
+ # encoding: utf-8
1
18
  require "randomized"
2
19
  require "rspec/stress_it"
3
20
 
@@ -5,10 +22,19 @@ RSpec.configure do |c|
5
22
  c.extend RSpec::StressIt
6
23
  end
7
24
 
25
+ shared_examples_for String do |variables|
26
+ analyze_it "should be a String", variables do
27
+ expect(subject).to(be_a(String))
28
+ end
29
+ analyze_it "have valid encoding", variables do
30
+ expect(subject).to(be_valid_encoding)
31
+ end
32
+ end
33
+
8
34
  describe Randomized do
9
35
  describe "#text" do
10
36
  context "with no arguments" do
11
- it "should raise ArgumentError" do
37
+ stress_it "should raise ArgumentError" do
12
38
  expect { subject.text }.to(raise_error(ArgumentError))
13
39
  end
14
40
  end
@@ -18,15 +44,15 @@ describe Randomized do
18
44
 
19
45
  context "that is positive" do
20
46
  let(:length) { rand(1..1000) }
21
- stress_it "should give a string with that length" do
22
- expect(subject).to(be_a(String))
47
+ it_behaves_like String, [:length]
48
+ analyze_it "has correct length", [:length] do
23
49
  expect(subject.length).to(eq(length))
24
50
  end
25
51
  end
26
52
 
27
53
  context "that is negative" do
28
54
  let(:length) { -1 * rand(1..1000) }
29
- stress_it "should raise ArgumentError" do
55
+ analyze_it "should raise ArgumentError", [:length] do
30
56
  expect { subject }.to(raise_error(ArgumentError))
31
57
  end
32
58
  end
@@ -38,16 +64,17 @@ describe Randomized do
38
64
  subject { described_class.text(range) }
39
65
 
40
66
  context "that is ascending" do
41
- let(:range) { start .. (start + length) }
42
- stress_it "should give a string within that length range" do
67
+ let(:range) { start..(start + length) }
68
+ it_behaves_like String, [:range]
69
+ analyze_it "should give a string within that length range", [:range] do
43
70
  expect(subject).to(be_a(String))
44
71
  expect(range).to(include(subject.length))
45
72
  end
46
73
  end
47
74
 
48
75
  context "that is descending" do
49
- let(:range) { start .. (start - length) }
50
- stress_it "should raise ArgumentError" do
76
+ let(:range) { start..(start - length) }
77
+ analyze_it "should raise ArgumentError", [:range] do
51
78
  expect { subject }.to(raise_error(ArgumentError))
52
79
  end
53
80
  end
@@ -56,40 +83,50 @@ describe Randomized do
56
83
 
57
84
  describe "#character" do
58
85
  subject { described_class.character }
59
- stress_it "returns a string of length 1" do
86
+ it_behaves_like String, [:subject]
87
+ analyze_it "has length == 1", [:subject] do
60
88
  expect(subject.length).to(be == 1)
61
89
  end
62
90
  end
63
91
 
64
- shared_examples_for "random numbers within a range" do
65
- let(:start) { Randomized.integer(-100000 .. 100000) }
66
- let(:length) { Randomized.integer(1 .. 100000) }
67
- let(:range) { start .. (start + length) }
92
+ shared_examples_for Numeric do |type|
93
+ let(:start) { Randomized.integer(-100_000..100_000) }
94
+ let(:length) { Randomized.integer(1..100_000) }
95
+ let(:range) { start..(start + length) }
68
96
 
69
- stress_it "should be a Numeric" do
70
- expect(subject).to(be_a(Numeric))
97
+ analyze_it "should be a #{type}", [:range] do
98
+ expect(subject).to(be_a(type))
71
99
  end
72
100
 
73
- stress_it "should be within the bounds of the given range" do
101
+ analyze_it "should be within the bounds of the given range", [:range] do
74
102
  expect(range).to(include(subject))
75
103
  end
76
104
  end
77
105
 
78
106
  describe "#integer" do
79
- it_behaves_like "random numbers within a range" do
107
+ it_behaves_like Numeric, Fixnum do
80
108
  subject { Randomized.integer(range) }
81
- stress_it "is a Fixnum" do
82
- expect(subject).to(be_a(Fixnum))
83
- end
84
109
  end
85
110
  end
111
+
86
112
  describe "#number" do
87
- it_behaves_like "random numbers within a range" do
113
+ it_behaves_like Numeric, Float do
88
114
  subject { Randomized.number(range) }
115
+ end
116
+ end
89
117
 
90
- stress_it "is a Float" do
91
- expect(subject).to(be_a(Float))
92
- end
118
+ describe "#iterations" do
119
+ let(:start) { Randomized.integer(1..100_000) }
120
+ let(:length) { Randomized.integer(1..100_000) }
121
+ let(:range) { start..(start + length) }
122
+ subject { Randomized.iterations(range) }
123
+
124
+ analyze_it "should return an Enumerable", [:range] do
125
+ expect(subject).to(be_a(Enumerable))
126
+ end
127
+
128
+ analyze_it "should have a size within the expected range", [:range] do
129
+ expect(range).to(include(subject.size))
93
130
  end
94
131
  end
95
132
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flores
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Sissel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-19 00:00:00.000000000 Z
11
+ date: 2015-02-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14
  Add fuzzing, randomization, and stress to your tests.
@@ -23,8 +23,10 @@ executables: []
23
23
  extensions: []
24
24
  extra_rdoc_files: []
25
25
  files:
26
+ - ".rubocop.yml"
26
27
  - Gemfile
27
28
  - Gemfile.lock
29
+ - LICENSE.txt
28
30
  - Makefile
29
31
  - examples/analyze_number.rb
30
32
  - examples/socket_acceptance_spec.rb