joinfix 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|