joinfix 0.1.1 → 1.0.0
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/README +157 -85
- data/Rakefile +38 -0
- data/TEST_README +45 -44
- data/lib/joinfix/error.rb +220 -0
- data/lib/joinfix/fixture.rb +3 -4
- data/lib/joinfix/fixtures.rb +107 -145
- data/lib/joinfix/fixtures_class.rb +51 -97
- data/lib/joinfix.rb +118 -84
- data/rails/app/models/group.rb +3 -3
- data/rails/db/migrate/004_create_users.rb +1 -1
- data/rails/db/schema.rb +1 -1
- data/rails/log/development.log +409 -57
- data/rails/log/test.log +350 -23
- data/rails/test/fixtures/groups.yml +2 -1
- data/rails/test/fixtures/users.yml +27 -19
- data/rails/test/unit/user_test.rb +25 -4
- data/test/has_many_test.rb +16 -0
- data/test/joinfix_test.rb +6 -69
- data/test/joinfix_test_suite.rb +1 -1
- metadata +9 -5
- data/test/todo +0 -15
data/README
CHANGED
@@ -1,86 +1,158 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
#
|
4
|
-
# == Info
|
5
|
-
#
|
6
|
-
# Copyright (c) 2006-2007, Regents of the University of Colorado.
|
7
|
-
# Developer:: Simon Chiang, Biomolecular Structure Program
|
8
|
-
# Support:: UCHSC School of Medicine Deans Academic Enrichment Fund
|
9
|
-
# Licence:: MIT-Style
|
10
|
-
#
|
11
|
-
# == Usage
|
12
|
-
# Consider the following data model:
|
13
|
-
#
|
14
|
-
# class User < ActiveRecord::Base
|
15
|
-
# has_many :user_groups,
|
16
|
-
# has_many :groups, :through => :user_groups
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# class Group < ActiveRecord::Base
|
20
|
-
# has_many :group_users, :class_name => 'UserGroup'
|
21
|
-
# has_many :users, :through => :group_users
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# class UserGroup < ActiveRecord::Base
|
25
|
-
# belongs_to :user
|
26
|
-
# belongs_to :group
|
27
|
-
# end
|
28
|
-
#
|
29
|
-
# Write your fixtures using the naming scheme you lay out in your models.
|
30
|
-
# Entries can be spread across multiple fixture files, or not. Joins between
|
31
|
-
# entries are written inline, either by referening the name of another entry
|
32
|
-
# or by defining the joined entry:
|
33
|
-
#
|
34
|
-
# [users.yml]
|
35
|
-
# bob:
|
36
|
-
# login: bob
|
37
|
-
# groups: admin_group # => reference to the 'admin_group' entry
|
38
|
-
#
|
39
|
-
# jane:
|
40
|
-
# id: 3 # => you can specify ids if you want
|
41
|
-
# login: jane
|
42
|
-
# groups: # => an array of joins
|
43
|
-
# - admin_group
|
44
|
-
# - workers:
|
45
|
-
# name: worker bees
|
46
|
-
#
|
47
|
-
# samantha:
|
48
|
-
# login: sam
|
49
|
-
# groups: # => inline definition of joined entries
|
50
|
-
# movers:
|
51
|
-
# name: movers
|
52
|
-
# shakers:
|
53
|
-
# name: shakers
|
54
|
-
#
|
55
|
-
# [groups.yml]
|
56
|
-
# admin_group: # => references can span files
|
57
|
-
# name: administrators
|
58
|
-
#
|
59
|
-
# Join entries implied in your definition, as in a has_and_belongs_to_many association, will
|
60
|
-
# be created and named by joining together the names of the parent and child, ordered
|
61
|
-
# by the '<' operator. For example, the users.yml and groups.yml fixtures will also produce:
|
62
|
-
#
|
63
|
-
# admin_group_bob # => join for bob and admin_group
|
64
|
-
# jane_workers # => join for jane and workers
|
65
|
-
# ...
|
66
|
-
#
|
67
|
-
# In your tests, require joinfix and use the fixtures exactly as you would normally.
|
68
|
-
# One gotcha (which really isn't a gotcha) -- you must be sure to name all the tables
|
69
|
-
# for which your fixtures create entries. In fact this is no different than normal,
|
70
|
-
# but it's easy to forget if you lump joins into one file.
|
71
|
-
#
|
72
|
-
# require 'joinfix'
|
73
|
-
#
|
74
|
-
# class UserTest < Test::Unit::TestCase
|
75
|
-
# fixtures :users, :groups, :user_groups # => got to name them all!
|
76
|
-
#
|
77
|
-
# def test_joinfix
|
78
|
-
# assert_equal "administrators", users(:bob).groups.first.name
|
79
|
-
# assert_equal 2, User.find_by_login("jane").groups.count
|
80
|
-
# assert_equal 3, UserGroup.find(user_groups(:jane_workers).id).user.id
|
81
|
-
# assert_equal users(:samantha), User.find_by_login("sam").groups.find_by_name("movers").users.first
|
82
|
-
# end
|
83
|
-
# end
|
84
|
-
#
|
85
|
-
#
|
1
|
+
= JoinFix
|
2
|
+
A reflection-based solution to the fixture join problem.
|
86
3
|
|
4
|
+
== Description
|
5
|
+
Making fixtures for models with complex joins can be a redundant, error-prone process. JoinFix
|
6
|
+
provides a solution to this problem by letting you reference and/or define child entries inline with
|
7
|
+
their parents.
|
8
|
+
|
9
|
+
[users.yml]
|
10
|
+
john_doe:
|
11
|
+
full_name: John Doe
|
12
|
+
groups:
|
13
|
+
- admin_group # => entry reference
|
14
|
+
- devel_group: # => inline definition
|
15
|
+
name: Developers
|
16
|
+
|
17
|
+
[groups.yml]
|
18
|
+
admin_group: # => referenced entry
|
19
|
+
name: Administrators
|
20
|
+
|
21
|
+
JoinFix uses reflection on ActiveRecord associations to determine how to perform joins so
|
22
|
+
no configuration is required. Simply require joinfix and begin writing entries.
|
23
|
+
|
24
|
+
== Info
|
25
|
+
|
26
|
+
Available at {rubyforge.org/projects/joinfix}[http://rubyforge.org/projects/joinfix]
|
27
|
+
|
28
|
+
Copyright (c) 2006-2007, Regents of the University of Colorado.
|
29
|
+
Developer:: Simon Chiang, Biomolecular Structure Program
|
30
|
+
Support:: UCHSC School of Medicine Deans Academic Enrichment Fund
|
31
|
+
Licence:: MIT-Style
|
32
|
+
|
33
|
+
== Usage
|
34
|
+
Consider the following data model:
|
35
|
+
|
36
|
+
class User < ActiveRecord::Base
|
37
|
+
has_many :user_groups
|
38
|
+
has_many :groups, :through => :user_groups
|
39
|
+
end
|
40
|
+
|
41
|
+
class Group < ActiveRecord::Base
|
42
|
+
has_many :user_groups
|
43
|
+
has_many :users, :through => :user_groups
|
44
|
+
end
|
45
|
+
|
46
|
+
class UserGroup < ActiveRecord::Base
|
47
|
+
belongs_to :user
|
48
|
+
belongs_to :group
|
49
|
+
end
|
50
|
+
|
51
|
+
Write your fixtures using the naming scheme you lay out in your models.
|
52
|
+
Entries can be referenced across multiple fixture files or defined inline:
|
53
|
+
|
54
|
+
[users.yml]
|
55
|
+
john_doe:
|
56
|
+
full_name: John Doe
|
57
|
+
groups: admin_group # => reference to the 'admin_group' entry
|
58
|
+
|
59
|
+
jane_doe:
|
60
|
+
full_name: Jane Doe
|
61
|
+
groups: # => you can specify an array of entries if needed
|
62
|
+
- admin_group
|
63
|
+
- worker_group: # => inline definition of the 'worker_group' entry
|
64
|
+
name: Workers
|
65
|
+
|
66
|
+
[groups.yml]
|
67
|
+
admin_group: # => the referenced 'admin_group' entry
|
68
|
+
id: 3 # => you can (but don't have to) specify ids
|
69
|
+
name: Administrators
|
70
|
+
|
71
|
+
Join entries implied in your definition, as in a has_and_belongs_to_many association,
|
72
|
+
will be created and named by joining together the names of the parent and child,
|
73
|
+
ordered by the '<' operator. For example, the users.yml and groups.yml fixtures
|
74
|
+
produce these entries:
|
75
|
+
|
76
|
+
[users]
|
77
|
+
john_doe:
|
78
|
+
id: 1 # => primary keys are assigned to all entries (see note)
|
79
|
+
full_name: John Doe
|
80
|
+
jane_doe:
|
81
|
+
id: 2
|
82
|
+
full_name: Jane Doe
|
83
|
+
|
84
|
+
[groups]
|
85
|
+
admin_group:
|
86
|
+
id: 3
|
87
|
+
name: Administrators
|
88
|
+
worker_group:
|
89
|
+
id: 1
|
90
|
+
name: Workers
|
91
|
+
|
92
|
+
[user_groups]
|
93
|
+
admin_group_john_doe
|
94
|
+
id: 1
|
95
|
+
user_id: 1 # => references are resolved to their foreign keys
|
96
|
+
group_id: 3 # => explicitly set primary keys are respected
|
97
|
+
admin_group_jane_doe
|
98
|
+
id: 2
|
99
|
+
user_id: 2
|
100
|
+
group_id: 3
|
101
|
+
jane_doe_worker_group # => Notice the '<' operator in action
|
102
|
+
id: 3
|
103
|
+
user_id: 2
|
104
|
+
group_id: 1
|
105
|
+
|
106
|
+
Note: Primary keys are assigned to entries based on the way the entry names are hashed, ie 'john_doe' will not necessarily have id '1'. If you need a specific id for an entry, then you must explicitly set it.
|
107
|
+
|
108
|
+
If you need to add additional fields to an implied entry, simply define them in their
|
109
|
+
fixture file. All fields across all fixtures will be merged into one entry (JoinFix raises
|
110
|
+
an error in the event of a collision).
|
111
|
+
|
112
|
+
[user_groups.yml]
|
113
|
+
admin_group_john_doe:
|
114
|
+
date_added: 2007-06-12
|
115
|
+
|
116
|
+
Nesting is allowed. This will make the same entries as above:
|
117
|
+
|
118
|
+
[users.yml]
|
119
|
+
john_doe:
|
120
|
+
full_name: John Doe
|
121
|
+
groups:
|
122
|
+
admin_group:
|
123
|
+
id: 3
|
124
|
+
name: Administrators
|
125
|
+
users:
|
126
|
+
jane_doe:
|
127
|
+
full_name: Jane Doe
|
128
|
+
groups:
|
129
|
+
worker_group:
|
130
|
+
name: Workers
|
131
|
+
|
132
|
+
In your tests, require joinfix and use the fixtures exactly as you would normally.
|
133
|
+
One gotcha -- you must be sure to name all the tables for which your fixtures create entries.
|
134
|
+
In fact this is no different than normal, but it's easy to forget if you lump joins into one file.
|
135
|
+
|
136
|
+
require 'joinfix'
|
137
|
+
|
138
|
+
class UserTest < Test::Unit::TestCase
|
139
|
+
fixtures :users, :groups, :user_groups # => got to name them all!!!
|
140
|
+
|
141
|
+
def test_joinfix
|
142
|
+
assert_equal "Administrators", users(:john_doe).groups.first.name
|
143
|
+
assert_equal 2, User.find_by_full_name("jane_doe").groups.count
|
144
|
+
assert_equal 3, UserGroup.find(user_groups(:admin_group_jane_doe).id).group.id
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
=== Command line options
|
149
|
+
|
150
|
+
JoinFix provides some command line options through the ENV variables. Setting these
|
151
|
+
variables is easy if you're using rake[http://rake.rubyforge.org/] to run your test suite:
|
152
|
+
|
153
|
+
% rake test key=value # => sets ENV['key'] = 'value'
|
154
|
+
|
155
|
+
Available options:
|
156
|
+
|
157
|
+
format_joinfix_errors:: Unless 'false', this option causes JoinFix to simplify the console output when a JoinFixError occurs.
|
158
|
+
joinfix_dump:: Prints all entries for tables matching joinfix_dump to STDOUT upon make_join_fixtures. Prints entries for all tables if 'true'.
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
# tasks
|
7
|
+
desc 'Default: Run tests.'
|
8
|
+
task :default => :test
|
9
|
+
|
10
|
+
desc 'Run tests.'
|
11
|
+
Rake::TestTask.new(:test) do |t|
|
12
|
+
t.libs << 'lib'
|
13
|
+
t.pattern = File.join('test', ENV['subset'] || '', ENV['pattern'] || '**/*_test.rb')
|
14
|
+
t.verbose = true
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Generate documentation.'
|
18
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
19
|
+
rdoc.rdoc_dir = 'rdoc'
|
20
|
+
rdoc.title = 'JoinFixtures'
|
21
|
+
rdoc.main = 'README'
|
22
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
23
|
+
rdoc.rdoc_files.include('README', 'MIT-LICENSE', 'TEST_README')
|
24
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Gem specification
|
29
|
+
#
|
30
|
+
if File.exists?("./gemspecs/1.0.0.gemspec")
|
31
|
+
|
32
|
+
Gem::manage_gems
|
33
|
+
spec = Gem::SourceIndex.load_specification("./gemspecs/1.0.0.gemspec")
|
34
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
35
|
+
pkg.need_tar = true
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/TEST_README
CHANGED
@@ -1,44 +1,45 @@
|
|
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
|
-
|
1
|
+
= JoinFix Tests
|
2
|
+
JoinFix does not have an active test suite that can be run when installed via RubyGems,
|
3
|
+
because, as you may expect, running the tests for joinfix requires that ActiveRecord can
|
4
|
+
connect to a test database. Additionally, the tests depend on the 'gemdev' gem.
|
5
|
+
|
6
|
+
If you want to run the tests, you need to do the following:
|
7
|
+
* install gemdev ('gem install gemdev')
|
8
|
+
* create the database and grant permissions to a test user
|
9
|
+
* modify config.yml to reflect the database and test user
|
10
|
+
|
11
|
+
These commands will create the database and grand permissions as needed, assuming
|
12
|
+
you're using mysql on localhost. Log into 'mysql', then enter:
|
13
|
+
|
14
|
+
create database joinfix;
|
15
|
+
grant all on joinfix.* to 'ruby'@'localhost' identified by 'rubypass'
|
16
|
+
|
17
|
+
Now you can run the test from the command line using:
|
18
|
+
|
19
|
+
% rake test
|
20
|
+
|
21
|
+
= Rails Tests
|
22
|
+
JoinFix is intended to integrate with Ruby on Rails. I've set up a rails project for
|
23
|
+
testing, complete with models, migrations, fixtures, and the appropriate tests.
|
24
|
+
|
25
|
+
The rails tests require a '_development' and '_test' database to connect to.
|
26
|
+
|
27
|
+
To setup the databases:
|
28
|
+
* create the databases and grant permissions to a test user
|
29
|
+
* modify rails/config/database.yml to reflect the databases and test user
|
30
|
+
* migrate the table schema into the development database
|
31
|
+
|
32
|
+
These commands will create the database and grand permissions as needed, assuming
|
33
|
+
you're using mysql on localhost. Log into 'mysql', then enter:
|
34
|
+
|
35
|
+
create database joinfix_development;
|
36
|
+
grant all on joinfix_development.* to 'ruby'@'localhost' identified by 'rubypass';
|
37
|
+
|
38
|
+
create database joinfix_test;
|
39
|
+
grant all on joinfix_test.* to 'ruby'@'localhost' identified by 'rubypass';
|
40
|
+
|
41
|
+
Subsequently you need to migrate the database specification into these tables
|
42
|
+
and run the tests. From the command line, in the rails directory:
|
43
|
+
|
44
|
+
% rake db:migrate
|
45
|
+
% rake test
|
@@ -0,0 +1,220 @@
|
|
1
|
+
# JoinFix provides help for debugging errors in your fixtures through subclasses of JoinFixError.
|
2
|
+
class JoinFixError < RuntimeError
|
3
|
+
class << self
|
4
|
+
def new(*args)
|
5
|
+
@already_created ||= {}
|
6
|
+
|
7
|
+
error = super(*args)
|
8
|
+
key = error.fixtures.respond_to?(:fixture_path) ? error.fixtures.fixture_path : error.fixtures
|
9
|
+
@already_created[key] ||= error
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :fixtures, :entry_name, :msg
|
14
|
+
attr_accessor :advice
|
15
|
+
|
16
|
+
def initialize(fixtures, entry_name, msg=nil)
|
17
|
+
@fixtures = fixtures
|
18
|
+
@entry_name = entry_name
|
19
|
+
@msg = msg
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class MissingFixtureError < JoinFixError # :nodoc:
|
24
|
+
attr_reader :table_name
|
25
|
+
def initialize(table_name)
|
26
|
+
@fixtures = table_name
|
27
|
+
@table_name = table_name
|
28
|
+
end
|
29
|
+
|
30
|
+
def message
|
31
|
+
"No fixture loaded for <#{table_name}>\n" +
|
32
|
+
(advice.nil? ? '' : "#{advice}\n")
|
33
|
+
end
|
34
|
+
|
35
|
+
def advice
|
36
|
+
%Q{
|
37
|
+
Be sure you've specified all the tables for which your fixtures create entries.
|
38
|
+
---
|
39
|
+
class UserTest < Test::Unit::TestCase
|
40
|
+
fixtures :users, :groups, :user_groups # => got to name them all!!!
|
41
|
+
end}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class MakeEntryError < JoinFixError # :nodoc:
|
46
|
+
attr_reader :entry
|
47
|
+
attr_accessor :advice
|
48
|
+
|
49
|
+
def initialize(fixtures, entry_name, entry, msg=nil)
|
50
|
+
super(fixtures, entry_name, msg)
|
51
|
+
@entry = entry
|
52
|
+
end
|
53
|
+
|
54
|
+
def message
|
55
|
+
"Error making <#{fixtures.klass.table_name}(:#{entry_name})> in <#{fixtures.fixture_path}>.\n" +
|
56
|
+
{entry_name => entry}.to_yaml +
|
57
|
+
(msg.nil? ? '' : "\n#{msg}\n") +
|
58
|
+
(advice.nil? ? '' : "#{advice}\n")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class EntryCollisionError < MakeEntryError # :nodoc:
|
63
|
+
end
|
64
|
+
|
65
|
+
class NoEntryNameError < MakeEntryError # :nodoc:
|
66
|
+
def advice
|
67
|
+
%Q{
|
68
|
+
This error occurs when an entry is not named as in:
|
69
|
+
---
|
70
|
+
john_doe:
|
71
|
+
full_name: John Doe
|
72
|
+
groups:
|
73
|
+
# an entry name like 'admin_group' is missing here
|
74
|
+
name: Administrators
|
75
|
+
...
|
76
|
+
|
77
|
+
Or sometimes if you have an error in your YAML:
|
78
|
+
---
|
79
|
+
john_doe:
|
80
|
+
full_name: John Doe
|
81
|
+
groups:
|
82
|
+
- admin_group:
|
83
|
+
name: Administrators
|
84
|
+
- worker_group:
|
85
|
+
name: Workers # this field is not properly indented
|
86
|
+
...}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class MultipleChildrenError < MakeEntryError # :nodoc:
|
91
|
+
def advice
|
92
|
+
%Q{
|
93
|
+
Single entry joins should specify a single entry, not an array of entries.
|
94
|
+
Use a different association if you need multiple joined entries.}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class MissingPolymorphicTypeError < MakeEntryError # :nodoc:
|
99
|
+
def advice
|
100
|
+
%Q{
|
101
|
+
When specifying a belongs_to :polymorphic join, the type
|
102
|
+
of the joined entry must be specified because it cannot be
|
103
|
+
inferred from association itself. Use something like:
|
104
|
+
--
|
105
|
+
book_I_read:
|
106
|
+
opinion: Great!
|
107
|
+
readable_type: Book
|
108
|
+
readable:
|
109
|
+
the_jungle_books:
|
110
|
+
author: Rudyard Kipling
|
111
|
+
title: The Jungle Books
|
112
|
+
|
113
|
+
poem_I_read:
|
114
|
+
opinion: Essential!
|
115
|
+
readable_type: Poem
|
116
|
+
readable:
|
117
|
+
sea_fever:
|
118
|
+
poet: John Masefield
|
119
|
+
title: Sea-Fever}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class ResolveJoinReferenceError < JoinFixError # :nodoc:
|
124
|
+
attr_reader :join_table_name, :join_name
|
125
|
+
|
126
|
+
def initialize(fixtures, entry_name, join_table_name, join_name, msg=nil)
|
127
|
+
super(fixtures, entry_name, msg)
|
128
|
+
@join_table_name = join_table_name
|
129
|
+
@join_name = join_name
|
130
|
+
end
|
131
|
+
|
132
|
+
def message
|
133
|
+
"Cannot resolve reference to <#{join_table_name}(:#{join_name})> " +
|
134
|
+
"for <#{fixtures.klass.table_name}(:#{entry_name})> " +
|
135
|
+
"in <#{fixtures.fixture_path}>.\n" +
|
136
|
+
(msg.nil? ? '' : "\n#{msg}\n") +
|
137
|
+
(advice.nil? ? '' : "#{advice}\n")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class ForeignKeySetError < ResolveJoinReferenceError # :nodoc:
|
142
|
+
def advice
|
143
|
+
%Q{
|
144
|
+
This error occurs when you specifiy the foreign key, as well as a join entry.
|
145
|
+
---
|
146
|
+
poem:
|
147
|
+
title: Poetry of Departures
|
148
|
+
author_id: 8
|
149
|
+
author: larkin
|
150
|
+
|
151
|
+
If you need to specify the foreign key, do so within the entry.
|
152
|
+
---
|
153
|
+
poem:
|
154
|
+
title: Poetry of Departures
|
155
|
+
author:
|
156
|
+
larkin:
|
157
|
+
id: 8}
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
require 'test/unit/ui/console/testrunner'
|
162
|
+
module Test # :nodoc:
|
163
|
+
module Unit # :nodoc:
|
164
|
+
module UI # :nodoc:
|
165
|
+
module Console # :nodoc:
|
166
|
+
|
167
|
+
# TestRunner is the Test::Unit class providing a user interface for running tests in a console.
|
168
|
+
# JoinFix modifies this class to provide a nicer output when JoinFix fails. Without these
|
169
|
+
# modifications a single error causes the test output to explode into a meaningless jumble,
|
170
|
+
# once for every test in a suite.
|
171
|
+
#
|
172
|
+
# Turn off the modifications by setting ENV['format_joinfix_errors'] = 'false', for instance by using:
|
173
|
+
#
|
174
|
+
# % rake test format_joinfix_errors=false
|
175
|
+
#
|
176
|
+
class TestRunner
|
177
|
+
private
|
178
|
+
|
179
|
+
alias join_fix_original_finished finished
|
180
|
+
|
181
|
+
def finished(elapsed_time)
|
182
|
+
if ENV['format_joinfix_errors'].to_s =~ /^false$/i
|
183
|
+
join_fix_original_finished(elapsed_time)
|
184
|
+
return
|
185
|
+
end
|
186
|
+
|
187
|
+
nl
|
188
|
+
output("Finished in #{elapsed_time} seconds.")
|
189
|
+
|
190
|
+
joinfix_faults = {}
|
191
|
+
@faults.each_with_index do |fault, index|
|
192
|
+
if fault.kind_of?(Test::Unit::Error) && fault.exception.kind_of?(JoinFixError)
|
193
|
+
affected_tests = (joinfix_faults[fault.exception] ||= [])
|
194
|
+
affected_tests << [index, fault.test_name]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
joinfix_faults.each_pair do |exception, affected_tests|
|
199
|
+
output("\n**************************************\n")
|
200
|
+
output("JoinFix -- #{exception.class}:\n#{exception.message}\n")
|
201
|
+
output("Caused Errors:\n")
|
202
|
+
affected_tests.each do |index, test_name|
|
203
|
+
output("%3d) Error: %s\n" % [index + 1, test_name])
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
@faults.each_with_index do |fault, index|
|
208
|
+
next if fault.kind_of?(Test::Unit::Error) && fault.exception.kind_of?(JoinFixError)
|
209
|
+
|
210
|
+
nl
|
211
|
+
output("%3d) %s" % [index + 1, fault.long_display])
|
212
|
+
end
|
213
|
+
nl
|
214
|
+
output(@result)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
data/lib/joinfix/fixture.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# Defines additional methods to make Fixture behave like a Hash. Required for resolving joins.
|
2
2
|
#
|
3
|
-
#
|
4
|
-
# a YAML::Omap
|
3
|
+
# Accomodates both of the allowed internal data structures for Fixture: Hash and YAML::Omap
|
5
4
|
class Fixture
|
6
5
|
def has_key?(key)
|
7
6
|
# should work for Hash and Omap
|
@@ -14,7 +13,7 @@ class Fixture
|
|
14
13
|
@fixture.each_pair(&block)
|
15
14
|
else
|
16
15
|
# for Omap
|
17
|
-
@fixture.map { |
|
16
|
+
@fixture.map { |key, value| yield(key, value) }
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|