So, I am trying to run the test but I am getting an error says.
Aruba::LaunchError:Command "seedly-calculator.rb" not found in PATH-variable
-seedly-calculator
-bin
-src
-seedly-calculator.rb
I have tried to change the path in rake file but it doesn't work.
My seedly-calculator.rb file is in the root directory.
require "rspec/core/rake_task"
namespace :spec do
desc "Run the functional suite against the CLI"
RSpec::Core::RakeTask.new(:functional, [] => [:set_path])
task :set_path do
project_bin_dir = File.join(File.dirname(File.expand_path(__FILE__)), '..', 'bin')
ENV['PATH'] = project_bin_dir + ':'+ ENV['PATH']
end
end
it shows error like:
Failure/Error: let(:command) { run "seedly-calculator.rb" }
Aruba::LaunchError:
Command "seedly-calculator.rb" not found in PATH-variable "/Users/bilaltariq/Desktop/seedly-calculator/functional_spec/bin:/Users/bilaltariq/Desktop/seedly-calculator/functional_spec/exe:/Users/bilaltariq/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/bin:/Users/bilaltariq/Desktop/seedly-calculator/functional_spec/../bin:/Users/bilaltariq/.rbenv/versions/2.6.2/bin:/usr/local/Cellar/rbenv/1.1.1/libexec:/Users/bilaltariq/.rbenv/shims:/Users/bilaltariq/.asdf/shims:/Users/bilaltariq/.asdf/bin:/usr/local/bin:/Users/bilaltariq/.bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/MacGPG2/bin".
I expect it to hit the file so i can write some test.
am i doing something wrong?
require 'spec_helper'
RSpec.describe 'Command Validation', type: :aruba do
let(:command) { run "seedly-calculator.rb" }
it "wrong/missing arguments" do
command.write("lookup\n")
stop_all_commands
expect(command.output).to end_with("Missing bank_name argument.\n")
end
end
seedly-calculator.rb:
#!/usr/bin/env ruby
# Complete bin/setup so that after it is
# run, ruby seedly-calculator.rb can be used to launch
# it.
# frozen_string_literal: true
require_relative './src/runner'
if !ARGV.length.zero?
input = ARGV
Runner.new.send('process_input', input)
else
puts "Arguments required!."
end
Update
To run a ruby script using run you need to make sure your ruby script is executable and contains a shebang so your system knows to run it with ruby. Here's example from this starter example
#!/usr/bin/env ruby
file = ARGV[0]
if file.nil? || file.empty?
abort "aruba-test-cli [file]: Filename is missing"
elsif !File.exist? file
abort "aruba-test-cli [file]: File does not exist"
end
puts File.read(file).chomp
So in your case you'll need to add this to the first line of your seedly-calculator.rb file
#!/usr/bin/env ruby
Then run this from command line to make it executable.
chmod +x #!/usr/bin/env ruby
I made a simple example forked off the one I reffed above. See this commit
Rspec convention is that it should match the same file structure of your project. It is not a good idea to set PATH manually.
Rake tasks are normally put in a tasks folder so you should have in project root a tasks folder
my_project/tasks/something.rake
Then you should have a spec folder that matches
my_project/spec/tasks/something_spec.rb
Then you should be able to get rid of task :set_path do end block and just run the spec without that.
You should also have a Gemfile to load your gems, run bundle install then invoke your test with
bundle exec rspec spec/tasks/sometask_spec.rb
Related
I have a Ruby project with a UNIX executable file called parse located in a bin subfolder in my project root directory.
At the moment it's just this:
#!/usr/bin/env ruby
# frozen_string_literal: true
puts 'hello world'
The file can be executed on the command line when this command is run from the project root directory: bin/parse
It works fine, but I also want to write a passing Rspec test for it.
I have this spec file:
RSpec.describe "end-to-end application behaviour" do
subject { system('bin/parse') }
it 'prints the expected messsage to stdout' do
expect { subject }.to output(
'hello world'
).to_stdout
end
end
When I run it I get the test failure:
expected block to output "hello world" to stdout, but output nothing
This is the location of my spec file relative to my project root: spec/integration/parse_spec.rb
I tried placing require and require_relative statements in that spec file with the paths to the parse executable, in case that would help, but I just kept getting:
LoadError: cannot load such file
Does anyone know how I can write a test in that file that will pass and prove the parse executable behaviour works?
Don't Use the RSpec Output Matcher
RSpec has a built-in output matcher than can test both where output goes, as well as its contents. However, it's testing where your Ruby output goes, not whether some external application is using standard input or standard error. You're going to have to make some different assumptions about your code.
You can avoid driving yourself nuts by comparing strings rather than testing the underlying shell or your output streams. For example, consider:
RSpec.describe "parse utility output" do
it "prints the right string on standard output" do
expect(`echo hello world`).to start_with("hello world")
end
it "shows nothing on standard output when it prints to stderr" do
expect(`echo foo >&2 > /dev/null`).to be_empty
end
end
Just replace the echo statements with the correct invocation of parse for your system, perhaps by setting PATH directly in your shell, using a utility like direnv, or by modifying ENV["PATH"] in your spec or spec_helper.
As a rule of thumb, RSpec isn't really meant for testing command-line applications. If you want to do that, consider using the Aruba framework to exercise your command-line applications. It's best to use RSpec to test the results of methods or the output of commands, rather than trying to test basic functionality. Of course, your mileage may vary.
Use to_stdout_from_any_process instead of to_stdout:
expect { subject }.to output('hello world').to_stdout_from_any_process
This question already has answers here:
Ruby: how to "require" a file from the current working dir?
(5 answers)
Closed 6 years ago.
I have create a Ruby class Worker, file name is Worker.rb:
class Worker
def initialize
...
end
def doTask(task_name)
...
end
end
Then, I created another Ruby script file, named run.rb (it requires Worker):
require 'Worker'
worker = Worker.new
worker.doTask("sort")
Both two ruby files are located directly under the project folder:
ProjectFolder/
-- Worker.rb
-- run.rb
I run the run.rb under project folder by command:
ruby run.rb
But get following error:
/Users/John/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- Worker (LoadError)
from /Users/John/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from runme.rb:1:in `<main>'
Why?
I figured out after checking #Geo 's github project, I should use:
require_relative "worker"
require looks for the required file from the so called load path and not the current directory. Since the syntax for looking in the current directory was awkward Ruby 1.9 introduces require_relative, which looks in the current directory.
Change your code like this:
require_relative "Worker"
instead of
require "Worker"
The reason this does not work is because the current directory is not part of ruby's default load path.
If you run the following command, you will see what the current load path is and it will confirm that the current directory is not part of that path.
ruby -e 'puts $LOAD_PATH'
This should answer your primary question as to why the required file was not loaded.
As for a solution, require_relative will work and is probably the best solution in this case.
There are however still cases were inserting directories into the load path is helpful, if not required. For example say you have a script that can be run anywhere in the file system and you want the flexibility to require a particular version of your co-worker's foo class.
/afs/some_cell/u/john/some_ruby_lib
prod/
foo.rb
bar.rb
prev/
foo.rb
bar.rb
beta/
foo.rb
bar.rb
In a case like this either setting the RUBYSIM var (maybe in a wrapper) or setting the proper include path on the ruby command line can be a useful solution.
Again, your co-worker has not published this as a gem, he is just providing a shared directory.
There are several ways you can insert directories into the load path when it is appropriate, as demonstrated below:
You can use the -I command line flag
ruby -I some_path -e 'puts $LOAD_PATH'
You can set the RUBYLIB env var to include your current directory.
on unix/linix/osx
export RUBYLIB=some_path
on windows
set RUBYLIB=some_path
Currently, I'm running all selenium scripts in my test suite (written by Selenium Ruby Webdriver) at one time by using rake gem in "Start Command Prompt with Ruby" terminal.
To do this I have to create a file with name "rakefile.rb" with below content and just call "rake" in my terminal: (I have known this knowledge based on the guide of a person in my previous post how to export results when running selenium ruby webdriver scripts to output files from command prompt ruby window).
task :default do
$stdout = File.new('console.out', 'w')
$stdout.sync = true
FileList['test*.rb'].each { |file|
begin
ruby file
rescue
puts "The following tests reported unexpected behavior:"
puts "#{file} \n"
end
}
end
However, I do not know how to modify "rakefile.rb" to be able to export the content of executing each failed tests (that being displayed on my Terminal) to each output file ? It means that I expect the content of executing each my script will be written to output files instead of displaying on my Ruby terminal (ex: when I'm running the test script "test_GI-1.rb", then the content of executing this script will be written to an output file "test_GI-1.rb.out" instead of showing in my Terminal.
I modified my "rakefile.rb" to something like ruby file >> test.rb.out, but it does not work at all (this thing only works when I type directly the thing like ruby test.rb >> output.out on my Ruby Terminal). Anybody please guide me a way. Thanks so much.
I have not tried this out, but I guess this should work
task :default do
FileList['test*.rb'].each { |file|
begin
system("ruby #{file} > #{file}.log")
rescue
puts "The following tests reported unexpected behavior:"
puts "#{file} \n"
end
}
end
Based on new requirements -
UPDATE
task :default do
logfile.new("console.out", "w")
FileList['test*.rb'].each { |file|
begin
system("ruby #{file} > #{file}.log")
rescue
logfile.puts("The following tests reported unexpected behavior:")
logfile.puts("#{file} \n")
end
}
end
I have a 2 scripts:
test1.rb
require 'test2.rb'
puts "hello"
test2.rb
puts "test"
I'm running this by executing ruby test2.rb test1.rb.
But only test is printed out and not hello.
You only need to run ruby test1.rb and the require statement should pull in test2.rb for you - you don't need to put it on the command line as well. (That will try and run test2.rb, passing the string 'test1.rb' as an argument, which is not what you want here)
Edit: the require statement does not look in the current directory by default when trying to find 'test2.rb'. You can explicitly specify it by changing it to:
require File.dirname(__FILE__) + '/test2.rb'
in test1.rb do (assuming test2.rb is in same directory, otherwise give its path relative to test1.rb)
require_relative 'test2.rb'
puts "hello"
and on the command line just do ruby test1.rb
This should work as well
require './test2.rb'
puts "hello"
There are some explanation how you can solve your problem, but not what is going wrong.
With ruby test2.rb test1.rb you call the ruby script with the parameter test1.rb.
You have access to the parameters in the constant ARGV.
An example with this script:
puts "test"
puts 'ARGV= %s' % ARGV
The result when you call it:
C:\Temp>ruby test.rb test2.rb
test
ARGV= test2.rb
So you could also write a program like:
require_relative ARGV.first
The first parameter defines a script to be loaded.
Or if you want to load many scripts you could use:
ARGV.each{|script| require_relative script }
I'm trying to create an application that will primarily consist of ruby scripts that will be run from the command-line (cron, specifically). I want to have a libs folder, so I can put encapsulated, reusable classes/modules in there, and be able to access them from any script.
I want to be able to put my scripts into a "bin" folder.
What is the best way to give them access to the libs folder? I know I can add to the load path via command-line argument, or at the top of each command-line script. In PHP, it sometimes made more sense to create a custom .ini file and point the cli to the ini file, so you got them all in one pop.
Anything similar for ruby? Based on your experience, what's the best way to go here?
At the top of each bin/executable, you can put this at the top
#!/usr/bin/env ruby
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')
require 'libfile'
[etc.]
Were you looking for something different?
If you turn your application into a Ruby gem and install the gem on your system, you don't even need to put this stuff at the top. The require statement would suffice in that case.
Sean,
There is no way to not have to require a library, that I know of. I guess if you want to personalize your Ruby so much you could "roll your own" using eval.
The script below basically works as the interpreter. You can add your own functions and include libraries. Give the file executable permissions and put it in /usr/bin if you really want. Then just use
$ myruby <source>
Here's the code for a very minimal one. As an example I've included the md5 digest library and created a custom function called md5()
#!/usr/bin/ruby -w
require 'digest/md5';
def executeCode(file)
handle = File.open(file,'r');
for line in handle.readlines()
line = line.strip();
begin
eval(line);
rescue Exception => e
print "Problem with script '" + file + "'\n";
print e + "\n";
end
end
end
def checkFile(file)
if !File.exists?(file)
print "No such source file '" + file + "'\n";
exit(1);
elsif !File.readable?(file)
print "Cannot read from source file '" + file + "'\n";
exit(1);
else
executeCode(file);
end
end
# My custom function for our "interpreter"
def md5(key=nil)
if key.nil?
raise "md5 requires 1 parameter, 0 given!\n";
else
return Digest::MD5.hexdigest(key)
end
end
if ARGV[0].nil?
print "No input file specified!\n"
exit(1);
else
checkFile(ARGV[0]);
end
Save that as myruby or myruby.rb and give it executable permissions (755). Now you're ready to create a normal ruby source file
puts "I will now generate a md5 digest for mypass using the md5() function"
puts md5('mypass')
Save that and run it as you would a normal ruby script but with our new interpreter. You'll notice I didn't need to include any libraries or write the function in the source code because it's all defined in our interpreter.
It's probably not the most ideal method, but it's the only one I can come up with.
Cheers
There is a RUBYLIB environment variable that can be set to any folder on the system
If you want to use your classes/modules globally, why not just move them to your main Ruby lib directory? eg: /usr/lib/ruby/1.8/ ?
Eg:
$ cat > /usr/lib/ruby/1.8/mymodule.rb
module HelloWorld
def hello
puts("Hello, World!");
end
end
We have our module in the main lib directory - should be able to
require it from anywhere in the system now.
$ irb
irb(main):001:0> require 'mymodule'
=> true
irb(main):002:0> include HelloWorld
=> Object
irb(main):003:0> hello
Hello, World!
=> nil