summaryrefslogtreecommitdiff
path: root/lib/hoe/test.rb
blob: e9591531d2c194f7dd00738c939f183ef05aa9ad (plain)
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
##
# Test plugin for hoe.
#
# === Tasks Provided:
#
# audit::              Run ZenTest against the package.
# default::            Run the default task(s).
# multi::              Run the test suite using multiruby.
# test::               Run the test suite.
# test_deps::          Show which test files fail when run alone.

module Hoe::Test
  def deprecate msg # :nodoc:
    where = caller_locations[1]

    warn "DEPRECATED: %s from %s" % [msg, where]
  end

  ##
  # Configuration for the supported test frameworks for test task.

  SUPPORTED_TEST_FRAMEWORKS = {
    :testunit => "test/unit",
    :minitest => "minitest/autorun",
    :none     => nil,
  }

  Hoe::DEFAULT_CONFIG["multiruby_skip"] = []

  ##
  # Optional: Array of incompatible versions for multiruby filtering.
  # Used as a regex.
  #
  # Can be defined both in .hoerc and in your hoe spec. Both will be
  # used.

  attr_accessor :multiruby_skip

  ##
  # Optional: What test library to require [default: :minitest]

  attr_accessor :testlib

  ##
  # Optional: Additional ruby to run before the test framework is loaded.

  attr_accessor :test_prelude

  ##
  # Optional: RSpec dirs. [default: %w(spec lib)]

  attr_accessor :rspec_dirs

  ##
  # Optional: RSpec options. [default: []]

  attr_accessor :rspec_options

  ##
  # The test task created for this plugin.

  attr_accessor :test_task

  ##
  # Initialize variables for plugin.

  def initialize_test
    self.multiruby_skip ||= []
    self.testlib        ||= :minitest
    self.test_prelude   ||= nil
    self.rspec_dirs     ||= %w[spec lib]
    self.rspec_options  ||= []
  end

  ##
  # Define tasks for plugin.

  def define_test_tasks
    default_tasks = []

    task :test

    if File.directory? "test" then
      case testlib
      when :minitest then
        require "minitest/test_task" # currently in hoe, but will move

        test_prelude = self.test_prelude
        self.test_task = Minitest::TestTask.create :test do |t|
          t.test_prelude = test_prelude
          t.libs += Hoe.include_dirs.uniq
        end
      when :testunit then
        desc "Run the test suite. Use FILTER or TESTOPTS to add flags/args."
        task :test do
          ruby make_test_cmd
        end

        desc "Print out the test command. Good for profiling and other tools."
        task :test_cmd do
          puts make_test_cmd
        end

        desc "Show which test files fail when run alone."
        task :test_deps do
          tests = Dir[*self.test_globs].uniq

          paths = %w[bin lib test].join(File::PATH_SEPARATOR)
          null_dev = Hoe::WINDOZE ? "> NUL 2>&1" : "> /dev/null 2>&1"

          tests.each do |test|
            unless system "ruby -I#{paths} #{test} #{null_dev}" then
              puts "Dependency Issues: #{test}"
            end
          end
        end

        if testlib == :minitest then
          desc "Show bottom 25 tests wrt time."
          task "test:slow" do
            sh "rake TESTOPTS=-v | sort -n -k2 -t= | tail -25"
          end
        end
      when :none then
        # do nothing
      else
        warn "Unsupported? Moving to Minitest::TestTask. Let me know if you use this!"
      end

      desc "Run the test suite using multiruby."
      task :multi do
        skip = with_config do |config, _|
          config["multiruby_skip"] + self.multiruby_skip
        end

        ENV["EXCLUDED_VERSIONS"] = skip.join(":")
        system "multiruby -S rake"
      end

      default_tasks << :test
    end

    if File.directory? "spec" then
      found = try_loading_rspec2 || try_loading_rspec1

      if found then
        default_tasks << :spec
      else
        warn "Found spec dir, but couldn't load rspec (1 or 2) task. skipping."
      end
    end

    desc "Run the default task(s)."
    task :default => default_tasks

    desc "Run ZenTest against the package."
    task :audit do
      libs = %w[lib test ext].join(File::PATH_SEPARATOR)
      sh "zentest -I=#{libs} #{spec.files.grep(/^(lib|test)/).join(" ")}"
    end
  end

  ##
  # Generate the test command-line.

  def make_test_cmd
    unless SUPPORTED_TEST_FRAMEWORKS.key?(testlib)
      raise "unsupported test framework #{testlib}"
    end

    deprecate "Moving to Minitest::TestTask. Let me know if you use this!"

    framework = SUPPORTED_TEST_FRAMEWORKS[testlib]

    tests = ["rubygems"]
    tests << framework if framework
    tests << test_globs.sort.map { |g| Dir.glob(g) }
    tests.flatten!
    tests.map! { |f| %(require "#{f}") }

    tests.insert 1, test_prelude if test_prelude

    filter = (ENV["FILTER"] || ENV["TESTOPTS"] || "").dup
    filter << " -n #{ENV["N"]}" if ENV["N"]
    filter << " -e #{ENV["X"]}" if ENV["X"]

    "#{Hoe::RUBY_FLAGS} -e '#{tests.join("; ")}' -- #{filter}"
  end

  ##
  # Attempt to load RSpec 2, returning true if successful

  def try_loading_rspec2
    deprecate "I want to drop this entirely. Let me know if you use this!"

    require "rspec/core/rake_task"

    desc "Run all specifications"
    RSpec::Core::RakeTask.new(:spec) do |t|
      t.rspec_opts = self.rspec_options
      t.rspec_opts << "-I#{self.rspec_dirs.join(":")}" unless
      rspec_dirs.empty?
    end

    true
  rescue LoadError => err
    warn "%p while trying to load RSpec 2: %s" % [ err.class, err.message ]
    false
  end

  ##
  # Attempt to load RSpec 1, returning true if successful

  def try_loading_rspec1
    deprecate "I want to drop this entirely. Let me know if you use this!"

    require "spec/rake/spectask"

    desc "Run all specifications"
    Spec::Rake::SpecTask.new(:spec) do |t|
      t.libs = self.rspec_dirs
      t.spec_opts = self.rspec_options
    end
    true
  rescue LoadError => err
    warn "%p while trying to load RSpec 1: %s" % [ err.class, err.message ]
    false
  end
end