generative 0.2.0 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 02a4f62bfe5c5c3d05c10bc1196bb33abe6ee992
4
- data.tar.gz: e692488353ac4202143d4ac3ec18597a72c5f10b
2
+ SHA256:
3
+ metadata.gz: 3dc4a220c7ed12097f5fa3fad6118130d716c7836146303ea35a33566fd44313
4
+ data.tar.gz: 05bc94db4ae4340694a1acbd7d6ffd9f83f352bf36a9fd9571836d6fff00464f
5
5
  SHA512:
6
- metadata.gz: 9840d498e882fec2575c43153a6c618988b2b8931923d7645c59d46ee0b82fa37e3b1797d6e5353fb5e272d9c6e5d173d478afc15981fba0d6c832e4ca0ef8a6
7
- data.tar.gz: 4876dafd32294af5d8d74324263e84a6e840467667d7ead681dff0c68b179ace66fd585ebf5060b5a923f4eb7d704a952d59e2f41aee441f3f610def7fec49d5
6
+ metadata.gz: a49da806f77ba8a38e40b72a146429cc7e4dc63260de5a201aadded4a484b41db7ec7a3239f30202597172943de3b3fc3c28da62ba4c1b15d3649e843798e5d0
7
+ data.tar.gz: 6803173dd0267d2a00291e47904524872bc2e8f9945f757498122bf64fddb1cf78c02ecd3d7bd50f55bd47d11d87692e867cbd062d6d919a9cb505e6a74a43ae
@@ -0,0 +1,26 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+
12
+ runs-on: ubuntu-latest
13
+
14
+ strategy:
15
+ matrix:
16
+ ruby-version: ["3.0", "2.7", "2.6", "2.5", "ruby-head"]
17
+
18
+ steps:
19
+ - uses: actions/checkout@v2
20
+ - name: Set up Ruby ${{ matrix.ruby-version }}
21
+ uses: ruby/setup-ruby@v1
22
+ with:
23
+ ruby-version: ${{ matrix.ruby-version }}
24
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
25
+ - name: Run tests
26
+ run: bundle exec rake ci
data/CHANGELOG.md CHANGED
@@ -1,14 +1,32 @@
1
1
  # Changelog
2
2
 
3
- ## 0.2.0
3
+ ## 0.2.5 (2022-01-25)
4
+
5
+ https://github.com/justincampbell/generative/compare/v0.2.4...v0.2.5
6
+
7
+ - Fix: require forwardable ([#30](https://github.com/justincampbell/generative/pull/30))
8
+
9
+ ## 0.2.4 (2016-09-15)
10
+
11
+ https://github.com/justincampbell/generative/compare/v0.2.4...v0.2.4
12
+
13
+ ## 0.2.3 (2014-12-16)
14
+
15
+ https://github.com/justincampbell/generative/compare/v0.2.2...v0.2.3
16
+
17
+ ## 0.2.2 (2014-12-08)
18
+
19
+ https://github.com/justincampbell/generative/compare/v0.2.0...v0.2.2
20
+
21
+ ## 0.2.0 (2014-08-13)
4
22
 
5
23
  * Drop support for RSpec 2
6
24
  * Update RSpec integration to support RSpec 3 final (@jessitron)
7
25
 
8
- ## 0.1.0
26
+ ## 0.1.0 (2013-12-18)
9
27
 
10
28
  * Add support for RSpec 2
11
29
 
12
- ## 0.0.1
30
+ ## 0.0.1 (2013-11-21)
13
31
 
14
32
  * Initial release
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Generative
2
2
 
3
- > Generative testing for RSpec
4
- > [![Gem Version](https://badge.fury.io/rb/generative.png)](http://badge.fury.io/rb/generative)
5
- > [![Build Status](https://travis-ci.org/justincampbell/generative.png?branch=master)](https://travis-ci.org/justincampbell/generative)
6
- > [![Code Climate](https://codeclimate.com/github/justincampbell/generative.png)](https://codeclimate.com/github/justincampbell/generative)
3
+ > Generative and property-based testing for RSpec
4
+ > [![Gem Version](https://badge.fury.io/rb/generative.svg)](http://badge.fury.io/rb/generative)
5
+ > [![CI](https://github.com/justincampbell/generative/actions/workflows/ci.yml/badge.svg)](https://github.com/justincampbell/generative/actions/workflows/ci.yml)
6
+ > [![Code Climate](https://codeclimate.com/github/justincampbell/generative.svg)](https://codeclimate.com/github/justincampbell/generative)
7
7
 
8
8
  ## Installation
9
9
 
@@ -22,7 +22,7 @@ end
22
22
 
23
23
  ```
24
24
  --color
25
- --format progress
25
+ --format Generative::Formatter
26
26
  --require generative
27
27
  ```
28
28
 
@@ -48,7 +48,7 @@ would a `let`. Then, write your `it`/`specify` blocks as usual (while keeping
48
48
  in mind that the input could be anything).
49
49
 
50
50
  ```rb
51
- describe String do
51
+ RSpec.describe String do
52
52
  let(:string) { "abc" }
53
53
 
54
54
  describe "#reverse" do
@@ -71,6 +71,22 @@ describe String do
71
71
  end
72
72
  ```
73
73
 
74
+ Alternatively, you can modify existing specs in a minimally intrusive way by just adding two tags to an existing context and using the fact that `data` is just an alias for `let`:
75
+ ```ruby
76
+ RSpec.describe String do
77
+ describe "#reverse", generative: true, order: :generative do
78
+ let(:string) { rand(12345).to_s }
79
+
80
+ it "maintains length" do
81
+ expect(string.reverse.length).to eq(string.length)
82
+ end
83
+
84
+ it "is not destructive" do
85
+ expect(string.reverse.reverse).to eq(string)
86
+ end
87
+ end
88
+ end
89
+ ```
74
90
  ### Running
75
91
 
76
92
  Generative comes with a `generative` command, which simply runs rspec with the
@@ -79,7 +95,7 @@ required arguments:
79
95
  ```
80
96
  $ generative
81
97
  + GENERATIVE_COUNT=10_000
82
- + rspec --require generative --format Generative --tag generative
98
+ + rspec --require generative --format Generative::Formatter --tag generative
83
99
  Run options: include {:generative=>true}
84
100
 
85
101
  String
@@ -110,3 +126,88 @@ Given the examples above, running `rspec` will use the default "progress"
110
126
  formatter. Requiring generative will modify this formatter to output blue dots
111
127
  instead of green for generative tests. Generative also includes it's own
112
128
  formatter, which will only display generative test names once, also in blue.
129
+
130
+ ### Generators
131
+
132
+ Generative allows you to register your own custom generators for generative
133
+ tests. Registering a generator requires two thing, a name and an object that
134
+ responds to `#call`.
135
+
136
+ Whether you just want to use lambdas.
137
+
138
+ ```rb
139
+ Generative.register_generator(:full_name) { "#{Generative.generate(:string)} #{Generative.generate(:string}" }
140
+
141
+ Generative.register_generator(:user) { FactoryGirl.build(:user, id: Generative.generate(:integer)) }
142
+ ```
143
+
144
+ A class or module that responds to `#call`.
145
+
146
+ ```rb
147
+ class LameGenerator
148
+ def self.call
149
+ random_string
150
+ end
151
+ end
152
+
153
+ Generative.register_generator(:lame, LameGenerator)
154
+ ```
155
+
156
+ Or you want to use a fancy library.
157
+
158
+ ```rb
159
+ FakeTypeMappingLibrary
160
+ generator_for Bar do
161
+ initializer Float, Fixnum
162
+
163
+ accessor :baz, Float
164
+ accessor :quz, NotherClass
165
+ end
166
+ end
167
+
168
+ Generative.register_generator(:bar, Bar }
169
+ ```
170
+
171
+ You can then use your generators using the `generate` helper.
172
+
173
+ ```rb
174
+ RSpec.describe String do
175
+ let(:string) { "abc" }
176
+
177
+ describe "#reverse" do
178
+ generative do
179
+ data(:string) { generate(:my_fancy_string) }
180
+
181
+ it "maintains length" do
182
+ expect(string.reverse.length).to eq(string.length)
183
+ end
184
+ end
185
+ end
186
+ end
187
+ ```
188
+
189
+ #### I heard you like generators so I put some generators in your generators...
190
+
191
+ If you want to use other generators in your registered generator, do note
192
+ you have to use Generative's module level method `.generate` like so...
193
+
194
+ ```rb
195
+ Generative.register_generator :user do
196
+ User.new( first_name: Generative.generate(:string, max: 100) )
197
+ end
198
+ ```
199
+
200
+
201
+
202
+ ### Pre-made Generators
203
+
204
+ **Note**: At this time Generative provides no pre-made generators. We
205
+ encourage you to go out and seek good ways of generating
206
+ data and maybe even package them up as your own gems. If you
207
+ do, let us know and we'll link to it here.
208
+
209
+
210
+ #### [Degenerate](https://github.com/niftyn8/degenerate)
211
+
212
+ This library has a few generators for some basic primitives... A great start if
213
+ you're looking to move quickly.
data/Rakefile CHANGED
@@ -13,10 +13,10 @@ task :acceptance do
13
13
  ENV.delete('GENERATIVE_COUNT')
14
14
 
15
15
  [
16
- ['rspec', '13'],
17
- ['rake spec', '13'],
18
- ['rake generative', '30000'],
19
- ['bin/generative', '30000']
16
+ ['rspec', '22'], # can we do this some other way
17
+ ['rake spec', '22'], # sucks to bump as we add tests...
18
+ ['rake generative', '40000'],
19
+ ['bin/generative', '40000']
20
20
  ].each do |command, expected_example_count|
21
21
  puts "Checking output of `#{command}`"
22
22
  output = %x{#{command}}
data/bin/generative CHANGED
@@ -13,7 +13,7 @@ command = %w[
13
13
  --tag generative
14
14
  ].join(' ')
15
15
 
16
- command = "GENERATIVE_COUNT=#{ENV['GENERATIVE_COUNT']} #{command}"
16
+ command = "export GENERATIVE_COUNT=#{ENV['GENERATIVE_COUNT']}; #{command}; unset GENERATIVE_COUNT"
17
17
 
18
18
  puts command
19
19
  system command
data/generative.gemspec CHANGED
@@ -2,19 +2,24 @@
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
+ authors = {
6
+ "Justin Campbell" => "justin@justincampbell.com",
7
+ "Dan McClory" => "danmcclory@gmail.com",
8
+ "Nate West" => "natescott.west@gmail.com"
9
+ }
10
+
5
11
  Gem::Specification.new do |gem|
6
12
  gem.name = 'generative'
7
- gem.version = '0.2.0'
8
- gem.authors = ["Justin Campbell", "Dan McClory"]
9
- gem.email = ["justin@justincampbell.me", "danmcclory@gmail.com"]
10
- gem.description = "Generative testing for RSpec"
11
- gem.summary = "Generative testing for RSpec"
13
+ gem.version = '0.2.5'
14
+ gem.authors = authors.keys
15
+ gem.email = authors.values
16
+ gem.description = "Generative and property-based testing for RSpec"
17
+ gem.summary = "Generative and property-based testing for RSpec"
12
18
  gem.homepage = "https://github.com/justincampbell/generative"
13
19
  gem.license = 'MIT'
14
20
 
15
21
  gem.files = `git ls-files`.split($/)
16
22
  gem.executables = gem.files.grep(%r{^bin/}).map { |file| File.basename file }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
23
  gem.require_paths = ["lib"]
19
24
 
20
25
  gem.add_dependency 'rspec', '>= 3.0'
@@ -4,5 +4,10 @@ class RSpec::Core::ExampleGroup
4
4
 
5
5
  class << self
6
6
  alias_method :data, :let
7
+ alias_method :for_every, :let
8
+ end
9
+
10
+ def generate(generator_name, *args)
11
+ Generative.generate(generator_name, *args)
7
12
  end
8
13
  end
@@ -37,7 +37,8 @@ module Generative
37
37
  output.puts if @group_level == 0
38
38
 
39
39
  if generative?(example_group)
40
- output.puts "#{current_indentation}#{detail_color('generative')}"
40
+ group_description = "#{example_group.description} (generative)"
41
+ output.puts "#{current_indentation}#{detail_color(group_description)}"
41
42
 
42
43
  @group_level += 1
43
44
  example_group.examples.each do |example|
@@ -72,7 +73,7 @@ module Generative
72
73
  example = notification.example
73
74
 
74
75
  if generative?(example)
75
- RSpec.wants_to_quit = true
76
+ RSpec.world.wants_to_quit = true
76
77
  end
77
78
 
78
79
  super
@@ -0,0 +1,30 @@
1
+ module Generative
2
+ class InvalidGenerator < StandardError; end
3
+ class UnregisteredGenerator < StandardError; end
4
+
5
+ class GeneratorManager
6
+
7
+ attr_reader :generators
8
+
9
+ def initialize(preregistered_generators={})
10
+ @generators = Hash.new(preregistered_generators)
11
+ end
12
+
13
+ def register_generator(name, factory=nil, &generator)
14
+ registerable = block_given? ? generator : factory
15
+ msg = "#{registerable} must respond to :call"
16
+ raise InvalidGenerator, msg unless generator_valid?(registerable)
17
+ @generators.merge!(name => registerable)
18
+ end
19
+
20
+ def find_and_call(name, *args)
21
+ generators.fetch(name) do
22
+ raise UnregisteredGenerator, "#{name} generator not registered"
23
+ end.call(*args)
24
+ end
25
+
26
+ def generator_valid?(generator)
27
+ generator.respond_to?(:call)
28
+ end
29
+ end
30
+ end
@@ -8,7 +8,7 @@ module Generative
8
8
 
9
9
  self.name = :generative if name == :spec
10
10
 
11
- desc "Run Generative specs" unless Rake.application.last_comment
11
+ desc "Run Generative specs" unless Rake.application.last_description
12
12
 
13
13
  options = %w[
14
14
  --require generative
data/lib/generative.rb CHANGED
@@ -1,8 +1,29 @@
1
1
  require 'rspec/core'
2
+ require 'forwardable'
2
3
 
3
4
  module Generative
5
+
4
6
  DEFAULT_COUNT = '10_000'
5
7
 
8
+ class << self
9
+ extend Forwardable
10
+ def_delegators :manager, :register_generator, :find_and_call
11
+ end
12
+
13
+ def self.generate(generator_name, *args)
14
+ find_and_call(generator_name, *args)
15
+ end
16
+
17
+ def self.manager
18
+ @manager ||= GeneratorManager.new(preregistered_generators)
19
+ end
20
+
21
+ def self.preregistered_generators
22
+ {
23
+ # nothing to see here yet
24
+ }
25
+ end
26
+
6
27
  def self.running?
7
28
  !!ENV['GENERATIVE_COUNT']
8
29
  end
@@ -11,3 +32,4 @@ end
11
32
  require 'generative/dsl'
12
33
  require 'generative/formatters'
13
34
  require 'generative/ordering'
35
+ require 'generative/generator_manager'
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Generative::GeneratorManager do
4
+
5
+ subject { Generative::GeneratorManager.new }
6
+
7
+ describe "#register_generator_generator" do
8
+ it "throws an exception if a block or a factory object isn't given" do
9
+ expect { subject.register_generator(:test) }.to raise_error(Generative::InvalidGenerator)
10
+ end
11
+
12
+ it "registers a new generator when given a generator block" do
13
+ name, generator = :test, lambda { "hi" }
14
+ expect(subject.generators).not_to include(name)
15
+ expect(subject.register_generator(name) { "hi" }).to include(name)
16
+ expect(subject.generators[name].call).to eq("hi")
17
+ end
18
+
19
+ it "registers a new generator when given a factory object" do
20
+ name, factory = :test, OpenStruct.new(call: true)
21
+ expect(subject.generators).not_to include(name)
22
+ expect(subject.register_generator(name, factory)).to include(name)
23
+ expect(subject.generators[name].call).to be_truthy
24
+ end
25
+ end
26
+
27
+ describe "#find_and_call" do
28
+ it "calls a specific generator passing in it's arguments" do
29
+ name, generator = :test, lambda { |arg| arg }
30
+ subject.register_generator(name, &generator)
31
+ expect(subject.find_and_call(name, "hi")).to eq("hi")
32
+ end
33
+
34
+ it "raises an error fo ran unregistered generator" do
35
+ expect { subject.find_and_call(:nope) }
36
+ .to raise_error(Generative::UnregisteredGenerator)
37
+ end
38
+
39
+ describe "#generator_valid?" do
40
+ it "returns false if an object doesn't respond to :call or :build" do
41
+ expect(subject.generator_valid?(nil)).to be_falsey
42
+ end
43
+
44
+ it "returns true if an object doesn't respond to :call" do
45
+ generator = OpenStruct.new(call: true)
46
+ expect(subject.generator_valid?(generator)).to be_truthy
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Generative::ORDERING do
3
+ RSpec.describe Generative::ORDERING do
4
4
  let(:ordering) { Generative::ORDERING }
5
5
 
6
6
  around do |example|
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'generative/rake_task'
3
3
 
4
- describe Generative::RakeTask do
4
+ RSpec.describe Generative::RakeTask do
5
5
  let(:task) { Generative::RakeTask.new(*args) }
6
6
  let(:args) { [] }
7
7
 
@@ -1,6 +1,8 @@
1
1
  require 'generative'
2
2
 
3
- describe String do
3
+ Generative.register_generator(:string) { "a" * rand(255) }
4
+
5
+ RSpec.describe String do
4
6
  let(:string) { "abc" }
5
7
 
6
8
  describe "#length" do
@@ -17,6 +19,16 @@ describe String do
17
19
  expect(string.length).to be >= 0
18
20
  end
19
21
  end
22
+
23
+ xit "uses registered generators"
24
+
25
+ generative do
26
+ data(:string) { generate(:string) }
27
+
28
+ it "is never negative" do
29
+ expect(string.length).to be >= 0
30
+ end
31
+ end
20
32
  end
21
33
 
22
34
  describe "#reverse" do
data/spec/spec_helper.rb CHANGED
@@ -20,4 +20,5 @@ RSpec.configure do |config|
20
20
  # the seed, which is printed after each run.
21
21
  # --seed 1234
22
22
  #config.order = 'random'
23
+ config.disable_monkey_patching!
23
24
  end
metadata CHANGED
@@ -1,56 +1,58 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: generative
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Campbell
8
8
  - Dan McClory
9
- autorequire:
9
+ - Nate West
10
+ autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2014-08-12 00:00:00.000000000 Z
13
+ date: 2022-01-25 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: rspec
16
17
  requirement: !ruby/object:Gem::Requirement
17
18
  requirements:
18
- - - '>='
19
+ - - ">="
19
20
  - !ruby/object:Gem::Version
20
21
  version: '3.0'
21
22
  type: :runtime
22
23
  prerelease: false
23
24
  version_requirements: !ruby/object:Gem::Requirement
24
25
  requirements:
25
- - - '>='
26
+ - - ">="
26
27
  - !ruby/object:Gem::Version
27
28
  version: '3.0'
28
29
  - !ruby/object:Gem::Dependency
29
30
  name: rake
30
31
  requirement: !ruby/object:Gem::Requirement
31
32
  requirements:
32
- - - '>='
33
+ - - ">="
33
34
  - !ruby/object:Gem::Version
34
35
  version: '0'
35
36
  type: :development
36
37
  prerelease: false
37
38
  version_requirements: !ruby/object:Gem::Requirement
38
39
  requirements:
39
- - - '>='
40
+ - - ">="
40
41
  - !ruby/object:Gem::Version
41
42
  version: '0'
42
- description: Generative testing for RSpec
43
+ description: Generative and property-based testing for RSpec
43
44
  email:
44
- - justin@justincampbell.me
45
+ - justin@justincampbell.com
45
46
  - danmcclory@gmail.com
47
+ - natescott.west@gmail.com
46
48
  executables:
47
49
  - generative
48
50
  extensions: []
49
51
  extra_rdoc_files: []
50
52
  files:
51
- - .gitignore
52
- - .rspec
53
- - .travis.yml
53
+ - ".github/workflows/ci.yml"
54
+ - ".gitignore"
55
+ - ".rspec"
54
56
  - CHANGELOG.md
55
57
  - Gemfile
56
58
  - LICENSE.txt
@@ -61,9 +63,11 @@ files:
61
63
  - lib/generative.rb
62
64
  - lib/generative/dsl.rb
63
65
  - lib/generative/formatters.rb
66
+ - lib/generative/generator_manager.rb
64
67
  - lib/generative/ordering.rb
65
68
  - lib/generative/rake_task.rb
66
69
  - lib/generative/version.rb
70
+ - spec/generative/generator_manager_spec.rb
67
71
  - spec/generative/ordering_spec.rb
68
72
  - spec/generative/rake_task_spec.rb
69
73
  - spec/generative_spec.rb
@@ -72,29 +76,23 @@ homepage: https://github.com/justincampbell/generative
72
76
  licenses:
73
77
  - MIT
74
78
  metadata: {}
75
- post_install_message:
79
+ post_install_message:
76
80
  rdoc_options: []
77
81
  require_paths:
78
82
  - lib
79
83
  required_ruby_version: !ruby/object:Gem::Requirement
80
84
  requirements:
81
- - - '>='
85
+ - - ">="
82
86
  - !ruby/object:Gem::Version
83
87
  version: '0'
84
88
  required_rubygems_version: !ruby/object:Gem::Requirement
85
89
  requirements:
86
- - - '>='
90
+ - - ">="
87
91
  - !ruby/object:Gem::Version
88
92
  version: '0'
89
93
  requirements: []
90
- rubyforge_project:
91
- rubygems_version: 2.0.14
92
- signing_key:
94
+ rubygems_version: 3.2.7
95
+ signing_key:
93
96
  specification_version: 4
94
- summary: Generative testing for RSpec
95
- test_files:
96
- - spec/generative/ordering_spec.rb
97
- - spec/generative/rake_task_spec.rb
98
- - spec/generative_spec.rb
99
- - spec/spec_helper.rb
100
- has_rdoc:
97
+ summary: Generative and property-based testing for RSpec
98
+ test_files: []
data/.travis.yml DELETED
@@ -1,11 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 1.9.3
4
- - 2.0.0
5
- - 2.1
6
- - ruby-head
7
- matrix:
8
- allow_failures:
9
- - rvm: ruby-head
10
- script:
11
- - rake ci