license_finder 0.7.3 → 0.8.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.
Files changed (73) hide show
  1. data/.gitignore +4 -3
  2. data/.travis.yml +1 -8
  3. data/bin/license_finder +31 -1
  4. data/db/migrate/201303290935_create_dependencies.rb +14 -0
  5. data/db/migrate/201303291155_create_licenses.rb +13 -0
  6. data/db/migrate/201303291402_create_approvals.rb +13 -0
  7. data/db/migrate/201303291456_create_ancestries.rb +9 -0
  8. data/db/migrate/201303291519_create_bundler_groups.rb +13 -0
  9. data/db/migrate/201303291720_move_manual_from_approvals_to_licenses.rb +11 -0
  10. data/db/migrate/201303291753_allow_null_license_names.rb +7 -0
  11. data/db/migrate/201304011027_allow_null_dependency_version.rb +7 -0
  12. data/db/migrate/201304020947_change_table_name_licenses_to_license_aliases.rb +5 -0
  13. data/features/approve_dependencies.feature +0 -45
  14. data/features/html_report.feature +1 -11
  15. data/features/license_finder.feature +13 -27
  16. data/features/license_finder_rake_task.feature +2 -1
  17. data/features/set_license.feature +2 -4
  18. data/features/step_definitions/license_finder_steps.rb +25 -0
  19. data/features/step_definitions/steps.rb +40 -26
  20. data/features/text_report.feature +2 -2
  21. data/files/license_finder.yml +1 -1
  22. data/lib/license_finder.rb +14 -6
  23. data/lib/license_finder/bundle.rb +4 -17
  24. data/lib/license_finder/bundle_syncer.rb +2 -3
  25. data/lib/license_finder/bundled_gem.rb +4 -47
  26. data/lib/license_finder/cli.rb +9 -16
  27. data/lib/license_finder/configuration.rb +55 -3
  28. data/lib/license_finder/dependency_report.rb +1 -1
  29. data/lib/license_finder/gem_saver.rb +69 -0
  30. data/lib/license_finder/html_report.rb +2 -2
  31. data/lib/license_finder/license.rb +60 -58
  32. data/lib/license_finder/license_files.rb +36 -0
  33. data/lib/license_finder/license_url.rb +8 -6
  34. data/lib/license_finder/platform.rb +32 -0
  35. data/lib/license_finder/possible_license_file.rb +1 -1
  36. data/lib/license_finder/tables.rb +7 -0
  37. data/lib/license_finder/tables/approval.rb +4 -0
  38. data/lib/license_finder/tables/bundler_group.rb +4 -0
  39. data/lib/license_finder/tables/dependency.rb +31 -0
  40. data/lib/license_finder/tables/license_alias.rb +22 -0
  41. data/lib/license_finder/yml_to_sql.rb +127 -0
  42. data/lib/tasks/license_finder.rake +3 -0
  43. data/lib/templates/html_report.erb +50 -32
  44. data/lib/templates/text_report.erb +3 -2
  45. data/license_finder.gemspec +14 -5
  46. data/readme.md +10 -50
  47. data/spec/lib/license_finder/bundle_spec.rb +22 -19
  48. data/spec/lib/license_finder/bundle_syncer_spec.rb +4 -10
  49. data/spec/lib/license_finder/bundled_gem_spec.rb +40 -108
  50. data/spec/lib/license_finder/cli_spec.rb +3 -3
  51. data/spec/lib/license_finder/configuration_spec.rb +53 -21
  52. data/spec/lib/license_finder/gem_saver_spec.rb +155 -0
  53. data/spec/lib/license_finder/html_report_spec.rb +32 -15
  54. data/spec/lib/license_finder/license_files_spec.rb +50 -0
  55. data/spec/lib/license_finder/tables/dependency_spec.rb +102 -0
  56. data/spec/lib/license_finder/tables/license_alias_spec.rb +54 -0
  57. data/spec/lib/license_finder/text_report_spec.rb +6 -4
  58. data/spec/lib/license_finder/yml_to_sql_spec.rb +99 -0
  59. data/spec/lib/license_finder_spec.rb +5 -5
  60. data/spec/spec_helper.rb +17 -1
  61. metadata +79 -32
  62. data/lib/license_finder/dependency.rb +0 -50
  63. data/lib/license_finder/persistence.rb +0 -1
  64. data/lib/license_finder/persistence/yaml.rb +0 -7
  65. data/lib/license_finder/persistence/yaml/configuration.rb +0 -34
  66. data/lib/license_finder/persistence/yaml/dependency.rb +0 -127
  67. data/lib/license_finder/source_syncer.rb +0 -40
  68. data/lib/templates/dependency.html.erb +0 -54
  69. data/spec/lib/license_finder/dependency_spec.rb +0 -188
  70. data/spec/lib/license_finder/persistence/yaml/dependency_spec.rb +0 -5
  71. data/spec/lib/license_finder/source_syncer_spec.rb +0 -37
  72. data/spec/support/shared_examples/persistence/configuration.rb +0 -28
  73. data/spec/support/shared_examples/persistence/dependency.rb +0 -138
data/readme.md CHANGED
@@ -7,10 +7,10 @@ With bundler it's easy for your project to depend on many gems. This decomposit
7
7
 
8
8
  ## Installation
9
9
 
10
- Add license_finder to your Rails project's Gemfile and `bundle`:
10
+ Add license_finder to your project's Gemfile and `bundle`:
11
11
 
12
12
  ```ruby
13
- gem 'license_finder', git: "https://github.com/pivotal/LicenseFinder.git"
13
+ gem 'license_finder'
14
14
  ```
15
15
 
16
16
  ## Usage
@@ -18,7 +18,7 @@ gem 'license_finder', git: "https://github.com/pivotal/LicenseFinder.git"
18
18
  License finder will generate reports of action items - i.e., dependencies that do not fall within your license "whitelist".
19
19
 
20
20
  ```sh
21
- $ bundle exec license_finder
21
+ $ license_finder
22
22
  ```
23
23
 
24
24
  The first time you run this, `license_finder` will create a default configuration file `./config/license_finder.yml`:
@@ -32,6 +32,7 @@ whitelist:
32
32
  ignore_groups:
33
33
  #- test
34
34
  #- development
35
+ dependencies_file_dir: './doc/'
35
36
  ```
36
37
 
37
38
  This allows you to configure bundler groups and add licenses to the whitelist.
@@ -51,7 +52,7 @@ rubyzip, 0.9.9, ruby
51
52
  xml-simple, 1.1.1, other
52
53
  ```
53
54
 
54
- The executable task will also write out a dependencies.yml, dependencies.txt, and dependencies.html file in the root of your project.
55
+ The executable task will also write out a dependencies.db, dependencies.txt, and dependencies.html file in the doc/ directory (by default).
55
56
 
56
57
  The latter two files are human readable reports that you could send to your non-technical business partners, lawyers, etc.
57
58
 
@@ -59,15 +60,9 @@ The latter two files are human readable reports that you could send to your non-
59
60
  unapproved dependencies. You could use this in a CI build, for example, to alert you whenever someone adds an
60
61
  unapproved dependency to the project.
61
62
 
62
- It will also merge in an existing dependencies.yml file, if one exists (i.e., you've previously run this command
63
- and then edited the resulting file).
64
-
65
63
  ### Manually recording licenses
66
64
 
67
- When you have dependencies marked as having an 'other' license, `license_finder` will output
68
- the license and readme file locations for the dependency, allowing you to manually research what the actual
69
- license is. Once this has been established, you can record this information with the `-l` option
70
- as such:
65
+ When you have dependencies marked as having an 'other' license, `license_finder` you should manually research what the actual license is. Once this has been established, you can record this information with the `-l` or `--license` option as such:
71
66
 
72
67
  ```sh
73
68
  $ license_finder -l MIT my_unknown_dependency
@@ -82,7 +77,7 @@ If your business decides that this is an acceptable risk, you can manually appro
82
77
  `--approve` option of the `license_finder` command.
83
78
 
84
79
  For example, lets assume you've only
85
- whitelisted the "MIT" license in your `config/license_finder.yml`. You then add the 'awesome_gpl_gem' to your Gemfile,
80
+ whitelisted the "MIT" license in your `config/license_finder.yml`. You then add the `awesome_gpl_gem` to your Gemfile,
86
81
  which we'll assume is licensed with the `GPL` license. You then run `license_finder` and see
87
82
  the gem listed in the output:
88
83
 
@@ -93,49 +88,14 @@ awesome_gpl_gem, 1.0.0, GPL
93
88
  Your business tells you that in this case, it's acceptable to use this gem. You now run:
94
89
 
95
90
  ```sh
96
- $ bundle exec license_finder -a awesome_gpl_gem
91
+ $ license_finder -a awesome_gpl_gem
97
92
  ```
98
93
 
99
94
  If you rerun `license_finder`, you should no longer see `awesome_gpl_gem` in the output.
100
95
 
96
+ ## Compatibility
101
97
 
102
- ## Manually managing Javascript Dependencies
103
-
104
- License Finder currently has no method for automatically detecting third-party javascript libraries in your application
105
- and alerting you to license violations. However, you can manually add javascript dependencies to your `dependencies.yml`
106
- file:
107
-
108
- ```yaml
109
- - name: "my_javascript_library"
110
- version: "0.0.0"
111
- license: "GPL"
112
- approved: false
113
- ```
114
-
115
- You could then update the "approved" attribute to true once you have signoff from your business. License Finder will
116
- remember any manually added licenses between successive runs.
117
-
118
-
119
- ## Usage with Rake
120
-
121
- First, add license finder to your project's Gemfile:
122
-
123
- ```ruby
124
- gem "license_finder"
125
- ```
126
-
127
- Next, update your project's Rakefile with the license finder rake task:
128
-
129
- ```ruby
130
- require 'bundler/setup'
131
- require 'license_finder'
132
- LicenseFinder.load_rake_tasks
133
- ```
134
-
135
- You can now run `bundle exec rake license_finder`. This is the equivalent of running `bundle exec license_finder`.
136
-
137
- This could be handy if you have a build for CI that you want to break when you have unapproved dependencies. The
138
- rake task will `exit 1` immediately if there are unapproved dependencies, stopping your build dead in its tracks!
98
+ license_finder is compatible with ruby 1.9, and ruby 2.0. There is also experimental support for jruby.
139
99
 
140
100
  ## A note to gem authors / maintainers
141
101
 
@@ -2,6 +2,17 @@ require "spec_helper"
2
2
 
3
3
  module LicenseFinder
4
4
  describe Bundle do
5
+ let(:definition) do
6
+ double('definition', {
7
+ :dependencies => [],
8
+ :groups => [],
9
+ :specs_for => [
10
+ build_gemspec('gem1', '1.2.3'),
11
+ build_gemspec('gem2', '0.4.2')
12
+ ]
13
+ })
14
+ end
15
+
5
16
  def build_gemspec(name, version, dependency=nil)
6
17
  Gem::Specification.new do |s|
7
18
  s.name = name
@@ -15,28 +26,20 @@ module LicenseFinder
15
26
  end
16
27
  end
17
28
 
18
- describe '.from_bundler(bundle)' do
19
- let(:definition) do
20
- double('definition', {
21
- :dependencies => [],
22
- :groups => [],
23
- :specs_for => [
24
- build_gemspec('gem1', '1.2.3'),
25
- build_gemspec('gem2', '0.4.2')
26
- ]
27
- })
28
- end
29
-
29
+ describe '.current_gem_dependencies' do
30
30
  subject do
31
- Bundle.new(definition).gems.map(&:to_dependency)
31
+ Bundle.current_gem_dependencies(definition)
32
32
  end
33
33
 
34
- its(:count) { should == 2 }
35
-
36
34
  it "should have 2 dependencies" do
37
35
  subject.size.should == 2
38
36
  end
39
37
 
38
+ it "returns persisted dependencies" do
39
+ subject.first.id.should be
40
+ subject.last.id.should be
41
+ end
42
+
40
43
  context "when initialized with a parent and child gem" do
41
44
  before do
42
45
  definition.stub(:specs_for).and_return([
@@ -46,11 +49,11 @@ module LicenseFinder
46
49
  end
47
50
 
48
51
  it "should update the child dependency with its parent data" do
49
- gem1 = subject.first
50
- gem2 = subject.last
52
+ gem1 = subject.first.reload
53
+ gem2 = subject.last.reload
51
54
 
52
- gem2.parents.should == [gem1.name]
53
- gem1.children.should == [gem2.name]
55
+ gem2.parents.should == [gem1]
56
+ gem1.children.should == [gem2]
54
57
  end
55
58
  end
56
59
  end
@@ -3,16 +3,10 @@ require "spec_helper"
3
3
  module LicenseFinder
4
4
  describe BundleSyncer do
5
5
  describe "#sync!" do
6
- it "should delegate the bundled dependencies and the persisted bundled dependencies to the source syncer" do
7
- gem = double :gem, :to_dependency => double(:gem_dependency)
8
- bundled_dep = double :bundled_dep, source: "bundle"
9
- manual_dep = double :manual_dep, source: nil
10
- syncer = double :source_syncer
11
-
12
- Bundle.stub_chain(:new, :gems).and_return [gem]
13
- Dependency.stub(:all).and_return [bundled_dep, manual_dep]
14
- SourceSyncer.should_receive(:new).with([gem.to_dependency], [bundled_dep]).and_return syncer
15
- syncer.should_receive(:sync!)
6
+ it "saves new, updates old, and destroys obsolete gems" do
7
+ current_dependencies = stub
8
+ Bundle.stub(:current_gem_dependencies).and_return { current_dependencies }
9
+ Dependency.should_receive(:destroy_obsolete).with(current_dependencies)
16
10
 
17
11
  BundleSyncer.sync!
18
12
  end
@@ -1,129 +1,61 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe LicenseFinder::BundledGem do
4
- subject { LicenseFinder::BundledGem.new(gemspec) }
5
-
6
- let(:gemspec) do
7
- Gem::Specification.new do |s|
8
- s.name = 'spec_name'
9
- s.version = '2.1.3'
10
- s.summary = 'summary'
11
- s.description = 'description'
12
- s.homepage = 'homepage'
13
-
14
- s.add_dependency 'foo'
15
- end
16
- end
17
-
18
- def fixture_path(fixture)
19
- Pathname.new(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec', 'fixtures', fixture)).realpath.to_s
20
- end
21
-
22
- its(:name) { should == 'spec_name 2.1.3' }
23
- its(:dependency_name) { should == 'spec_name' }
24
- its(:dependency_version) { should == '2.1.3' }
25
- its(:install_path) { should == gemspec.full_gem_path }
26
-
27
- describe "#determine_license" do
28
- subject do
29
- details = LicenseFinder::BundledGem.new(gemspec)
30
- details.stub(:license_files).and_return([license_file])
31
- details
32
- end
33
-
34
- let(:license_file) { LicenseFinder::PossibleLicenseFile.new('gem', 'gem/license/path') }
35
-
36
- it "returns the license from the gemspec if provided" do
37
- gemspec.stub(:license).and_return('Some License')
38
-
39
- subject.determine_license.should == "Some License"
40
- end
41
-
42
- it "returns the matched license if detected" do
43
- license_file.stub(:license).and_return('Detected License')
44
-
45
- subject.determine_license.should == "Detected License"
46
- end
47
-
48
- it "returns 'other' otherwise" do
49
- license_file.stub(:license).and_return(nil)
50
-
51
- subject.determine_license.should == "other"
52
- end
53
- end
54
-
55
- describe "#license_files" do
56
- it "is empty if there aren't any license files" do
57
- subject.license_files.should == []
58
- end
59
-
60
- it "includes files with names like LICENSE, License or COPYING" do
61
- gemspec.stub(:full_gem_path).and_return(fixture_path('license_names'))
62
-
63
- subject.license_files.map(&:file_name).should =~
64
- %w[COPYING.txt LICENSE Mit-License README.rdoc Licence.rdoc]
3
+ module LicenseFinder
4
+ describe BundledGem do
5
+ subject { described_class.new(gemspec) }
6
+
7
+ let(:gemspec) do
8
+ Gem::Specification.new do |s|
9
+ s.name = 'spec_name'
10
+ s.version = '2.1.3'
11
+ s.summary = 'summary'
12
+ s.description = 'description'
13
+ s.homepage = 'homepage'
14
+
15
+ s.add_dependency 'foo'
16
+ end
65
17
  end
66
18
 
67
- it "includes files deep in the hierarchy" do
68
- gemspec.stub(:full_gem_path).and_return(fixture_path('nested_gem'))
69
-
70
- subject.license_files.map { |f| [f.file_name, f.file_path] }.should =~ [
71
- %w[LICENSE vendor/LICENSE]
72
- ]
19
+ def fixture_path(fixture)
20
+ Pathname.new(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec', 'fixtures', fixture)).realpath.to_s
73
21
  end
74
22
 
75
- it "includes both files nested inside LICENSE directory and top level files" do
76
- gemspec.stub(:full_gem_path).and_return(fixture_path('license_directory'))
77
- found_license_files = subject.license_files
23
+ its(:name) { should == 'spec_name 2.1.3' }
24
+ its(:dependency_name) { should == 'spec_name' }
25
+ its(:dependency_version) { should == '2.1.3' }
78
26
 
79
- found_license_files.map { |f| [f.file_name, f.file_path] }.should =~ [
80
- %w[BSD-2-Clause.txt LICENSE/BSD-2-Clause.txt],
81
- %w[GPL-2.0.txt LICENSE/GPL-2.0.txt],
82
- %w[MIT.txt LICENSE/MIT.txt],
83
- %w[RUBY.txt LICENSE/RUBY.txt],
84
- %w[COPYING COPYING],
85
- %w[LICENSE LICENSE/LICENSE]
86
- ]
87
- end
88
- end
27
+ describe "#determine_license" do
28
+ subject do
29
+ details = BundledGem.new(gemspec)
30
+ details.stub(:license_files).and_return([license_file])
31
+ details
32
+ end
89
33
 
90
- describe '#to_dependency' do
91
- subject { LicenseFinder::BundledGem.new(gemspec).to_dependency }
34
+ let(:license_file) { PossibleLicenseFile.new('gem', 'gem/license/path') }
92
35
 
93
- its(:name) { should == 'spec_name' }
94
- its(:version) { should == '2.1.3' }
95
- its(:summary) { should == 'summary' }
96
- its(:source) { should == 'bundle' }
97
- its(:description) { should == 'description' }
98
- its(:homepage) { should == 'homepage' }
99
- its(:children) { should == ['foo']}
36
+ it "returns the license from the gemspec if provided" do
37
+ gemspec.stub(:license).and_return('Some License')
100
38
 
101
- describe 'with a known license' do
102
- before do
103
- gemspec.stub(:full_gem_path).and_return(fixture_path('mit_licensed_gem'))
104
- LicenseFinder::PossibleLicenseFile.any_instance.stub(:license).and_return('Detected License')
39
+ subject.determine_license.should == "Some License"
105
40
  end
106
41
 
107
- its(:license) { should == 'Detected License' }
108
- its(:license_files) { should == ["LICENSE"] }
109
- end
42
+ it "returns the matched license if detected" do
43
+ license_file.stub(:license).and_return('Detected License')
110
44
 
111
- describe 'with an unknown license' do
112
- before do
113
- gemspec.stub(:full_gem_path).and_return(fixture_path('other_licensed_gem'))
114
- LicenseFinder::PossibleLicenseFile.any_instance.stub(:license).and_return(nil)
45
+ subject.determine_license.should == "Detected License"
115
46
  end
116
47
 
117
- its(:license) { should == 'other' }
118
- end
48
+ it "returns 'other' otherwise" do
49
+ license_file.stub(:license).and_return(nil)
119
50
 
120
- describe 'with UTF8 file License' do
121
- before do
122
- gemspec.stub(:full_gem_path).and_return(fixture_path('utf8_gem'))
51
+ subject.determine_license.should == "other"
123
52
  end
53
+ end
124
54
 
125
- it "handles non UTF8 encodings" do
126
- expect { subject }.not_to raise_error ArgumentError, "invalid byte sequence in UTF-8"
55
+ describe "#license_files" do
56
+ it "delegates to the license files helper" do
57
+ LicenseFiles.should_receive(:new).with(gemspec.full_gem_path) { stub(files: [] )}
58
+ subject.license_files
127
59
  end
128
60
  end
129
61
  end
@@ -10,7 +10,7 @@ module LicenseFinder
10
10
  dependency = double('dependency', :name => nil)
11
11
  dependency.should_receive(:approve!)
12
12
 
13
- Dependency.stub(:find_by_name).with('foo').and_return(dependency)
13
+ Dependency.stub(:first).with(name: 'foo').and_return(dependency)
14
14
 
15
15
  CLI.execute! approve: true, dependency: 'foo'
16
16
  end
@@ -19,9 +19,9 @@ module LicenseFinder
19
19
  context "when the -l (--license) switch is provided" do
20
20
  it "should update the license on the requested gem" do
21
21
  dependency = double :dependency, :name => nil
22
- dependency.should_receive(:update_attributes).with(:license => "foo")
22
+ dependency.should_receive(:set_license_manually).with("foo")
23
23
 
24
- Dependency.stub(:find_by_name).with("foo_gem").and_return dependency
24
+ Dependency.stub(:first).with(name: "foo_gem").and_return dependency
25
25
 
26
26
  CLI.execute! license: "foo", dependency: 'foo_gem'
27
27
  end
@@ -1,38 +1,70 @@
1
1
  require "spec_helper"
2
2
 
3
- describe LicenseFinder::Configuration do
4
- it_behaves_like "a persistable configuration"
3
+ module LicenseFinder
4
+ describe Configuration do
5
+ let(:config) { described_class.new }
5
6
 
6
- let(:config) { LicenseFinder::Configuration.new }
7
+ let(:klass) { described_class }
7
8
 
8
- describe "whitelisted?" do
9
- context "canonical name whitelisted" do
10
- before { config.whitelist = [LicenseFinder::License::Apache2.names[rand(LicenseFinder::License::Apache2.names.count)]]}
9
+ describe '.new' do
10
+ let(:attributes) do
11
+ {
12
+ "whitelist" => ["FooLicense", "BarLicense"],
13
+ "ignore_groups" => [:test, :development],
14
+ "dependencies_file_dir" => "."
15
+ }
16
+ end
11
17
 
12
- let(:possible_license_names) { LicenseFinder::License::Apache2.names }
18
+ subject { klass.new(attributes) }
13
19
 
14
- it "should return true if if the license is the canonical name, pretty name, or alternative name of the license" do
15
- possible_license_names.each do |name|
16
- config.whitelisted?(name).should be_true, "expected #{name} to be whitelisted, but wasn't."
20
+ context "with known attributes" do
21
+ it "should set the all of the attributes on the instance" do
22
+ subject.whitelist.should == attributes['whitelist']
23
+ subject.ignore_groups.should == attributes['ignore_groups']
24
+ subject.dependencies_dir.should == attributes['dependencies_file_dir']
17
25
  end
18
26
  end
19
27
 
20
- it "should be case-insensitive" do
21
- possible_license_names.map(&:downcase).each do |name|
22
- config.whitelisted?(name).should be_true, "expected #{name} to be whitelisted, but wasn't"
23
- end
28
+ it "uses absolute path in database_path" do
29
+ subject.database_path.should_not start_with(".")
24
30
  end
25
31
  end
26
- end
27
32
 
28
- describe "#ignore_groups" do
29
- it "should default to an empty array" do
30
- config.ignore_groups.should == []
33
+ describe "#whitelist" do
34
+ it "should default to an empty array" do
35
+ klass.new.whitelist.should == []
36
+ end
31
37
  end
32
38
 
33
- it "should always return symbolized versions of the ignore groups" do
34
- config.ignore_groups = %w[test development]
35
- config.ignore_groups.should == [:test, :development]
39
+ describe "whitelisted?" do
40
+ context "canonical name whitelisted" do
41
+ before { config.whitelist = [License::Apache2.names[rand(License::Apache2.names.count)]]}
42
+
43
+ let(:possible_license_names) { License::Apache2.names }
44
+
45
+ it "should return true if if the license is the canonical name, pretty name, or alternative name of the license" do
46
+ possible_license_names.each do |name|
47
+ config.whitelisted?(name).should be_true, "expected #{name} to be whitelisted, but wasn't."
48
+ end
49
+ end
50
+
51
+ it "should be case-insensitive" do
52
+ possible_license_names.map(&:downcase).each do |name|
53
+ config.whitelisted?(name).should be_true, "expected #{name} to be whitelisted, but wasn't"
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "#ignore_groups" do
60
+ it "should default to an empty array" do
61
+ config.ignore_groups.should == []
62
+ end
63
+
64
+ it "should always return symbolized versions of the ignore groups" do
65
+ config.ignore_groups = %w[test development]
66
+ config.ignore_groups.should == [:test, :development]
67
+ end
36
68
  end
37
69
  end
38
70
  end