Can Rake run each test in a separate Ruby instance? - ruby

I have a very simple Rakefile to test a small Ruby gem. It looks like this:
Rake::TestTask.new
task :default => :test
It invokes two tests that define constants with the same name. This results in errors being output by the second test like this:
warning: already initialized constant xxxxx
The reason for this is because Rake executes all of the tests within a single Ruby instance:
/usr/bin/ruby -I"lib" -I"/usr/lib/ruby/gems/2.1.0/gems/rake-10.3.2/lib" "/usr/lib/ruby/gems/2.1.0/gems/rake-10.3.2/lib/rake/rake_test_loader.rb" "test/test*.rb"
How should I specify that each test should be run in a separate Ruby instance ?
I have achieved this as shown below but I wonder if there is a better way because this solution doesn't scale well for lots of tests.
Rake::TestTask.new(:one) { |t| t.test_files = %w(test/test_one.rb) }
Rake::TestTask.new(:two) { |t| t.test_files = %w(test/test_two.rb) }
task :default => [:one, :two]

Instead of using Rake::TestTask, you could define a test task in your Rakefile that loops through each test file and runs them with sh like this:
task :test do
libs = ['lib',
'/usr/lib/ruby/gems/2.1.0/gems/rake-10.3.2/lib',
'/usr/lib/ruby/gems/2.1.0/gems/rake-10.3.2/lib/rake/rake_test_loader.rb']
test_files = FileList['test/**/test*.rb']
test_files.each do |test_file|
includes = libs.map { |l| "-I#{l}"}.join ' '
sh "ruby #{includes} #{test_file}"
end
end

Related

Rake::TestTask is not working inside another task

We have developed few test cases using mini-test / ruby
Now we are trying to run it using rake files.
its working fine if we are running below code.
require 'rake'
require 'rake/testtask'
Rake::TestTask.new do |t|
t.test_files = FileList['../Home/*TC1.rb']
t.verbose = true
end
But we are putting the above code in separate task then id does not run the test
task :myCustom_task do
Rake::TestTask.new do |t|
t.test_files = FileList['../Home/*TC1.rb']
t.verbose = true
end
end
Then we run it by below command
rake myCustom_task
and it does not run the test.Also it does not show any error while running with --trace option.
What is missing in this approach ?

Rake not running any tests with minitest

I have a file containing a class of multiple tests (using minitest). I have require 'minitest/autorun' at the top of the file and all tests run correctly when I call the file directly (ruby my_tests.rb).
So far, so good. However, now I'm trying to run my tests via rake.
require "rake/testtask"
task :default => [:test]
Rake::TestTask.new do |t|
t.libs << Dir.pwd + "/lib/examples"
t.test_files = FileList['test/test*.rb']
end
Calling rake shows test/my_test.rb getting called but no tests within the class get run (0 tests, 0 assertions, etc.). I do get these warnings:
...gems/minitest-5.8.0/lib/minitest/assertions.rb:17: warning: already initialized constant MiniTest::Assertions::UNDEFINED
...ruby/2.1.0/lib/ruby/2.1.0/minitest/unit.rb:80: warning: previous definition of UNDEFINED was here
How can I run my tests within rake successfully? I am not using rails.
EDIT: Here is the top of my test file:
require 'minitest/spec'
require 'minitest/autorun'
require 'minitest/reporters'
reporter_options = { color: true }
Minitest::Reporters.use![Minitest::Reporters::DefaultReporter.new(reporter_options)]
class Test_PowerSpecInputs < Minitest::Test
def setup
#mc = TestClass.new()
end
def test_does_lib_have_constant
# my test code
end
end
Try changing your Rakefile to this.
require "bundler/gem_tasks"
require "rake/testtask"
Rake::TestTask.new(:test) do |t|
t.libs << "test"
t.libs << "lib"
t.test_files = FileList['test/**/*_test.rb']
end
task :default => :test
jphager2 got me thinking about tool versions and it turned out that my version of rake was fairly old. Updating to 11.x did the trick.

How do I programmatically extract a rake task's description?

I'm attempting to capture the equivalent of rake -D programmatically. I can load the Rakefile I'm targeting and see a list of tasks, but I can not figure out how to get the descriptions.
This will let me see the tasks that I am interested in:
Dir.chdir #myTarget
rake = Rake::Application.new
Rake.application = rake
rake.init
rake.load_rakefile
tasks = Rake.application.tasks
puts tasks.inspect
The above outputs something similar to:
[<Rake::Task default => [test]>, <Rake::Task foodcritic => []>, <Rake::Task integration => [kitchen:all]>]
My question is how to access the desc comments that are visible if I run rake -D. Here's what I'm after:
rake foodcritic
Run Foodcritic lint checks
rake integration
Alias for kitchen:all
rake kitchen:all
Run all test instances
Here's the final solution. The key was that I was missing metadata from the taskmanager:
Dir.chdir #myTarget
rake = Rake::Application.new
Rake::TaskManager.record_task_metadata = true
Rake.application = rake
rake.init
rake.load_rakefile
Rake.application.tasks.each do |t, n|
puts t
puts t.full_comment
puts "\n"
end
Use the methods comment or full_comment for that. More docs on the Rake::Task class here.

How to create an RSpec Rake task using RSpec::Core::RakeTask?

How do I initialize an RSpec Rake task using RSpec::Core::RakeTask?
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new do |t|
# what do I put in here?
end
The Initialize function documented at
http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method isn't very well-documented; it just says:
- (RakeTask) initialize(*args, &task_block)
A new instance of RakeTask
What should I put for *args and &task_block?
I'm following in the footsteps of someone who had already started to build some ruby automation for a PHP project using RSpec in combination with Rake. I'm used to using RSpec without Rake, so I'm unfamiliar with the syntax.
Thanks,
-Kevin
Here is an example of my Rakefile:
require 'rspec/core/rake_task'
task :default => [:spec]
desc "Run the specs."
RSpec::Core::RakeTask.new do |t|
t.pattern = "spec.rb"
end
desc "Run the specs whenever a relevant file changes."
task :watch do
system "watchr watch.rb"
end
This allows to run specs defined in the spec.rb file from Rake
This is what my rakefile looks like
gem 'rspec', '~>3'
require 'rspec/core/rake_task'
task :default => :spec
desc "run tests for this app"
RSpec::Core::RakeTask.new do |task|
test_dir = Rake.application.original_dir
task.pattern = "#{test_dir}/*_spec.rb"
task.rspec_opts = [ "-I#{test_dir}", "-I#{test_dir}/source", '-f documentation', '-r ./rspec_config']
task.verbose = false
end
You can 'rake' from your tests directory and it will run all tests with a name [something]_spec.rb - and it should work across different test directories (e.g. different projects); if you have source in a separate directory (e.g. in the code above, a subdirectory called '/source' it will pick them up. Obviously, you can change that source directory to what you want.
Here's the rspec_config file I use - you can add your own settings in here:
RSpec.configure do |c|
c.fail_fast = true
c.color = true
end

extending Rake's test tasks

I have a few pure-JavaScript, client-side tests using PhantomJS. These I'd like to integrate with rake test.
Currently I use this:
namespace :test do
task :client do
basedir = Rails.root.join("test", "client")
sh "cd #{basedir} && phantomjs lib/run-qunit.js index.html"
end
end
task :test => "test:client"
However, this integration is far from perfect; if one of these tests fails, rake aborts. Also, in contrast to :units, :functionals and :integration, there is no summary of the issues at the end (e.g. "6 tests, 21 assertions, 1 failures, 0 errors").
I could extract that data easily enough, but how do I tell Rake to add it to the total test tally?
You are calling via sh a shell command. Ruby does not know, that it is a test.
In addition sh seems to stop, if a failure occurs.
You have to do two things: Catch the error and check the result of your call.
An example:
require 'rake'
$summary = Hash.new(0)
def mytest(name, cmd)
$summary['test'] += 1
sh cmd do |ok, res|
if ok
$summary['ok'] += 1
else
$summary['failure'] += 1
puts "#{cmd } failed"
end
end
end
namespace :test do
task :one do |tsk|
mytest(tsk.name, "dir")
end
task :two do |tsk|
mytest(tsk.name, "undefined_cmd")
end
task :summary do
p $summary
end
end
task :test => "test:one"
task :test => "test:two"
task :test => "test:summary"
shis called with a block to catch failures. Inside the block, I analyse the result (true for ok, false if the script stops with an error. The result is added to a summary hash.
For your use, you may adapt the code and split the code into two files: All test in one file. And the rake file get a Rake::TestTast.
Your test file may look like this:
gem 'test-unit'
require 'test/unit'
class MyTest < Test::Unit::TestCase
def test_one
assert_nothing_raised{
basedir = Rails.root.join("test", "client")
res = system("cd #{basedir} && phantomjs lib/run-qunit.js index.html")
assert_true(res)
}
end
def test_two
assert_nothing_raised{
res = `dir` #Test with windows
assert_match(/C:/, res) #We are in c:
}
end
end
This works only, if your test finish with a exit code. Perhaps you can use `` instead and get the output of your test for a detailed analyze.

Resources