You can do this a few different ways
Kernel.system "command"
%x[command]
`command`
Question
I am doing iOS testing using Frank. It is a ruby gem that uses Cucumber as well. I have a "Given" step that checks whether the app is running or if it has crashed. If my step finds that it has crashed I would like to launch the app again. I launch the app using a shell script which is stored somewhere near the cucumber .feature files.
How can I call a script from that step definition?
Solution
You can do this a few different ways
Kernel.system "command"
%x[command]
`command`
OTHER TIPS
As other answers suggested, there are many ways of executing shell scripts from Ruby, but they're all not created equal. I'll try to explain all methods i know in more detail.
`command arg1 arg2`
%x(command arg1 arg2)
Runs the command in a subshell and returns the output of the command. The command and its arguments are provided as a string delimited by backticks. An alternative syntax is %x(...)
which serves to avoid escaping issues, e.g. when you want to execute a command that contains backticks itself. The parentheses can be replaced by other delimiters such as []
, {}
, !!
, … in order to be able to work around just about any escaping issue.
Stderr is printed as normal, Stdout is suppressed. Returns the stdout output of the command. This means you can use the backtick notation to get the output of a command into a variable for further processing.
exec("command arg1 arg2")
exec("command", "arg1", "arg2")
Replaces the current process by running the command. The command and its arguments are provided as a normal string or as a comma delimited list of strings. Can be useful if you already have a list of arguments as an array. Output is left as is, i.e. will be printed to the console as if the command was run directly.
system("command arg1 arg2")
system("command","arg1 arg2")
Like Kernel.exec
but runs in a subshell again. Returns true
if the process exited correctly (status 0), false
otherwise. This works great inside if
-statements.
pid = spawn("command")
# do other stuff
Process.wait(pid)
Similar to Kernel.system
but will spawn a child process to run the specified command. The parent process will thus not wait for the command to finish executing unless Process.wait
is used. The return value is the PID of the spawned process.
io = IO.popen("command")
IO.popen("command") {|io| ... }
Runs the command in a child process again but allows for greater control over the IO. The child processes' stdout and stdin are connected to an IO object that is either accessible as the return value or a block parameter. If obtained via return value, the IO object should be closed after using it with io.close
.
For use-cases more advanced than system
or IO.popen
, you can use Open3 from the Ruby standard library. Its popen3
method lets you manually interact with the stdin, stdout, and stderr of the child process. Open3’s popen2
method is the same except it doesn’t give you stderr. An example of using popen2
:
require 'open3'
Open3.popen2("wc -c") do |stdin, stdout, status_thread|
stdin.print "answer to life the universe and everything"
stdin.close
p stdout.gets #=> "42\n"
end
Here are some nice ways. Backticks are probably the least intrusive. But beware: as pointed out by tadman, exec
terminates the calling process, which can be averted by creating a child process or using system
.