I am using rspec and cucumber to run watir tests at sauce labs.
I would like that test name (at sauce labs) is the same as the name of rspec describe block or cucumber feature.
So, if I have rspec file:
describe "something" do
# teh codez
end
or cucumber file:
Feature: something
# teh codez
I would like that at sauce labs the test is also named something. I know how to say to sauce labs how I want the test to be named, but I do not know how to get rspec describe block name or cucumber feature name when the tests are running.
A bit more context: I have several rspec files and all of them are running in parallel, I am using parallel_tests gem for that. It provides TEST_ENV_NUMBER variable, so I am using it to name tests:
caps[:name] = "job #{ENV['TEST_ENV_NUMBER']}"
So jobs are named: job , job 1, job 2... But I would be better if they were named: user, search, login...
You can get the names in the before hooks:
# rspec:
before do
p [example.description, example.full_description]
end
# cucumber:
Before do |scenario|
p [scenario.feature.name, scenario.name]
end
Related
I'm building a class-based Tic-tac-toe game with all the classes in tic_tac_toe.rb. I can load the class into irb for interactive testing with irb -r ./tic_tac_toe.rb, but I have to manually create a player and gameboard instance every time. I included p1 = Player.new int tic_tac_toe.rb but that does not seem to run.
More generally, is what I'm doing a good workflow or not? How should I go about writing some code for my class and testing it and going back? (Is there something simpler than unit testing for this small project?)
To directly address your question, you can simplify your workflow greatly with the addition of RSpec. RSpec is a BDD (behavior driven development) tool for Ruby that will let you describe your classes in an (arguably) more descriptive way than plain jane unit tests. I have included a small code sample below to help get you started.
Create a Gemfile if you do not have one for your project and add RSpec. If you've never done this check out Bundler for more information on Gemfiles.
# in your Gemfile
gem 'rspec' # rspec testing tool
gem 'require_relative' # allows you to require files with relative paths
Create a spec folder to house your specs (specs are what RSpec calls its tests).
# via Command Line (or in Windows Explorer) create a spec folder in your project
mkdir spec
Create a spec_helper.rb in the spec/ folder to house the configuration for your tests.
# in spec/spec_helper.rb
require "rspec" # require rspec testing tool
require_relative '../tic_tac_toe' # require the class to be tested
config.before(:suite) do
begin
#=> code here will run before your entire suite
#first_player = Player.new
#second_player = Player.new
ensure
end
end
Now that you've setup two players before your test suite runs, you can use these in your tests. Create a spec for your class that you would like to test and suffix it with _spec.
# in spec/player_spec.rb
require 'spec_helper' # require our setup file and rspec will setup our suite
describe Player do
before(:each) do
# runs before each test in this describe block
end
it "should have a name" do
# either of the bottom two will verify player's name is not nil, for example
#first_player.name.nil? == false
#first_player.name.should_not be_nil
end
end
Run these tests from the root of your project by using bundle exec rspec. This will look for a spec/ folder, load the spec helper, and run your specs. There is much more you can do with RSpec, such as work in Factories etc (this would be for larger projecxts). However for your project you would only need a few specs for your classes.
Other things I would suggest would be RSpec-Given, when you have a firm grasp of rspec. This gem helps DRY up your rspec tests and makes them a bit more readable.
You can also look into Guard and creating a Guardfile, which will watch your files for you and run tests when you change files.
Lastly, I included a small suggestion on a basic project structure to visualize this a bit easier.
/your_project
--- Gemfile
--- tic_tac_toe.rb
--- spec/
------- spec_helper.rb
------- player_spec.rb
I have linked all the referenced docs so if you have any questions definitely check the links out. The documentation on Bundler, RSpec, RSpec-Given, and Guard is pretty decent. Happy programming.
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!
Let me preface this by saying I am a newbie to Ruby.
I am doing an extremely basic tutorial on Ruby in RubyMine, and as part of the tutorial, we create a class in a .rb Ruby file called thing.rb. In addition to the class, the tutorial has us put an Rspec test in the same .rb file. The .rb file looks like the following:
require 'rspec'
class Thing
def value
5
end
end
describe Thing do
it "should have a value of 6" do
Thing.new.value.should eq(7)
end
end
If I right-click the project folder and "Run all specs in the project", I get errors and messages including "0 files found" and "Empty test suite." If I just run the rb script, I get no errors...the script runs fine.
The STRANGE thing is that if I add a second file to the project called thing_spec.rb and put in it only the test from above:
require 'rspec'
require_relative 'thing'
describe Thing do
it "should have a value of 6" do
Thing.new.value.should eq(7)
end
end
And then right-click the project and select "Run all specs," the tests run fine. Notice I said the tests (plural)...RubyMine will run the test in thing.rb AND the test in thing_spec.rb.
Why won't it recognize the test in thing.rb without my having to add a second file called thing_spec.rb?? This makes no sense to me. Is there anyway I could have it run the rspec tests from within thing.rb without having to create a second file?
In case it is important: I work on a Mac, have RubyMine version 4.5, using ruby interpreter 1.9.3, rspec 2.12.0.
If you go in Run > Edit Configurations...
And select All Specs in <Your Project> you'll see Filename Mask: **/*_spec.rb
This means when you tell RubyMine to run "All Specs", it only runs files which match the regex.
Now when you add second file and you do require_relative to load the other one, so both the tests run.
Is it possible to include conditional logic within an Rspec2 tag so that I can run all examples with tags less than or equal to a given value?
Something like:
rspec Dummy_spec.rb --tag version:= <=2
Obviously, this doesn't work but is there some Ruby magic that would make this work?
The reason for doing so is that I want to version my Rspec examples using tags. More specifically, I want to be able to filter all examples with a tag that is equal to or less than the tag value I specify when running the examples.
For example, if I am working on version 2 of my code but also getting a jump start on version 3, then I want to be able to just run all the examples that would be applicable to version 1 and version 2 of my code..but not version 3. (see code example below)
In anticipation of some replies, my rspec examples are in a separate project than my production code so its not a simple matter of versioning the examples with the code. But if there is a better way to handle this, I'm open to alternatives.
Full example of what I want to do:
describe "using version as tags" do
context "When I run 'rspec Dummy_spec.rb --tag version:2'"
it "should run this test applicable to ver 1", :version =>1 do
true.should eq(true)
end
it "should run this test applicable to ver 2", :version =>2 do
true.should eq(true)
end
it "should not run this test applicable to ver 3", :version =>3 do
true.should eq(true)
end
end
The Relish page for the --tag option explains that you can exclude tags via ~key:value, so you should be able to run rspec Dummy_spec.rb --tag ~version:3 to run everything but the version 3 tests.
I'm new to Ruby, and I've been trying to learn Rake, RSpec, and Cucumber. I found some code that will help me test my Rake tasks, but I'm having trouble getting it to work. I was told here: http://blog.codahale.com/2007/12/20/rake-vs-rspec-fight/ to drop this:
def describe_rake_task(task_name, filename, &block)
require "rake"
describe "Rake task #{task_name}" do
attr_reader :task
before(:all) do
#rake = Rake::Application.new
Rake.application = #rake
load filename
#task = Rake::Task[task_name]
end
after(:all) do
Rake.application = nil
end
def invoke!
for action in task.instance_eval { #actions }
instance_eval(&action)
end
end
instance_eval(&block)
end
end
into my spec_helper.rb file.
I've managed to take this code out and run it in my cucumber steps like this:
When /^I run the update_installers task$/ do
#rake = Rake::Application.new
Rake.application = #rake
load "lib/tasks/rakefile.rb"
#task = Rake::Task["update_installers"]
for action in #task.instance_eval { #actions }
instance_eval(&action)
end
instance_eval(&block)
Rake.application = nil
end
but when I try to get things working in rspec, I get the following error.
ArgumentError in 'Rake task
install_grapevine should install to
the mygrapevine directory'
wrong number of arguments (1 for 2)
/spec/spec_helper.rb: 21:in instance_eval'
/spec/spec_helper.rb: 21:inblock in invoke!'
/spec/spec_helper.rb: 20:in each'
/spec/spec_helper.rb: 20:ininvoke!'
/spec/tasks/rakefile_spec.rb:12:in `block (2 levels) in
'
Unfortunately, I've got just under a week of ruby under by belt, so the metaprogramming stuff is over my head. Could anyone point me in the right direction?
This works for me: (Rails3/ Ruby 1.9.2)
When /^the system does it's automated tasks$/ do
require "rake"
#rake = Rake::Application.new
Rake.application = #rake
Rake.application.rake_require "tasks/cron"
Rake::Task.define_task(:environment)
#rake['cron'].invoke
end
Substitute your rake task name here and also note that your require may be "lib/tasks/cron" if you don't have the lib folder in your load path.
I agree that you should only do minimal work in the Rake task and push the rest to models for ease of testing. That being said I think it's important to ensure that the code is ACTUALLY run in my cron tasks during my integration tests so I think very mild testing of the rake tasks is justified.
Since testing rake is just too much for me, I tend to move this problem around. Whenever I find myself with a long rake task that I want to test, I create a module/class in lib/ and move all the code from the task there. This leaves the task to a single line of Ruby code, that delegates to something more testable (class, module, you name it). The only thing that remains untested is whether the rake task invokes the right line of code (and passes the right parameters), but I think that is OK.
It might be useful to tell us which is the 21nd line of your spec_helper.rb. But given that the approach you posted digs deep in rake (referring to its instance variables), I would entirely abandon it for what I suggested in the previous paragraph.
I've just spent a little while getting cucumber to run a rake task so I thought I'd share my approach. Note: This is using Ruby 2.0.0 and Rake 10.0.4, but I don't think the behaviour has changed since previous versions.
There are two parts to this. The first is easy: with a properly set up instance of Rake::Application then we can access tasks on it by calling #[] (eg rake['data:import']). Once we have a task we can run it by calling #invoke and passing in the arguments (eg rake['data:import'].invoke('path/to/my/file.csv').
The second part is more awkward: properly setting up an instance of Rake::Application to work with. Once we've done require 'rake' we have access to the Rake module. It already has an application instance, available from Rake.application, but it's not yet set up — it doesn't know about any of our rake tasks. It does, however, know where to find our Rakefile, assuming we've used one of the standard file names: rakefile, Rakefile, rakefile.rb or Rakefile.rb.
To load the rakefile we just need to call #load_rakefile on the application, but before we can do that we need to call #handle_options. The call to #handle_options populates options.rakelib with a default value. If options.rakelib is not set then the #load_rakefile method will blow up, as it expects options.rakelib to be enumerable.
Here's the helper I've ended up with:
module RakeHelper
def run_rake_task(task_name, *args)
rake_application[task_name].invoke(*args)
end
def rake_application
require 'rake'
#rake_application ||= Rake.application.tap do |app|
app.handle_options
app.load_rakefile
end
end
end
World(RakeHelper)
Pop that code into a file in features/support/ and then just use run_rake_task in your steps, eg:
When /^I import data from a CSV$/ do
run_rake_task 'data:import', 'path/to/my/file.csv'
end
The behavior might have changed since the correct answer was posted. I was experiencing problems executing two scenarios that needed to run the same rake task (only one was being executed despite me using .execute instead of .invoke). I thought to share my approach to solve the issue (Rails 4.2.5 and Ruby 2.3.0).
I tagged all the scenarios that require rake with #rake and I defined a hook to setup rake only once.
# hooks.rb
Before('#rake') do |scenario|
unless $rake
require 'rake'
Rake.application.rake_require "tasks/daily_digest"
# and require other tasks
Rake::Task.define_task(:environment)
$rake = Rake::Task
end
end
(Using a global variable is suggested here: https://github.com/cucumber/cucumber/wiki/Hooks#running-a-before-hook-only-once)
In the step definition I simply called $rake
# step definition
Then(/^the daily digest task is run$/) do
$rake['collector:daily_digest'].execute
end
Any feedback is welcome.