Order of Rake Test Task - ruby

I have a rake file with three tasks, which I need to execute in order.
require 'rake/testtask'
file 'some_binary_file.elf' do
puts 'fetching file from server ...'
# this task connects to a server and downloads some binaries
# it takes a few seconds to run
end
task flash_application: 'some_binary_file.elf' do
puts 'flashing the file to the hardware ...'
# this task copies a binary file to the flash memory
# of some external hardware, also takes a few seconds
end
Rake::TestTask(:hardware) do |t|
puts 'running tests ...'
f.test_files = FileList['test/**/*_test.rb']
end
rake default: [:flash_application, :hardware]
when I run $ rake in a terminal, it produces the following output.
running tests ... < ---- (not actually running)
fetching file from server ...
flashing the file to the hardware ...
I would expect rake to run the tasks in the order I specified, but It seems to always execute the test task first. It is remarkable that the tests do not run - but the output of the task creation is produced anyway.

When you want to run the tasks in a specific order, you must depend them on each other. In your case, :flash_application should then depend on :hardware

Found the Bug - This problem was not ruby / rake specific. The flash_application task changes the working directory. Because of that, there is no Rakefile with a task 'hardware' in the current working directory. But researching for this bug yielded some interesting insights.
Ruby arrays are ordered, if one want to execute task in an order it is sufficient to define them in execution order in an array i.e.
task some_task: [:first, :second, :third]
Rake::TestTask.new defines a plain old rake task when called. That means, when rake is called, ruby creates an instance of a Rake::TestTask. All code passed into the constructor is executed / yielded during this phase. This yields the described behavior from the original question.

Related

Testing multiple hosts with the same test using serverspec

The Advanced Tips section of the Serverspec site shows an example of testing multiple hosts with the same test set. I've built an example of my own (https://gist.github.com/neilhwatson/81249ad393800a76a8ad), but there are problems.
The first problem is that the tests stop at the first failure rather than proceeding through the lot and keeping a tally. The second is that the failure output does not indicate on which host the failure occurred. What can I do to fix these problems and produce a final report for all hosts?
For the first issue, ServerSpec by default will run all your tests. However, since you have a loop that executes a Rake task for each environment, the first environment to have a failure causes the task to fails and so an exception is raised and the rest of your tasks don't run.
I've forked your gist and updated the Rake task to surround it with a begin/rescue.
...
begin
desc "Run serverspec to #{host}"
RSpec::Core::RakeTask.new(host) do |t|
ENV['TARGET_HOST'] = host
t.pattern = "spec/base,cfengine3/*_spec.rb"
end
rescue
end
...
For the second problem, it doesn't look like ServerSpec will output which environment the tests are running in. But since the updated Gist shows that the host gets set in the spec_helper.rb we can use that to add an RSpec configuration that sets up an after(:each) and only output the host on errors. The relevant code changes are in a fork of the gist, but basically you'll just need the below snippet in your spec_helper.rb:
RSpec.configure do |c|
c.after(:each) do |example|
if example.exception
puts "Failed on #{host_run_on}"
end
end
end

How can I run features within a rake task in parallel?

Normally I run my tests with parallel_cucumber which runs different features in parallel using parallel_test gem. I want to setup a rake task that will run using different profiles and run the features within each task in parallel.
I have setup my Rakefile this way:
namespace :features do
Cucumber::Rake::Task.new(:basket) do |t|
t.profile = "basket"
end
Cucumber::Rake::Task.new(:fruits) do |t|
t.profile = "fruits"
end
Cucumber::Rake::Task.new(:veggies) do |t|
t.profile = "veggies"
end
task :all => [:basket, :fruits, :veggies]
end
When I run "rake features:all" it will run each task in sequence(as expected/desired) but will run the features within each task one at a time(not desired). I would like to keep each task running in sequence but would like the features within each task to run in parallel. Is this possible? If not is there a way this can be done?
As always your help is much appreciated.
Rake offers multitask. You could either
Changing task to multitask in the rakefile:
multitask :all => [:basket, :fruits, :veggies]
use -m option in the command line:
rake -m features:all
Have a look at the parallel_tests gem. It allows you to run your features in parallel. While the typical use case is to run all of your features, you are able to run specific rake tasks in parallel. See the documentation for more details.

run Ruby Unit Tests with Buildr

I am using buildr for some time now, but today I came over a little problem in connection to unit testing of ruby code.
So in my buildfile I have these lines:
define "ruby-project" do
project.version = VERSION_NUMBER
project.group = GROUP
Rake::TestTask.new(:test_rb) do |t|
t.warning = true
t.verbose = true
t.test_files = FileList['test/*.rb']
end
task test => [:test_rb]
end
running buildr test actually runs the tests, what is nice. The test is actually just that:
require 'test/unit'
class TestFileParse < Test::Unit::TestCase
def test_fail
assert(false, 'test to fail')
end
end
As expected it fails, BUT what is strange for me is that buildr quits the build with that message:
sh: 2: Syntax error: Unterminated quoted string
Buildr aborted!
RuntimeError : Command failed with status (1): [/usr/bin/ruby1.9.1 -w -I"lib" -I"/var/lib/...]
Running ruby file-with-failing-test-from-above.rp does not throw a runtime error, instead it prints the test report on screen, what is what is what I want.
Question
How can I make Buildr run the unit tests without quitting with an RuntimeError if a test fails?
Greetings Philipp
Since I am not too familiar with Ruby development, what involves Rake, I was looking for the wrong question. Instead of looking for: »how to run unit test with buildr«, the question should have been »how to run unit tests with rake«, because buildr is a kind of extended Rake (similar to the »maven-ant-relationship«). So everything one can do in Rake, one can do in buildr, too. Therefore on good SO answer to run ruby unit tests in buildr is here.
Additionally it is possible to run RSpec's with buildr, therefore one has two options:
set project.test.using :rspec, what involves the use of JRuby, so one has to set JRUBY_HOME (in my case ~/.rvm/rubies/jruby-1.7.9/), or run buildr within jruby. In my case this slowed test execution down, because each time a jvm needed to be started.
Or one can use rspec's rake task in this manner. I choose this method since my tests run much faster without the jvm overhead.
n.b. as the answer implies, I switched over to rspec.
Happy Testing/Speccing!

Why RSpec runs specs twice when running from within ruby and spec file is reloaded?

I'm trying to use RSpec from within existing ruby runtime and run specs every time when file changes. This is because of JRuby and JVM startup time. To eliminate this on every run I'd like to start ruby once, then only reload changed files and run specs. I was using guard (with diffrent extensions) and watchr but all seem to suffer from an issue described below.
I nailed the issue down to RSpec itself. The problem is, when running RSpec via RSpec::Core::Runner.run several times it works fine until spec file is reloaded using load. Then RSpecs starts running specs twice.
I've created sample project showing this issue live: https://github.com/mostr/rspec_double_run_issue
Below is sample output:
ruby run_spec_in_loop.rb
Running spec from within ruby runtime
.
Finished in 0.00047 seconds
1 example, 0 failures
loading spec file via 'load' as if it was changed and we wanted changes to be picked up
Running spec from within ruby runtime
..
Finished in 0.001 seconds
2 examples, 0 failures
Is there any way to tell RSpec to clear its context between subsequent runs when run from within existing ruby runtime? I've also raised this as an issue #826 for RSpec Core project.
Summarizing the answer here in order to remove this question from the "Unanswered" filter...
Per RJHunter's observation, the explanation has been documented on the GitHub RSpec Core project here:
https://github.com/rspec/rspec-core/issues/826#issuecomment-15089030
For posterity (in case the above link dies), here are the details:
The RSpec runner is already calling load internally, your second load is what's causing the double run issue.
I quickly knocked up a script based off your example which reruns a single spec file, changes the specs to something else, then reruns them, work's correctly without the second load
See: https://gist.github.com/JonRowe/5192007
The aforementioned Gist contains:
require 'rspec'
spec_file = 'spec/sample_spec.rb'
File.open(spec_file, 'w') { |file| file.write 'describe { specify { expect(true).to eq false } }' }
1.upto(5) do |i|
puts "Running spec from within ruby runtime"
::RSpec::Core::Runner.run([spec_file], STDERR, STDOUT)
#rewriting the spec file
File.open(spec_file, 'w') { |file| file.write "describe { specify { expect(#{i}).to eq false } }" }
end

How to call rake target twice

I generate two different sets of DLL files from my .sln by modifying the .csproj files to include an extra compilation symbol. I'm using rake to build the solution, and have the following Build task:
#==========================================================
desc "Builds the DPSF.sln in Release mode."
msbuild :Build do |msb|
puts 'Building the DPSF solution...'
msb.properties :configuration => :Release
msb.targets [:Clean, :Rebuild]
msb.solution = DPSF_SOLUTION_FILE_PATH
msb.parameters "/nologo", "/maxcpucount", "/fileLogger", "/noconsolelogger"
msb.verbosity = "quiet" # Use "diagnostic" instead of "quiet" for troubleshooting build problems.
# Delete the build log file if the build was successful (otherwise the script will puke before this point).
File.delete('msbuild.log')
end
I then try to generate both sets of DLL files using:
desc "Builds new regular and AsDrawableGameComponent DLLs."
task :BuildNewDLLs => [:DeleteExistingDLLs, :Build, :UpdateCsprojFilesToBuildAsDrawableGameComponentDLLs, :Build, :RevertCsprojFilesToBuildRegularDLLs]
You can see that I call :Build twice here. The problem is that only the first one runs. If I copy/paste my :Build target and call it :Build2 and change :BuildNewDLLs to call :Build2 the second time, then everything works fine. So how can I make it so that I can call the :Build target multiple times from within the :BuildNewDLLs target?
Thanks in advance.
I know this is an old question, but I just spent 15 minutes figuring this out, so for the sake of documentation, here goes:
You can call reenable from within the same task that you wish to reenable. And since the task block yields the current task as first argument, you can do:
task :thing do |t|
puts "hello"
t.reenable
end
And now this works:
rake thing thing
Rake will, by default, ensure that each rake task is executed once and only once per session. You can re-enable your build task with the following code.
::Rake.application['Build'].reenable
That will allow it to be re-executed in the same session.

Resources