codders-dataset 1.3.2.1

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.

Potentially problematic release.


This version of codders-dataset might be problematic. Click here for more details.

Files changed (47) hide show
  1. data/CHANGELOG +67 -0
  2. data/LICENSE +19 -0
  3. data/README +111 -0
  4. data/Rakefile +31 -0
  5. data/TODO +15 -0
  6. data/VERSION.yml +4 -0
  7. data/lib/dataset.rb +130 -0
  8. data/lib/dataset/base.rb +157 -0
  9. data/lib/dataset/collection.rb +19 -0
  10. data/lib/dataset/database/base.rb +43 -0
  11. data/lib/dataset/database/mysql.rb +34 -0
  12. data/lib/dataset/database/postgresql.rb +34 -0
  13. data/lib/dataset/database/sqlite3.rb +32 -0
  14. data/lib/dataset/extensions/cucumber.rb +20 -0
  15. data/lib/dataset/extensions/rspec.rb +21 -0
  16. data/lib/dataset/extensions/test_unit.rb +60 -0
  17. data/lib/dataset/instance_methods.rb +10 -0
  18. data/lib/dataset/load.rb +47 -0
  19. data/lib/dataset/record/fixture.rb +73 -0
  20. data/lib/dataset/record/heirarchy.rb +65 -0
  21. data/lib/dataset/record/meta.rb +30 -0
  22. data/lib/dataset/record/model.rb +50 -0
  23. data/lib/dataset/resolver.rb +110 -0
  24. data/lib/dataset/session.rb +51 -0
  25. data/lib/dataset/session_binding.rb +319 -0
  26. data/lib/dataset/version.rb +9 -0
  27. data/plugit/descriptor.rb +25 -0
  28. data/spec/dataset/cucumber_spec.rb +54 -0
  29. data/spec/dataset/database/base_spec.rb +21 -0
  30. data/spec/dataset/record/heirarchy_spec.rb +14 -0
  31. data/spec/dataset/resolver_spec.rb +110 -0
  32. data/spec/dataset/rspec_spec.rb +133 -0
  33. data/spec/dataset/session_binding_spec.rb +203 -0
  34. data/spec/dataset/session_spec.rb +299 -0
  35. data/spec/dataset/test_unit_spec.rb +210 -0
  36. data/spec/fixtures/datasets/constant_not_defined.rb +0 -0
  37. data/spec/fixtures/datasets/ending_with_dataset.rb +2 -0
  38. data/spec/fixtures/datasets/exact_name.rb +2 -0
  39. data/spec/fixtures/datasets/not_a_dataset_base.rb +2 -0
  40. data/spec/fixtures/more_datasets/in_another_directory.rb +2 -0
  41. data/spec/models.rb +18 -0
  42. data/spec/schema.rb +26 -0
  43. data/spec/spec_helper.rb +47 -0
  44. data/spec/stubs/mini_rails.rb +18 -0
  45. data/spec/stubs/test_help.rb +1 -0
  46. data/tasks/dataset.rake +19 -0
  47. metadata +164 -0
@@ -0,0 +1,67 @@
1
+ *1.3.2.1 [Feature]
2
+
3
+ * Added support for mysql2 adapter
4
+
5
+ *1.3.2 [Bugfix]
6
+
7
+ * Fixed bug where sti finder names were not always generated correctly [aiwilliams]
8
+
9
+ *1.3.0 [Rails 2.3.2] (??)
10
+
11
+ * Supporting Rails 2.3.2 [mhawkins, underlog]
12
+ * Added tasks to load path so folks can require 'dataset.rake' [aiwilliams]
13
+ * Updated gemspec to include dependencies [aiwilliams]
14
+
15
+ *1.2.0 [Cucumber] (April 8, 2009)
16
+
17
+ * Support for cucumber [jgarber, seancribbs]
18
+
19
+ *1.1.0 [STI, belongs_to] (February 14, 2009)
20
+
21
+ * STI is better supported for inserting, naming and finding records [aiwilliams]
22
+
23
+ class Place < ActiveRecord::Base; end
24
+ class State < Place; end
25
+ class NorthCarolina < State; end
26
+
27
+ create_record(NorthCarolina, :state) # no need to define the 'type' column value
28
+ states(:state) == places(:state) == north_carolinas(:state) # read with the class names pluralized
29
+
30
+ * Moved to jeweler for much cleaner, github embracing gem building [aiwilliams]
31
+ * Support for simple belongs to associations [aiwilliams]
32
+
33
+ class Person < ActiveRecord::Base; end
34
+ class Note < ActiveRecord::Base
35
+ belongs_to :person
36
+ end
37
+
38
+ person_id = create_record Person, :myguy
39
+ create_record Note, :person => :myguy
40
+ Note.last.person_id == person_id
41
+
42
+ * Models inside modules are supported a little more conveniently [aiwilliams]
43
+
44
+ module MList
45
+ class Message < ActiveRecord::Base
46
+ end
47
+ end
48
+
49
+ # We'll get rid of the underscore in 'm_list_messages'
50
+ create_record MList::Message, :test
51
+ mlist_messages(:test)
52
+
53
+ * Helper method for converting strings to useful symbols for finding records [siannopollo]
54
+
55
+ This is useful if you write creator methods of your own.
56
+
57
+ def create_person(attributes)
58
+ create_record Person, name_to_sym(attributes[:name]), attributes
59
+ end
60
+
61
+ create_person(:name => 'Little John')
62
+ people(:little_john)
63
+
64
+
65
+ *1.0.0 [Scenarios Replacement] (December 15, 2008)
66
+
67
+ * Drop-in replacement for Scenarios plugin of old [aiwilliams]
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2008-2009, Adam Williams
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README ADDED
@@ -0,0 +1,111 @@
1
+ = Dataset
2
+
3
+ Dataset provides a simple API for creating and finding sets of data in your database. Check out Dataset::RecordMethods and Dataset::ModelFinders.
4
+
5
+ Dataset loads data intelligently if you use 'nested contexts' in your tests (RSpec, anything that uses Test::Unit::TestCase subclassing for creating nested contexts):
6
+
7
+ describe Something do
8
+ dataset :a => Dataset :a is loaded (at the right time)
9
+
10
+ it 'should whatever'
11
+ end
12
+
13
+ describe More do
14
+ dataset :b => Dataset :b is loaded. :a data is still there
15
+
16
+ it 'should'
17
+ end
18
+ end
19
+
20
+ describe Another do => Database is restored to :a, without re-running :a logic
21
+ it 'should'
22
+ end
23
+ end
24
+ end
25
+
26
+ The goal is to see a marked improvement in overall test run speed, basing this on the assumption that it is faster to have the OS copy a file or mySQL dump and load. Of course, we may find this to be a false assumption, but there were plenty of bugs in the former 'Scenarios' - addressing that afforded the opportunity to test the assumption.
27
+
28
+
29
+ Dataset does not prevent you from using other libraries like Machinist or factory_girl. If you were to used either of those, you could have a dataset like this:
30
+
31
+ require 'faker'
32
+
33
+ class OrganizationsDataset < Dataset::Base
34
+ Sham.name { Faker::Name.name }
35
+
36
+ Organization.blueprint do
37
+ name { Sham.name }
38
+ end
39
+
40
+ def load
41
+ name_model Organization.make, :org_one
42
+ end
43
+ end
44
+
45
+ The benefit is that you can reuse interesting sets of data, without sacrificing the utility of those other libraries.
46
+
47
+ describe Organization, 'stuff' do
48
+ dataset :organizations
49
+ end
50
+
51
+ describe Organization, 'other stuff' do
52
+ dataset :organizations
53
+ end
54
+
55
+
56
+ Get things installed, then read more in the Dataset documentation at http://aiwilliams.github.com/dataset
57
+
58
+
59
+ == Installation
60
+
61
+ Install the plugin:
62
+
63
+ ./script/plugin install git://github.com/aiwilliams/dataset.git
64
+
65
+ In your test_helper.rb/spec_helper.rb:
66
+
67
+ require 'dataset'
68
+ class Test::Unit::TestCase
69
+ include Dataset
70
+ datasets_directory "#{RAILS_ROOT}/spec/datasets"
71
+ end
72
+
73
+ If you don't use rspec_on_rails, or you have specs that aren't of the RailsExampleGroup type, you should do this in spec_helper.rb:
74
+
75
+ require 'dataset'
76
+ class Spec::Example::ExampleGroup
77
+ include Dataset
78
+ datasets_directory "#{RAILS_ROOT}/spec/datasets"
79
+ end
80
+
81
+ If you were a user of the Scenarios plugin, and want to do as little as possible to get going (assumes you are using rspec_on_rails):
82
+
83
+ require 'dataset'
84
+ Scenario = Scenarios = Dataset
85
+ class Test::Unit::TestCase
86
+ include Dataset
87
+ class << self
88
+ alias_method :scenario, :dataset
89
+ end
90
+ end
91
+ class ScenariosResolver < Dataset::DirectoryResolver
92
+ def suffix
93
+ @suffix ||= 'Scenario'
94
+ end
95
+ end
96
+ Dataset::Resolver.default = ScenariosResolver.new("#{RAILS_ROOT}/spec/scenarios")
97
+
98
+
99
+ == Credits
100
+
101
+ Written by [Adam Williams](http://github.com/aiwilliams).
102
+
103
+ Contributors:
104
+
105
+ - [Saturn Flyer](http://www.saturnflyer.com) [github](http://github.com/saturnflyer)
106
+ - [Steve Iannopollo](http://github.com/siannopollo)
107
+ - [John Long](http://github.com/jlong)
108
+
109
+ ---
110
+
111
+ Dataset is released under the MIT-License and is Copyright (c)2008 Adam Williams.
@@ -0,0 +1,31 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+
3
+ require File.join(File.dirname(__FILE__), 'plugit/descriptor')
4
+ require 'rubygems'
5
+ require 'spec/rake/spectask'
6
+
7
+ task :default => :spec
8
+
9
+ desc "Run all specs"
10
+ Spec::Rake::SpecTask.new do |t|
11
+ t.spec_files = FileList['spec/**/*_spec.rb']
12
+ t.spec_opts = ['--options', 'spec/spec.opts']
13
+ end
14
+
15
+ begin
16
+ require 'jeweler'
17
+ Jeweler::Tasks.new do |s|
18
+ s.name = 'dataset'
19
+ s.summary = 'A simple API for creating and finding sets of data in your database, built on ActiveRecord.'
20
+ s.email = 'adam@thewilliams.ws'
21
+ s.files = FileList["[A-Z]*", "{lib,tasks}/**/*", "plugit/descriptor.rb"].exclude("tmp")
22
+ s.require_paths = ["lib", "tasks"]
23
+ s.add_dependency('activesupport', '>= 2.3.0')
24
+ s.add_dependency('activerecord', '>= 2.3.0')
25
+ s.homepage = "http://github.com/aiwilliams/dataset"
26
+ s.description = s.summary
27
+ s.authors = ['Adam Williams']
28
+ end
29
+ rescue LoadError
30
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
31
+ end
data/TODO ADDED
@@ -0,0 +1,15 @@
1
+ take any instance variables already in context and make them available to dataset blocks - this is for nested describes
2
+ I'm not sure about this one. It can be very frustrating to lose context of when the state of an iv is modified.
3
+
4
+ add ability to clear the database (some tests wanted to guarantee a clear db)
5
+ This is acheived with "dataset {}"
6
+
7
+ clear database completely at beginning of session, only tables where data was created within a session??
8
+
9
+ clear all dumps on new run of tests
10
+ be sure we are capturing a dataset if it has already be captured before during a run
11
+ describe what happens when someone has a fixtures file - they get loaded after our datasets, thereby causing all the data in the table of the fixture file (like things.yml) to be deleted - the fixtures are then loaded
12
+ look into truncating database instead individual table deletes
13
+ allow configuration of dataset
14
+ * permatable / global scope
15
+ re-evaluation location of some tests that depend on TestCase in non-test/unit tests
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 2
3
+ :major: 1
4
+ :minor: 3
@@ -0,0 +1,130 @@
1
+ require 'activesupport'
2
+ require 'activerecord'
3
+
4
+ require 'dataset/version'
5
+ require 'dataset/instance_methods'
6
+ require 'dataset/base'
7
+ require 'dataset/database/base'
8
+ require 'dataset/database/mysql'
9
+ require 'dataset/database/mysql2'
10
+ require 'dataset/database/sqlite3'
11
+ require 'dataset/database/postgresql'
12
+ require 'dataset/collection'
13
+ require 'dataset/load'
14
+ require 'dataset/resolver'
15
+ require 'dataset/session'
16
+ require 'dataset/session_binding'
17
+ require 'dataset/record/heirarchy'
18
+ require 'dataset/record/meta'
19
+ require 'dataset/record/fixture'
20
+ require 'dataset/record/model'
21
+
22
+ # == Quick Start
23
+ #
24
+ # Write a test. If you want some data in your database, create a dataset.
25
+ # Start simple.
26
+ #
27
+ # describe States do
28
+ # dataset do
29
+ # [%w(Colorado CO), %w(North\ Carolina NC), %w(South\ Carolina SC)].each do |name,abbrev|
30
+ # create_record :state, abbrev.downcase, :name => name, :abbrev => abbrev
31
+ # end
32
+ # end
33
+ #
34
+ # it 'should have an abbreviated name'
35
+ # states(:nc).abbrev.should be('NC')
36
+ # end
37
+ #
38
+ # it 'should have a name'
39
+ # states(:nc).name.should be('North Carolin')
40
+ # end
41
+ # end
42
+ #
43
+ # Notice that you won't be using _find_id_ or _find_model_ in your tests. You
44
+ # use methods like _states_ and _state_id_, as in the example above.
45
+ #
46
+ # When you find that you're seeing patterns in the data you are creating, pull it into a class.
47
+ #
48
+ # spec/datasets/states.rb
49
+ # class StatesDataset < Dataset::Base
50
+ # def load
51
+ # # create useful data
52
+ # end
53
+ # end
54
+ #
55
+ # spec/models/state.rb
56
+ # describe State do
57
+ # dataset :states
58
+ # end
59
+ #
60
+ # == Installation
61
+ #
62
+ # Dataset is installed into your testing environment by requiring the library,
63
+ # then including it into the class that will be the context of your test
64
+ # methods.
65
+ #
66
+ # require 'dataset'
67
+ # class Test::Unit::TestCase
68
+ # include Dataset
69
+ # datasets_directory "#{RAILS_ROOT}/test/datasets"
70
+ # end
71
+ #
72
+ # Note that should you desire your Dataset::Base subclasses be
73
+ # auto-discovered, you can set the _datasets_directory_.
74
+ #
75
+ module Dataset
76
+ def self.included(test_context) # :nodoc:
77
+ if test_context.name =~ /World\Z/
78
+ require 'dataset/extensions/cucumber'
79
+ elsif test_context.name =~ /TestCase\Z/
80
+ require 'dataset/extensions/test_unit'
81
+ elsif test_context.name =~ /ExampleGroup\Z/
82
+ require 'dataset/extensions/rspec'
83
+ else
84
+ raise "I don't understand your test framework"
85
+ end
86
+
87
+ test_context.extend ContextClassMethods
88
+ end
89
+
90
+ # Methods that are added to the class that Dataset is included in (the test
91
+ # context class).
92
+ #
93
+ module ContextClassMethods
94
+ def self.extended(context_class) # :nodoc:
95
+ context_class.module_eval do
96
+ include InstanceMethods
97
+ superclass_delegating_accessor :dataset_session
98
+ end
99
+ end
100
+
101
+ mattr_accessor :datasets_database_dump_path
102
+ self.datasets_database_dump_path = File.expand_path(RAILS_ROOT + '/tmp/dataset') if defined?(RAILS_ROOT)
103
+
104
+ # Replaces the default Dataset::Resolver with one that will look for
105
+ # dataset class definitions in the specified directory. Captures of the
106
+ # database will be stored in a subdirectory 'tmp' (see
107
+ # Dataset::Database::Base).
108
+ def datasets_directory(path)
109
+ Dataset::Resolver.default = Dataset::DirectoryResolver.new(path)
110
+ Dataset::ContextClassMethods.datasets_database_dump_path = File.join(path, '/tmp/dataset')
111
+ end
112
+
113
+ def add_dataset(*datasets, &block) # :nodoc:
114
+ dataset_session = dataset_session_in_hierarchy
115
+ datasets.each { |dataset| dataset_session.add_dataset(self, dataset) }
116
+ dataset_session.add_dataset(self, Class.new(Dataset::Block) {
117
+ define_method :doload, block
118
+ }) unless block.nil?
119
+ end
120
+
121
+ def dataset_session_in_hierarchy # :nodoc:
122
+ self.dataset_session ||= begin
123
+ database_spec = ActiveRecord::Base.configurations['test'].with_indifferent_access
124
+ database_class = Dataset::Database.const_get(database_spec[:adapter].classify)
125
+ database = database_class.new(database_spec, Dataset::ContextClassMethods.datasets_database_dump_path)
126
+ Dataset::Session.new(database)
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,157 @@
1
+ module Dataset
2
+
3
+ # The superclass of your Dataset classes.
4
+ #
5
+ # It is recommended that you create a dataset using the Dataset::Block
6
+ # method first, then grow into using classes as you recognize patterns in
7
+ # your test data creation. This will help you to keep simple things simple.
8
+ #
9
+ class Base
10
+ class << self
11
+ # Allows a subclass to define helper methods that should be made
12
+ # available to instances of this dataset, to datasets that use this
13
+ # dataset, and to tests that use this dataset.
14
+ #
15
+ # This feature is great for providing any kind of method that would help
16
+ # test the code around the data your dataset creates. Be careful,
17
+ # though, to keep from adding business logic to these methods! That
18
+ # belongs in your production code.
19
+ #
20
+ def helpers(&method_definitions)
21
+ @helper_methods ||= begin
22
+ mod = Module.new
23
+ include mod
24
+ mod
25
+ end
26
+ @helper_methods.module_eval &method_definitions
27
+ end
28
+
29
+ def helper_methods # :nodoc:
30
+ @helper_methods
31
+ end
32
+
33
+ # Allows a subsclass to declare which datasets it uses.
34
+ #
35
+ # Dataset is designed to promote 'design by composition', rather than
36
+ # 'design by inheritance'. You should not use class hiearchies to share
37
+ # data and code in your datasets. Instead, you can write something like
38
+ # this:
39
+ #
40
+ # class PeopleDataset < Dataset::Base; end
41
+ # class DepartmentsDataset < Dataset::Base; end
42
+ # class OrganizationsDataset < Dataset::Base
43
+ # uses :people, :departments
44
+ # end
45
+ #
46
+ # When the OrganizationsDataset is loaded, it will have all the data
47
+ # from the datasets is uses, as well as all of the helper methods
48
+ # defined by those datasets.
49
+ #
50
+ # When a dataset uses other datasets, and those datasets themselves use
51
+ # datasets, things will be loaded in the order of dependency you would
52
+ # expect:
53
+ #
54
+ # C uses B
55
+ # A uses C
56
+ # B, C, A is the load order
57
+ #
58
+ def uses(*datasets)
59
+ @used_datasets = datasets
60
+ end
61
+
62
+ def used_datasets # :nodoc:
63
+ @used_datasets
64
+ end
65
+ end
66
+
67
+ # Invoked once before a collection of tests is run. If you use a dataset
68
+ # in multiple test classes, it will be called once for each of them -
69
+ # remember that the database will be cleared at the beginning of running a
70
+ # 'suite' or 'group' of tests, unless you are using nested contexts (as in
71
+ # nested describe blocks in RSpec).
72
+ #
73
+ # Override this method in your subclasses.
74
+ #
75
+ def load; end
76
+ end
77
+
78
+ # The easiest way to create some data before a suite of tests is run is by
79
+ # using a Dataset::Block. An example works wonders:
80
+ #
81
+ # class PeopleTest < Test::Unit::TestCase
82
+ # dataset do
83
+ # create_record :person, :billy, :name => 'Billy'
84
+ # end
85
+ #
86
+ # def test_name
87
+ # assert_equal 'Billy', people(:billy).name
88
+ # end
89
+ # end
90
+ #
91
+ # The database will be cleared and billy will be inserted once before
92
+ # running each of the tests within a transaction. All the normal transaction
93
+ # fixtures stuff will still work.
94
+ #
95
+ # One of the great features of Dataset, at least when things get really
96
+ # interesting in your data needs, is that nested contexts will be additive.
97
+ # Consider this:
98
+ #
99
+ # describe Something do
100
+ # dataset :a => Dataset :a is loaded (at the right time)
101
+ #
102
+ # it 'should whatever'
103
+ # end
104
+ #
105
+ # describe More do
106
+ # dataset :b => Dataset :b is loaded. :a data is still there
107
+ #
108
+ # it 'should'
109
+ # end
110
+ # end
111
+ #
112
+ # describe Another do => Database is restored to :a, without re-running :a logic
113
+ # it 'should'
114
+ # end
115
+ # end
116
+ # end
117
+ #
118
+ # == Instance Variables
119
+ #
120
+ # You may also assign instance variables in a dataset block, and they will
121
+ # be available to your test methods. You have to be careful with this in a
122
+ # similar way that you must with an RSpec before :all block. Since the
123
+ # instance variables are pointing to the same instances accross all tests,
124
+ # things can get weird if you intend to change their state. It's best use is
125
+ # for loading objects that you want to read a lot without loading over and
126
+ # over again for each test.
127
+ #
128
+ # == Building on Other Datasets
129
+ #
130
+ # You may pass any number of Dataset::Base subclasses - or better yet, their
131
+ # names - to the dataset method. When you use a block, this adds a lot of
132
+ # clarity:
133
+ #
134
+ # class PersonTest < Test::Unit::TestCase
135
+ # dataset :organization, :people do
136
+ # id = create_record :person, :second_admin, :name => 'Admin Three'
137
+ # create_record :organization_administratorship, :organization_id => organization_id(:first_bank), :person_id => id
138
+ # end
139
+ #
140
+ # def test_admins
141
+ # assert organizations(:first_bank).admins.include?(people(:second_admin))
142
+ # end
143
+ # end
144
+ #
145
+ # == Reusing a Dataset
146
+ #
147
+ # When you need to go beyond the block, create a Dataset::Base subclass!
148
+ class Block < Base
149
+ include Dataset::InstanceMethods
150
+
151
+ def load # :nodoc:
152
+ dataset_session_binding.install_block_variables(self)
153
+ doload
154
+ dataset_session_binding.copy_block_variables(self)
155
+ end
156
+ end
157
+ end