Cucumber/Aruba Thor: testing multiple commands in a single scenario, first passes and second fails - ruby

I'm trying to write a small ruby gem that does some template generating, using Bundler and Thor. I'm writing the tests in Cucumber and Aruba, and I'm having trouble getting them to pass.
I have the following Thor CLI class defined in the app:
require 'thor'
require 'sleipnir'
require 'sleipnir/generators/layout'
require 'sleipnir/generators/app'
module Sleipnir
class CLI < Thor
desc "app", "Generates an app directory and copies the appropriate files"
def app(app_name)
Sleipnir::Generators::App.start([app_name])
end
desc "layout", "Generates specific layout based on template type"
def layout(template_type)
Sleipnir::Generators::Layout.start([template_type])
end
end
end
This is the app.rb file:
require 'thor/group'
module Sleipnir
module Generators
class App < Thor::Group
include Thor::Actions
argument :app_name, :type => :string
class_option :template_type, :default => :erb, :required => true
def self.source_root
File.dirname(__FILE__)
end
def create_app_dir
empty_directory(app_name)
end
def copy_app_scaffold
directory("app", app_name)
end
end
end
end
And the layout.rb file:
require 'thor/group'
module Sleipnir
module Generators
class Layout < Thor::Group
include Thor::Actions
class_option :template_type, :default => :erb, :required => true
def self.source_root
File.dirname(__FILE__) + "/template"
end
def copy_layout
template_type = options[:template_type]
template("layout_template.#{template_type}", "views/layout.#{template_type}")
end
end
end
end
I have a cucumber test written for the app method, and it passes. However, the layout method is failing. Here is the test:
Feature: Generate
In order to generate templates
As a CLI
I want to run the generator
Scenario: Layout
When I run `sleipnir app test_app`
Then the following directories should exist:
| test_app/views |
When I run `sleipnir layout --template_type "erb"`
Then the following files should exist:
| test_app/views/layout.erb |
The first part of the test passes just fine (i.e. the directory is created), but the part about verifying the file exists fails. I've checked the file structure, and the layout_template.erb file exists, so I can't figure out why it isn't be templated properly.

Unfortunately, Aruba does not support this: https://github.com/cucumber/aruba/issues/140.
But writing your own step definition isn't bad, just have that you want to execute first happen before the command you pass in. See https://github.com/cucumber/cucumber/wiki/Step-Definitions for examples.

Related

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.

'Error: Cannot open "/home/<...>/billy-bones/=" for reading' while using pry and DataMapper

So, I'm trying to build a quick console program for my development needs, akin to rails console (I'm using Sinatra + DataMapper + pry).
I run it and launch cat = Category.new(name: 'TestCat', type: :referential). It gives me the following error:
Error: Cannot open "/home/art-solopov/Projects/by-language/Ruby/billy-bones/=" for reading.
What could be the cause of the problem?
console:
#!/usr/bin/env ruby
$LOAD_PATH << 'lib'
require 'pry'
require 'config'
binding.pry
lib/config.rb:
# Configuration files and app-wide requires go here
require 'sinatra'
require 'data_mapper'
require 'model/bill'
require 'model/category'
configure :production do
DataMapper::Logger.new('db-log', :debug)
DataMapper.setup(:default,
'postgres://billy-bones:billy#localhost/billy-bones')
DataMapper.finalize
end
configure :development do
DataMapper::Logger.new($stderr, :debug)
DataMapper.setup(:default,
'postgres://billy-bones:billy#localhost/billy-bones-dev')
DataMapper.finalize
DataMapper.auto_upgrade!
end
configure :test do
require 'dm_migrations'
DataMapper::Logger.new($stderr, :debug)
DataMapper.setup(:default,
'postgres://billy-bones:billy#localhost/billy-bones-test')
DataMapper.finalize
DataMapper.auto_migrate!
end
lib/model/category.rb:
require 'data_mapper'
class Category
include DataMapper::Resource
property :id, Serial
property :name, String
property :type, Enum[:referential, :predefined, :computable]
has n, :bills
# has n, :tariffs TODO uncomment when tariff ready
def create_bill(params)
# A bill factory for current category type
case type
when :referential
ReferentialBill.new params
when :predefined
PredefinedBill.new params
when :computable
ComputableBill.new params
end
end
end
If I substitute pry with irb in the console script, it goes fine.
Thank you very much!
P. S.
Okay, yesterday I tried this script again, and it worked perfectly. I didn't change anything. I'm not sure whether I should remove the question now or not.
P. P. S.
Or actually not... Today I've encountered it again. Still completely oblivious to what could cause it.
** SOLVED **
DAMN YOU PRY!
Okay, so here's the difference.
When I tested it the second time, I actually entered a = Category.new(name: 'TestCat', type: :referential) and it worked. Looks like pry just thinks cat is a Unix command, not a valid variable name.
Not answer to the pry question I just generally hate case statements in ruby.
Why not change:
def create_bill(params)
# A bill factory for current category type
case type
when :referential
ReferentialBill.new params
when :predefined
PredefinedBill.new params
when :computable
ComputableBill.new params
end
end
to:
def create_bill(params)
# A bill factory for current category type
self.send("new_#{type}_bill",params)
end
def new_referential_bill(params)
ReferentialBill.new params
end
def new_predefined_bill(params)
PredefinedBill.new params
end
def new_computable_bill(params)
ComputableBill.new params
end
You could make this more dynamic but I think that would take away from readability in this case but if you'd like in rails this should do the trick
def create_bill(params)
if [:referential, :predefined, :computable].include?(type)
"#{type}_bill".classify.constantize.new(params)
else
#Some Kind of Handling for non Defined Bill Types
end
end
Or this will work inside or outside rails
def create_bill(params)
if [:referential, :predefined, :computable].include?(type)
Object.const_get("#{type.to_s.capitalize}Bill").new(params)
else
#Some Kind of Handling for non Defined Bill Types
end
end

uninitialized constant BikeShare (NameError)

I'm trying to implement some simple testing in rspec for a gem I'm writing. When I comment out describe BikeShare do down to end and run the file, the file loads in and runs successfully. I'm sure it's something tiny I'm missing.
My test file is really simple and looks like this:
require 'spec_helper'
describe BikeShare do
it "should run" do
# response = BikeShare.new
# response.should_be present
end
end
When run, I get the error uninitialized constant BikeShare (NameError) at line 3.
My bikeshare.rb file looks like this, fairly simple:
class BikeShare
def initialize
response = JSON.parse(open("http://bayareabikeshare.com/stations/json").read)
#response = response["stationBeanList"]
end
def get_last_station
#response.last["id"]
end
end
My Rakefile looks like this:
require 'rubygems'
require 'bundler'
Bundler.setup
Bundler::GemHelper.install_tasks
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new do |spec|
# spec.libs << 'lib' << 'spec'
spec.pattern = 'spec/*_spec.rb'
end
task :default => :spec
Your tests arent aware of BikeShare.
You need to require the file that defines your BikeShare class. I dont use rspec but I think that you normally set up your testing environment in spec_helper.rb.

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

A rake task by .rake file

I have the following Rakefile in a Ruby 1.9.3 project:
require 'rake/testtask'
require 'json'
Rake::TestTask.new do |t|
t.pattern = "spec/**/*_spec.rb"
t.verbose = true
end
task :default => :test
namespace :omglol do
namespace :file_a do
task :foo do
# do some stuff
end
end
namespace :file_b do
task :bar do
# do some stuff
end
end
end
As you can see, the first part of this file allow to run tests, just using rake command. And the second part contains some tasks.
Actually, I have a lot of tasks inside omglol:file_a and omglol:file_b namespaces. That's why I would like to move each of them inside a file, for instance tasks/omglol/file_a.rake and tasks/omglol/file_b.rake.
Is there a best way to do so? Thanks.
Yes. Simply move the logic into the appropriate files and then require them.
Example Rakefile:
require 'rake/testtask'
require 'json'
require 'lib/tasks/omglol/file_a.rake' # <= contains your subtasks
Rake::TestTask.new do |t|
t.pattern = "spec/**/*_spec.rb"
t.verbose = true
end
task :default => :test
Then in lib/tasks/omglol/file_a.rake simply define your tasks as normal:
namespace :omglol do
namespace :file_a do
task :foo do
# do some stuff
end
end
end
The pattern would be the same for file_b.rake.

Resources